diff --git a/build/libifm.php b/build/libifm.php index ce0e721..e6548e2 100644 --- a/build/libifm.php +++ b/build/libifm.php @@ -1549,7 +1549,7 @@ function IFM( params ) { item.download.action = "download"; item.download.icon = "icon icon-download"; } - if( item.icon.indexOf( 'file-image' ) !== -1 && self.config.isDocroot ) { + if( item.icon.indexOf( 'file-image' ) !== -1 ) { item.tooltip = 'data-toggle="tooltip"'; } if( self.config.extract && self.inArray( item.ext, ["zip","tar","tgz","tar.gz","tar.xz","tar.bz2"] ) ) { @@ -1668,7 +1668,10 @@ function IFM( params ) { title: function() { var item = self.fileCache.find( x => x.guid == $(this).attr('id') ); var tooltip = document.createElement( 'img' ); - tooltip.src = encodeURI( self.pathCombine( self.currentDir, item.name ) ).replace( '#', '%23' ).replace( '?', '%3F' ); + if( self.config.isDocroot ) + tooltip.src = encodeURI( self.pathCombine( self.currentDir, item.name ) ).replace( '#', '%23' ).replace( '?', '%3F' ); + else + tooltip.src = self.api + "?api=proxy&dir=" + encodeURIComponent( self.currentDir ) + "&filename=" + encodeURIComponent( item.name ); tooltip.classList.add( 'imgpreview' ); return tooltip; }, @@ -3279,6 +3282,7 @@ function IFM( params ) { case "searchItems": $this->searchItems( $_REQUEST ); break; case "getFolderTree": $this->getFolderTree( $_REQUEST ); break; case "createArchive": $this->createArchive( $_REQUEST ); break; + case "proxy": $this->downloadFile( $_REQUEST, false ); break; default: $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid api action given" ) ); break; @@ -3657,7 +3661,7 @@ function IFM( params ) { } // provides a file for downloading - private function downloadFile( array $d ) { + private function downloadFile( array $d, $forceDL=true ) { if( $this->config['download'] != 1 ) $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) ); elseif( $this->config['showhtdocs'] != 1 && ( substr( $d['filename'], 0, 3 ) == ".ht" || substr( $d['filename'],0,3 ) == ".ht" ) ) @@ -3666,7 +3670,10 @@ function IFM( params ) { $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) ); else { $this->chDirIfNecessary( $d["dir"] ); - $this->fileDownload( $d['filename'] ); + if( ! is_file( $d['filename' ] ) ) + http_response_code( 404 ); + else + $this->fileDownload( array( "file" => $d['filename'], "forceDL" => $forceDL ) ); } } @@ -3793,7 +3800,7 @@ function IFM( params ) { else $d['filename'] = basename( getcwd() ); } - $this->fileDownload( $dfile, $d['filename'] . ".zip" ); + $this->fileDownload( array( "file" => $dfile, "name" => $d['filename'] . ".zip" ) ); } catch ( Exception $e ) { echo $this->l['error'] . " " . $e->getMessage(); } finally { @@ -4236,16 +4243,24 @@ function IFM( params ) { else return true; } - private function fileDownload( $file, $name="" ) { + private function fileDownload( array $options ) { + if( $options['forceDL'] ) + $content_type = "application/octet-stream"; + else + $content_type = mime_content_type( $options['file'] ); + + if( ! isset( $options['name'] ) || trim( $options['name'] ) == "" ) + $options['name'] = basename( $options['file'] ); + header( 'Content-Description: File Transfer' ); - header( 'Content-Type: application/octet-stream' ); - header( 'Content-Disposition: attachment; filename="' . ( trim( $name ) == "" ? basename( $file ) : $name ) . '"' ); + header( 'Content-Type: ' . $content_type ); + header( 'Content-Disposition: attachment; filename="' . $options['name'] . '"' ); header( 'Expires: 0' ); header( 'Cache-Control: must-revalidate' ); header( 'Pragma: public' ); - header( 'Content-Length: ' . filesize( $file ) ); + header( 'Content-Length: ' . filesize( $options['file'] ) ); - $file_stream = fopen( $file, 'rb' ); + $file_stream = fopen( $options['file'], 'rb' ); $stdout_stream = fopen('php://output', 'wb'); stream_copy_to_stream($file_stream, $stdout_stream); diff --git a/ifm.php b/ifm.php index ca5ad2a..bd0194c 100644 --- a/ifm.php +++ b/ifm.php @@ -1549,7 +1549,7 @@ function IFM( params ) { item.download.action = "download"; item.download.icon = "icon icon-download"; } - if( item.icon.indexOf( 'file-image' ) !== -1 && self.config.isDocroot ) { + if( item.icon.indexOf( 'file-image' ) !== -1 ) { item.tooltip = 'data-toggle="tooltip"'; } if( self.config.extract && self.inArray( item.ext, ["zip","tar","tgz","tar.gz","tar.xz","tar.bz2"] ) ) { @@ -1668,7 +1668,10 @@ function IFM( params ) { title: function() { var item = self.fileCache.find( x => x.guid == $(this).attr('id') ); var tooltip = document.createElement( 'img' ); - tooltip.src = encodeURI( self.pathCombine( self.currentDir, item.name ) ).replace( '#', '%23' ).replace( '?', '%3F' ); + if( self.config.isDocroot ) + tooltip.src = encodeURI( self.pathCombine( self.currentDir, item.name ) ).replace( '#', '%23' ).replace( '?', '%3F' ); + else + tooltip.src = self.api + "?api=proxy&dir=" + encodeURIComponent( self.currentDir ) + "&filename=" + encodeURIComponent( item.name ); tooltip.classList.add( 'imgpreview' ); return tooltip; }, @@ -3279,6 +3282,7 @@ function IFM( params ) { case "searchItems": $this->searchItems( $_REQUEST ); break; case "getFolderTree": $this->getFolderTree( $_REQUEST ); break; case "createArchive": $this->createArchive( $_REQUEST ); break; + case "proxy": $this->downloadFile( $_REQUEST, false ); break; default: $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid api action given" ) ); break; @@ -3657,7 +3661,7 @@ function IFM( params ) { } // provides a file for downloading - private function downloadFile( array $d ) { + private function downloadFile( array $d, $forceDL=true ) { if( $this->config['download'] != 1 ) $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) ); elseif( $this->config['showhtdocs'] != 1 && ( substr( $d['filename'], 0, 3 ) == ".ht" || substr( $d['filename'],0,3 ) == ".ht" ) ) @@ -3666,7 +3670,10 @@ function IFM( params ) { $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) ); else { $this->chDirIfNecessary( $d["dir"] ); - $this->fileDownload( $d['filename'] ); + if( ! is_file( $d['filename' ] ) ) + http_response_code( 404 ); + else + $this->fileDownload( array( "file" => $d['filename'], "forceDL" => $forceDL ) ); } } @@ -3793,7 +3800,7 @@ function IFM( params ) { else $d['filename'] = basename( getcwd() ); } - $this->fileDownload( $dfile, $d['filename'] . ".zip" ); + $this->fileDownload( array( "file" => $dfile, "name" => $d['filename'] . ".zip" ) ); } catch ( Exception $e ) { echo $this->l['error'] . " " . $e->getMessage(); } finally { @@ -4236,16 +4243,24 @@ function IFM( params ) { else return true; } - private function fileDownload( $file, $name="" ) { + private function fileDownload( array $options ) { + if( $options['forceDL'] ) + $content_type = "application/octet-stream"; + else + $content_type = mime_content_type( $options['file'] ); + + if( ! isset( $options['name'] ) || trim( $options['name'] ) == "" ) + $options['name'] = basename( $options['file'] ); + header( 'Content-Description: File Transfer' ); - header( 'Content-Type: application/octet-stream' ); - header( 'Content-Disposition: attachment; filename="' . ( trim( $name ) == "" ? basename( $file ) : $name ) . '"' ); + header( 'Content-Type: ' . $content_type ); + header( 'Content-Disposition: attachment; filename="' . $options['name'] . '"' ); header( 'Expires: 0' ); header( 'Cache-Control: must-revalidate' ); header( 'Pragma: public' ); - header( 'Content-Length: ' . filesize( $file ) ); + header( 'Content-Length: ' . filesize( $options['file'] ) ); - $file_stream = fopen( $file, 'rb' ); + $file_stream = fopen( $options['file'], 'rb' ); $stdout_stream = fopen('php://output', 'wb'); stream_copy_to_stream($file_stream, $stdout_stream); diff --git a/src/ifm.js b/src/ifm.js index 7c20bc9..59e3a19 100644 --- a/src/ifm.js +++ b/src/ifm.js @@ -135,7 +135,7 @@ function IFM( params ) { item.download.action = "download"; item.download.icon = "icon icon-download"; } - if( item.icon.indexOf( 'file-image' ) !== -1 && self.config.isDocroot ) { + if( item.icon.indexOf( 'file-image' ) !== -1 ) { item.tooltip = 'data-toggle="tooltip"'; } if( self.config.extract && self.inArray( item.ext, ["zip","tar","tgz","tar.gz","tar.xz","tar.bz2"] ) ) { @@ -254,7 +254,10 @@ function IFM( params ) { title: function() { var item = self.fileCache.find( x => x.guid == $(this).attr('id') ); var tooltip = document.createElement( 'img' ); - tooltip.src = encodeURI( self.pathCombine( self.currentDir, item.name ) ).replace( '#', '%23' ).replace( '?', '%3F' ); + if( self.config.isDocroot ) + tooltip.src = encodeURI( self.pathCombine( self.currentDir, item.name ) ).replace( '#', '%23' ).replace( '?', '%3F' ); + else + tooltip.src = self.api + "?api=proxy&dir=" + encodeURIComponent( self.currentDir ) + "&filename=" + encodeURIComponent( item.name ); tooltip.classList.add( 'imgpreview' ); return tooltip; }, diff --git a/src/main.php b/src/main.php index ec2ebe2..a5dd15e 100644 --- a/src/main.php +++ b/src/main.php @@ -271,6 +271,7 @@ f00bar; case "searchItems": $this->searchItems( $_REQUEST ); break; case "getFolderTree": $this->getFolderTree( $_REQUEST ); break; case "createArchive": $this->createArchive( $_REQUEST ); break; + case "proxy": $this->downloadFile( $_REQUEST, false ); break; default: $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid api action given" ) ); break; @@ -649,7 +650,7 @@ f00bar; } // provides a file for downloading - private function downloadFile( array $d ) { + private function downloadFile( array $d, $forceDL=true ) { if( $this->config['download'] != 1 ) $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) ); elseif( $this->config['showhtdocs'] != 1 && ( substr( $d['filename'], 0, 3 ) == ".ht" || substr( $d['filename'],0,3 ) == ".ht" ) ) @@ -658,7 +659,10 @@ f00bar; $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) ); else { $this->chDirIfNecessary( $d["dir"] ); - $this->fileDownload( $d['filename'] ); + if( ! is_file( $d['filename' ] ) ) + http_response_code( 404 ); + else + $this->fileDownload( array( "file" => $d['filename'], "forceDL" => $forceDL ) ); } } @@ -785,7 +789,7 @@ f00bar; else $d['filename'] = basename( getcwd() ); } - $this->fileDownload( $dfile, $d['filename'] . ".zip" ); + $this->fileDownload( array( "file" => $dfile, "name" => $d['filename'] . ".zip" ) ); } catch ( Exception $e ) { echo $this->l['error'] . " " . $e->getMessage(); } finally { @@ -1228,16 +1232,24 @@ f00bar; else return true; } - private function fileDownload( $file, $name="" ) { + private function fileDownload( array $options ) { + if( $options['forceDL'] ) + $content_type = "application/octet-stream"; + else + $content_type = mime_content_type( $options['file'] ); + + if( ! isset( $options['name'] ) || trim( $options['name'] ) == "" ) + $options['name'] = basename( $options['file'] ); + header( 'Content-Description: File Transfer' ); - header( 'Content-Type: application/octet-stream' ); - header( 'Content-Disposition: attachment; filename="' . ( trim( $name ) == "" ? basename( $file ) : $name ) . '"' ); + header( 'Content-Type: ' . $content_type ); + header( 'Content-Disposition: attachment; filename="' . $options['name'] . '"' ); header( 'Expires: 0' ); header( 'Cache-Control: must-revalidate' ); header( 'Pragma: public' ); - header( 'Content-Length: ' . filesize( $file ) ); + header( 'Content-Length: ' . filesize( $options['file'] ) ); - $file_stream = fopen( $file, 'rb' ); + $file_stream = fopen( $options['file'], 'rb' ); $stdout_stream = fopen('php://output', 'wb'); stream_copy_to_stream($file_stream, $stdout_stream);