misterunknown: replaced old zip class, added ability to download script root as a zip file

This commit is contained in:
Marco Dickert 2016-11-23 05:19:03 +01:00
parent d4ca4a3cf0
commit ed260c2573
5 changed files with 223 additions and 449 deletions

View File

@ -7,7 +7,7 @@ $IFM_INCLUDES = "src/includes.php";
$IFM_MAIN = "src/main.php"; $IFM_MAIN = "src/main.php";
$IFM_STYLE = "src/style.css"; $IFM_STYLE = "src/style.css";
$IFM_JS = "src/ifm.js"; $IFM_JS = "src/ifm.js";
$IFM_OTHER_PHPFILES = array("src/zip_file.php"); $IFM_OTHER_PHPFILES = array("src/ifmzip.php");
$filename = "ifm.php"; $filename = "ifm.php";

533
ifm.php
View File

@ -240,405 +240,72 @@ AeDRWST;
AeDRWST; AeDRWST;
} }
} }
// zip class (for zipnload) /* =======================================================================
class archive { * Improved File Manager
function __construct($name) { * ---------------------
$this->options = array( * License: This project is provided under the terms of the MIT LICENSE
'basedir' => ".", * http://github.com/misterunknown/ifm/blob/master/LICENSE
'name' => $name, * =======================================================================
'prepend' => "", *
'inmemory' => 0, * zip class
'overwrite' => 0, *
'recurse' => 1, * this was adapted from http://php.net/manual/de/class.ziparchive.php#110719
'storepaths' => 1, */
'followlinks' => 0,
'level' => 3, class IFMZip {
'method' => 1, private static function folderToZip($folder, &$zipFile, $exclusiveLength) {
'sfx' => "", $handle = opendir( $folder );
'type' => "", while( false !== $f = readdir( $handle ) ) {
'comment' => "", if( $f != '.' && $f != '..' ) {
'maxsize' => memory_get_usage() $filePath = "$folder/$f";
); if( file_exists( $filePath ) && is_readable( $filePath ) ) {
$this->files = array(); // Remove prefix from file path before add to zip.
$this->exclude = array(); $localPath = substr($filePath, $exclusiveLength);
$this->exclude_regexp = array(); if( is_file( $filePath ) ) {
$this->storeonly = array(); $zipFile->addFile( $filePath, $localPath );
$this->error = array(); } elseif( is_dir( $filePath ) ) {
} // Add sub-directory.
function set_options($options) { $zipFile->addEmptyDir( $localPath );
foreach ($options as $key => $value) self::folderToZip( $filePath, $zipFile, $exclusiveLength );
$this->options[$key] = $value; }
if (!empty($this->options['basedir'])) { }
$this->options['basedir'] = str_replace("\\", "/", $this->options['basedir']); }
$this->options['basedir'] = preg_replace("/\/+/", "/", $this->options['basedir']); }
$this->options['basedir'] = preg_replace("/\/$/", "", $this->options['basedir']); closedir( $handle );
} }
if (!empty($this->options['name'])) {
$this->options['name'] = str_replace("\\", "/", $this->options['name']); public static function create_zip( $src, $out, $root=false )
$this->options['name'] = preg_replace("/\/+/", "/", $this->options['name']); {
} $z = new ZipArchive();
if (!empty($this->options['prepend'])) { $z->open( $out, ZIPARCHIVE::CREATE);
$this->options['prepend'] = str_replace("\\", "/", $this->options['prepend']); if( $root ) {
$this->options['prepend'] = preg_replace("/^(\.*\/+)+/", "", $this->options['prepend']); self::folderToZip( realpath( $src ), $z, strlen( realpath( $src ) . '/' ) );
$this->options['prepend'] = preg_replace("/\/+/", "/", $this->options['prepend']); } else {
$this->options['prepend'] = preg_replace("/\/$/", "", $this->options['prepend']) . "/"; $z->addEmptyDir( basename( $src ) );
} self::folderToZip( realpath( $src ), $z, strlen( dirname( $src ) . '/' ) );
} }
function create_archive() { try {
$this->make_list(); if( ( $res = $z->close() ) !== true ) {
if ($this->options['inmemory'] == 0) { throw new Exception("Error while creating zip archive: ". $z->getStatusString());
$pwd = getcwd(); }
chdir($this->options['basedir']); } catch ( Exception $e ) {
if ($this->options['overwrite'] == 0 && file_exists($this->options['name'] . ($this->options['type'] == "gzip" || $this->options['type'] == "bzip" ? ".tmp" : ""))) { throw $e;
$this->error[] = "File {$this->options['name']} already exists."; }
chdir($pwd); }
return 0;
} else public static function unzip_file( $file ) {
if ($this->archive = @fopen($this->options['name'] . ($this->options['type'] == "gzip" || $this->options['type'] == "bzip" ? ".tmp" : ""), "wb+")) $zip = new ZipArchive();
chdir($pwd); $res = $zip->open( $file );
else { if( $res === true ) {
$this->error[] = "Could not open {$this->options['name']} for writing."; $zip->extractTo( './' );
chdir($pwd); $zip->close();
return 0; return true;
} } else {
} else return false;
$this->archive = ""; }
switch ($this->options['type']) { }
case "zip" : }
if (!$this->create_zip()) {
$this->error[] = "Could not create zip file.";
return 0;
}
break;
case "bzip" :
if (!$this->create_tar()) {
$this->error[] = "Could not create tar file.";
return 0;
}
if (!$this->create_bzip()) {
$this->error[] = "Could not create bzip2 file.";
return 0;
}
break;
case "gzip" :
if (!$this->create_tar()) {
$this->error[] = "Could not create tar file.";
return 0;
}
if (!$this->create_gzip()) {
$this->error[] = "Could not create gzip file.";
return 0;
}
break;
case "tar" :
if (!$this->create_tar()) {
$this->error[] = "Could not create tar file.";
return 0;
}
}
if ($this->options['inmemory'] == 0) {
fclose($this->archive);
if ($this->options['type'] == "gzip" || $this->options['type'] == "bzip")
unlink($this->options['basedir'] . "/" . $this->options['name'] . ".tmp");
}
}
function add_data($data) {
if ($this->options['inmemory'] == 0)
fwrite($this->archive, $data);
else
$this->archive .= $data;
}
function exclude_file($name) {
$ret = false;
// Check for exclusion regexps
if (!empty($this->exclude_regexp)) {
foreach ($this->exclude_regexp as $pattern) {
if (preg_match('|^' . $pattern . '$|', $name)) {
$ret = true;
}
}
}
if ($this->options['maxsize'] > 0) {
if (filesize($this->options['basedir'] . "/" . $name) > $this->options['maxsize']) {
$ret = true;
}
}
return $ret;
}
function make_list() {
foreach ($this->files as $key => $value) {
if ($this->exclude_file($value['name'])) {
unset($this->files[$key]);
}
}
if (!empty($this->exclude)) {
foreach ($this->files as $key => $value) {
foreach ($this->exclude as $current) {
if ($value['name'] == $current['name']) {
unset($this->files[$key]);
}
}
}
}
if (!empty($this->storeonly))
foreach ($this->files as $key => $value)
foreach ($this->storeonly as $current)
if ($value['name'] == $current['name'])
$this->files[$key]['method'] = 0;
unset($this->exclude, $this->storeonly);
}
function add_files($list) {
$temp = $this->list_files($list);
foreach ($temp as $current)
$this->files[] = $current;
}
function exclude_regexp_files($patterns) {
$this->exclude_regexp = explode("|", $patterns);
}
function exclude_files($list) {
$temp = $this->list_files($list);
foreach ($temp as $current)
$this->exclude[] = $current;
}
function store_files($list) {
$temp = $this->list_files($list);
foreach ($temp as $current)
$this->storeonly[] = $current;
}
function list_files($list) {
if (!is_array($list)) {
$temp = $list;
$list = array(
$temp
);
unset($temp);
}
$files = array();
$pwd = getcwd();
chdir($this->options['basedir']);
foreach ($list as $current) {
$current = str_replace("\\", "/", $current);
$current = preg_replace("/\/+/", "/", $current);
$current = preg_replace("/\/$/", "", $current);
if (strstr($current, "*")) {
$regex = preg_replace("/([\\\^\$\.\[\]\|\(\)\?\+\{\}\/])/", "\\\\\\1", $current);
$regex = str_replace("*", ".*", $regex);
$dir = strstr($current, "/") ? substr($current, 0, strrpos($current, "/")) : ".";
$temp = $this->parse_dir($dir);
//print "dir: ".$dir; print_r($temp);print "EOL<br>\n";
foreach ($temp as $current2) {
//print "$regex : ".$current2['name']." <br>\n";
if (preg_match("/^{$regex}$/i", $current2['name']))
$files[] = $current2;
}
unset($regex, $dir, $temp, $current);
} else
if (@ is_dir($current)) {
$temp = $this->parse_dir($current);
foreach ($temp as $file)
$files[] = $file;
unset($temp, $file);
} else
if (@ file_exists($current))
$files[] = array(
'name' => $current,
'name2' => $this->options['prepend'] .
preg_replace("/(\.+\/+)+/", "", ($this->options['storepaths'] == 0 && strstr($current, "/")) ? substr($current, strrpos($current, "/") + 1) : $current),
'type' => @ is_link($current) && $this->options['followlinks'] == 0 ? 2 : 0,
'ext' => substr($current, strrpos($current, ".")),
'stat' => stat($current)
);
}
chdir($pwd);
unset($current, $pwd);
usort($files, array(
"archive",
"sort_files"
));
return $files;
}
function parse_dir($dirname) {
if ($this->options['storepaths'] == 1 && !preg_match("/^(\.+\/*)+$/", $dirname))
$files = array(
array(
'name' => $dirname,
'name2' => $this->options['prepend'] .
preg_replace("/(\.+\/+)+/", "", ($this->options['storepaths'] == 0 && strstr($dirname, "/")) ? substr($dirname, strrpos($dirname, "/") + 1) : $dirname),
'type' => 5,
'stat' => stat($dirname)
)
);
else
$files= array();
$dir = @ opendir($dirname);
while ($file = @ readdir($dir)) {
$fullname = $dirname . "/" . $file;
if ($file == "." || $file == "..")
continue;
else
if (@ is_dir($fullname)) {
if (empty($this->options['recurse']))
continue;
$temp = $this->parse_dir($fullname);
foreach ($temp as $file2)
$files[] = $file2;
} else
if (@ file_exists($fullname))
$files[] = array(
'name' => $fullname,
'name2' => $this->options['prepend'] .
preg_replace("/(\.+\/+)+/", "", ($this->options['storepaths'] == 0 && strstr($fullname, "/")) ? substr($fullname, strrpos($fullname, "/") + 1) : $fullname),
'type' => @ is_link($fullname) && $this->options['followlinks'] == 0 ? 2 : 0,
'ext' => substr($file, strrpos($file, ".")),
'stat' => stat($fullname)
);
}
@ closedir($dir);
return $files;
}
function sort_files($a, $b) {
if ($a['type'] != $b['type'])
if ($a['type'] == 5 || $b['type'] == 2)
return -1;
else
if ($a['type'] == 2 || $b['type'] == 5)
return 1;
else
if ($a['type'] == 5)
return strcmp(strtolower($a['name']), strtolower($b['name']));
else
if ($a['ext'] != $b['ext'])
return strcmp($a['ext'], $b['ext']);
else
if ($a['stat'][7] != $b['stat'][7])
return $a['stat'][7] > $b['stat'][7] ? -1 : 1;
else
return strcmp(strtolower($a['name']), strtolower($b['name']));
return 0;
}
function download_file() {
if ($this->options['inmemory'] == 0) {
$this->error[] = "Can only use download_file() if archive is in memory. Redirect to file otherwise, it is faster.";
return;
}
switch ($this->options['type']) {
case "zip" :
header("Content-Type: application/zip");
break;
case "bzip" :
header("Content-Type: application/x-bzip2");
break;
case "gzip" :
header("Content-Type: application/x-gzip");
break;
case "tar" :
header("Content-Type: application/x-tar");
}
$header = "Content-Disposition: attachment; filename=\"";
$header .= strstr($this->options['name'], "/") ? substr($this->options['name'], strrpos($this->options['name'], "/") + 1) : $this->options['name'];
$header .= "\"";
header($header);
header("Content-Length: " . strlen($this->archive));
header("Content-Transfer-Encoding: binary");
header("Cache-Control: no-cache, must-revalidate, max-age=60");
header("Expires: Sat, 01 Jan 2000 12:00:00 GMT");
print ($this->archive);
}
function save_file($filename, $path = '') {
if ($this->options['inmemory'] == 0) {
$this->error[] = "Can only use save_file() if archive is in memory.";
return;
}
if ($fhandle = @fopen($path . $filename, 'w')) {
if (@fwrite($fhandle, $this->archive)) {
if (@fclose($fhandle))
return 1;
else
return 0;
}else {
return -2;
}
} else {
return -1;
}
}
}
class zip_file extends archive {
function __construct($name) {
parent::__construct($name);
$this->options['type'] = "zip";
}
function create_zip() {
$files = 0;
$offset = 0;
$central = "";
if (!empty($this->options['sfx']))
if ($fp = @ fopen($this->options['sfx'], "rb")) {
$temp = fread($fp, filesize($this->options['sfx']));
fclose($fp);
$this->add_data($temp);
$offset += strlen($temp);
unset($temp);
} else
$this->error[] = "Could not open sfx module from {$this->options['sfx']}.";
$pwd = getcwd();
chdir($this->options['basedir']);
foreach ($this->files as $current) {
if ($current['name'] == $this->options['name'])
continue;
$timedate = explode(" ", date("Y n j G i s", $current['stat'][9]));
$timedate = ($timedate[0] - 1980 << 25) | ($timedate[1] << 21) | ($timedate[2] << 16) | ($timedate[3] << 11) | ($timedate[4] << 5) | ($timedate[5]);
$block = pack("VvvvV", 0x04034b50, 0x000A, 0x0000, (isset($current['method']) || $this->options['method'] == 0) ? 0x0000 : 0x0008, $timedate);
//if ($current['stat'][7] == 0 && $current['type'] == 5) {
if ($current['type'] == 5) {
$block .= pack("VVVvv", 0x00000000, 0x00000000, 0x00000000, strlen($current['name2']) + 1, 0x0000);
$block .= $current['name2'] . "/";
$this->add_data($block);
$central .= pack("VvvvvVVVVvvvvvVV", 0x02014b50, 0x0014, $this->options['method'] == 0 ? 0x0000 : 0x000A, 0x0000, (isset($current['method']) || $this->options['method'] == 0) ? 0x0000 : 0x0008, $timedate, 0x00000000, 0x00000000, 0x00000000, strlen($current['name2']) + 1, 0x0000, 0x0000, 0x0000, 0x0000, $current['type'] == 5 ? 0x00000010 : 0x00000000, $offset);
$central .= $current['name2'] . "/";
$files++;
$offset += ( 31 + strlen($current['name2']));
} else
if ($current['stat'][7] == 0) {
$block .= pack("VVVvv", 0x00000000, 0x00000000, 0x00000000, strlen($current['name2']), 0x0000);
$block .= $current['name2'];
$this->add_data($block);
$central .= pack("VvvvvVVVVvvvvvVV", 0x02014b50, 0x0014, $this->options['method'] == 0 ? 0x0000 : 0x000A, 0x0000, (isset($current['method']) || $this->options['method'] == 0) ? 0x0000 : 0x0008, $timedate, 0x00000000, 0x00000000, 0x00000000, strlen($current['name2']), 0x0000, 0x0000, 0x0000, 0x0000, $current['type'] == 5 ? 0x00000010 : 0x00000000, $offset);
$central .= $current['name2'];
$files++;
$offset += ( 30 + strlen($current['name2']));
} else
if ($fp = @ fopen($current['name'], "rb")) {
$temp = fread($fp, $current['stat'][7]);
fclose($fp);
$crc32 = crc32($temp);
if (!isset($current['method']) && $this->options['method'] == 1) {
$temp = gzcompress($temp, $this->options['level']);
$size = strlen($temp) - 6;
$temp = substr($temp, 2, $size);
} else
$size= strlen($temp);
$block .= pack("VVVvv", $crc32, $size, $current['stat'][7], strlen($current['name2']), 0x0000);
$block .= $current['name2'];
$this->add_data($block);
$this->add_data($temp);
unset($temp);
$central .= pack("VvvvvVVVVvvvvvVV", 0x02014b50, 0x0014, $this->options['method'] == 0 ? 0x0000 : 0x000A, 0x0000, (isset($current['method']) || $this->options['method'] == 0) ? 0x0000 : 0x0008, $timedate, $crc32, $size, $current['stat'][7], strlen($current['name2']), 0x0000, 0x0000, 0x0000, 0x0000, 0x00000000, $offset);
$central .= $current['name2'];
$files++;
$offset += ( 30 + strlen($current['name2']) + $size);
} else
$this->error[] = "Could not open file {$current['name']} for reading. It was not added.";
}
$this->add_data($central);
$this->add_data(pack("VvvvvVVv", 0x06054b50, 0x0000, 0x0000, $files, $files, strlen($central), $offset, !empty($this->options['comment']) ? strlen($this->options['comment']) : 0x0000));
if (!empty($this->options['comment']))
$this->add_data($this->options['comment']);
chdir($pwd);
return 1;
}
}
/* ======================================================================= /* =======================================================================
* Improved File Manager * Improved File Manager
@ -856,24 +523,30 @@ if(!ifm) {
if(data[i].group) newrow += '<td>'+data[i].group+'</td>'; if(data[i].group) newrow += '<td>'+data[i].group+'</td>';
if(ifm.inArray(1,[ifm.config.edit, ifm.config.rename, ifm.config.delete, ifm.config.zipnload, ifm.config.extract])) { if(ifm.inArray(1,[ifm.config.edit, ifm.config.rename, ifm.config.delete, ifm.config.zipnload, ifm.config.extract])) {
newrow += '<td>'; newrow += '<td>';
if(data[i].type == "dir") {
if( data[i].name == ".." ) data[i].name = ".";
if(ifm.config.zipnload == 1) {
newrow += '<form method="post" style="display:inline-block;padding:0;margin:0;border:0;">\
<fieldset style="display:inline-block;padding:0;margin:0;border:0;">\
<input type="hidden" name="dir" value="'+ifm.currentDir+'">\
<input type="hidden" name="filename" value="'+data[i].name+'">\
<input type="hidden" name="api" value="zipnload">';
if( data[i].name == "." )
newrow += '<sub>download current directory</sub>';
newrow += '<button type="submit">\
<img src="'+ifm.icons["zipnload.png"]+'" alt="zip&amp;load">\
</button>\
</fieldset>\
</form>';
}
}
else if(data[i].name.toLowerCase().substr(-4) == ".zip") {
if(ifm.config.extract == 1) newrow += '<button onclick="ifm.extractFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["extract.png"]+'" alt="extract" /></button>';
}
else {
if(ifm.config.edit == 1) newrow += '<button onclick="ifm.showLoading();ifm.editFile(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["edit.png"]+'" alt="edit" /></button>';
}
if(data[i].name != ".." && data[i].name != ".") { if(data[i].name != ".." && data[i].name != ".") {
if(data[i].type == "dir") {
if(ifm.config.zipnload == 1)
newrow += '<form method="post" style="display:inline-block;padding:0;margin:0;border:0;">\
<fieldset style="display:inline-block;padding:0;margin:0;border:0;">\
<input type="hidden" name="dir" value="'+ifm.currentDir+'">\
<input type="hidden" name="filename" value="'+data[i].name+'">\
<input type="hidden" name="api" value="zipnload">\
<button type="submit"><img src="'+ifm.icons["zipnload.png"]+'" alt="zip&amp;load"></button>\
</fieldset>\
</form>';
}
else if(data[i].name.toLowerCase().substr(-4) == ".zip") {
if(ifm.config.extract == 1) newrow += '<button onclick="ifm.extractFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["extract.png"]+'" alt="extract" /></button>';
}
else {
if(ifm.config.edit == 1) newrow += '<button onclick="ifm.showLoading();ifm.editFile(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["edit.png"]+'" alt="edit" /></button>';
}
if(ifm.config.rename == 1) newrow += '<button onclick="ifm.renameFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["rename.png"]+'" alt="rename" /></button>'; if(ifm.config.rename == 1) newrow += '<button onclick="ifm.renameFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["rename.png"]+'" alt="rename" /></button>';
if(ifm.config.delete == 1) newrow += '<button onclick="ifm.deleteFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["delete.png"]+'" alt="delete" /></button>'; if(ifm.config.delete == 1) newrow += '<button onclick="ifm.deleteFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["delete.png"]+'" alt="delete" /></button>';
} }
@ -1964,15 +1637,26 @@ $(document).ready(function() {ifm.init()}); // init ifm
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( ! file_exists( $d['filename'] ) ) if( ! file_exists( $d['filename'] ) )
echo json_encode( array( "status" => "ERROR", "message" => "Directory not found" ) ); echo json_encode( array( "status" => "ERROR", "message" => "Directory not found" ) );
elseif ( ! $this->allowedFileName( $d['filename'] ) )
echo json_encode( array( "status" => "ERROR", "message" => "Filename not allowed" ) );
else { else {
unset( $zip ); unset( $zip );
$dfile = uniqid( "ifm-tmp-" ) . ".zip"; // temporary filename $dfile = uniqid( "ifm-tmp-" ) . ".zip"; // temporary filename
$zip = new zip_file( $dfile ); try {
$zip->add_files( $d['filename'] ); IFMZip::create_zip( realpath( $d['filename'] ), $dfile, ( $d['filename'] == "." ) );
$zip->create_archive( ); if( $d['filename'] == "." ) {
header( "Content-Disposition: attachment; filename=\"".$d['filename'].".zip\"" ); if( getcwd() == $this->getScriptRoot() )
echo file_get_contents( $dfile ); $d['filename'] = "root";
unlink( $dfile ); // delete temporary file else
$d['filename'] = basename( getcwd() );
}
header( "Content-Disposition: attachment; filename=\"".$d['filename'].".zip\"" );
readfile( $dfile );
} catch ( Exception $e ) {
echo "An error occured: " . $e->getMessage();
} finally {
if( file_exists( $dfile ) ) @unlink( $dfile );
}
} }
} }
} }
@ -2134,7 +1818,8 @@ $(document).ready(function() {ifm.init()}); // init ifm
} }
private function getScriptRoot() { private function getScriptRoot() {
return realpath( substr( $_SERVER["SCRIPT_FILENAME"], 0, strrpos( $_SERVER["SCRIPT_FILENAME"], "/" ) ) ); //return realpath( substr( $_SERVER["SCRIPT_FILENAME"], 0, strrpos( $_SERVER["SCRIPT_FILENAME"], "/" ) ) );
return dirname( $_SERVER["SCRIPT_FILENAME"] );
} }
private function chDirIfNecessary($d) { private function chDirIfNecessary($d) {
@ -2218,6 +1903,8 @@ $(document).ready(function() {ifm.init()}); // init ifm
return false; return false;
elseif( IFMConfig::showhiddenfiles != 1 && substr( $f, 0, 1 ) == "." ) elseif( IFMConfig::showhiddenfiles != 1 && substr( $f, 0, 1 ) == "." )
return false; return false;
elseif( ! $this->isPathValid( $f ) )
return false;
return true; return true;
} }

View File

@ -130,24 +130,30 @@ if(!ifm) {
if(data[i].group) newrow += '<td>'+data[i].group+'</td>'; if(data[i].group) newrow += '<td>'+data[i].group+'</td>';
if(ifm.inArray(1,[ifm.config.edit, ifm.config.rename, ifm.config.delete, ifm.config.zipnload, ifm.config.extract])) { if(ifm.inArray(1,[ifm.config.edit, ifm.config.rename, ifm.config.delete, ifm.config.zipnload, ifm.config.extract])) {
newrow += '<td>'; newrow += '<td>';
if(data[i].type == "dir") {
if( data[i].name == ".." ) data[i].name = ".";
if(ifm.config.zipnload == 1) {
newrow += '<form method="post" style="display:inline-block;padding:0;margin:0;border:0;">\
<fieldset style="display:inline-block;padding:0;margin:0;border:0;">\
<input type="hidden" name="dir" value="'+ifm.currentDir+'">\
<input type="hidden" name="filename" value="'+data[i].name+'">\
<input type="hidden" name="api" value="zipnload">';
if( data[i].name == "." )
newrow += '<sub>download current directory</sub>';
newrow += '<button type="submit">\
<img src="'+ifm.icons["zipnload.png"]+'" alt="zip&amp;load">\
</button>\
</fieldset>\
</form>';
}
}
else if(data[i].name.toLowerCase().substr(-4) == ".zip") {
if(ifm.config.extract == 1) newrow += '<button onclick="ifm.extractFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["extract.png"]+'" alt="extract" /></button>';
}
else {
if(ifm.config.edit == 1) newrow += '<button onclick="ifm.showLoading();ifm.editFile(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["edit.png"]+'" alt="edit" /></button>';
}
if(data[i].name != ".." && data[i].name != ".") { if(data[i].name != ".." && data[i].name != ".") {
if(data[i].type == "dir") {
if(ifm.config.zipnload == 1)
newrow += '<form method="post" style="display:inline-block;padding:0;margin:0;border:0;">\
<fieldset style="display:inline-block;padding:0;margin:0;border:0;">\
<input type="hidden" name="dir" value="'+ifm.currentDir+'">\
<input type="hidden" name="filename" value="'+data[i].name+'">\
<input type="hidden" name="api" value="zipnload">\
<button type="submit"><img src="'+ifm.icons["zipnload.png"]+'" alt="zip&amp;load"></button>\
</fieldset>\
</form>';
}
else if(data[i].name.toLowerCase().substr(-4) == ".zip") {
if(ifm.config.extract == 1) newrow += '<button onclick="ifm.extractFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["extract.png"]+'" alt="extract" /></button>';
}
else {
if(ifm.config.edit == 1) newrow += '<button onclick="ifm.showLoading();ifm.editFile(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["edit.png"]+'" alt="edit" /></button>';
}
if(ifm.config.rename == 1) newrow += '<button onclick="ifm.renameFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["rename.png"]+'" alt="rename" /></button>'; if(ifm.config.rename == 1) newrow += '<button onclick="ifm.renameFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["rename.png"]+'" alt="rename" /></button>';
if(ifm.config.delete == 1) newrow += '<button onclick="ifm.deleteFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["delete.png"]+'" alt="delete" /></button>'; if(ifm.config.delete == 1) newrow += '<button onclick="ifm.deleteFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><img src="'+ifm.icons["delete.png"]+'" alt="delete" /></button>';
} }

67
src/ifmzip.php Normal file
View File

@ -0,0 +1,67 @@
<?php
/* =======================================================================
* Improved File Manager
* ---------------------
* License: This project is provided under the terms of the MIT LICENSE
* http://github.com/misterunknown/ifm/blob/master/LICENSE
* =======================================================================
*
* zip class
*
* this was adapted from http://php.net/manual/de/class.ziparchive.php#110719
*/
class IFMZip {
private static function folderToZip($folder, &$zipFile, $exclusiveLength) {
$handle = opendir( $folder );
while( false !== $f = readdir( $handle ) ) {
if( $f != '.' && $f != '..' ) {
$filePath = "$folder/$f";
if( file_exists( $filePath ) && is_readable( $filePath ) ) {
// Remove prefix from file path before add to zip.
$localPath = substr($filePath, $exclusiveLength);
if( is_file( $filePath ) ) {
$zipFile->addFile( $filePath, $localPath );
} elseif( is_dir( $filePath ) ) {
// Add sub-directory.
$zipFile->addEmptyDir( $localPath );
self::folderToZip( $filePath, $zipFile, $exclusiveLength );
}
}
}
}
closedir( $handle );
}
public static function create_zip( $src, $out, $root=false )
{
$z = new ZipArchive();
$z->open( $out, ZIPARCHIVE::CREATE);
if( $root ) {
self::folderToZip( realpath( $src ), $z, strlen( realpath( $src ) . '/' ) );
} else {
$z->addEmptyDir( basename( $src ) );
self::folderToZip( realpath( $src ), $z, strlen( dirname( $src ) . '/' ) );
}
try {
if( ( $res = $z->close() ) !== true ) {
throw new Exception("Error while creating zip archive: ". $z->getStatusString());
}
} catch ( Exception $e ) {
throw $e;
}
}
public static function unzip_file( $file ) {
$zip = new ZipArchive();
$res = $zip->open( $file );
if( $res === true ) {
$zip->extractTo( './' );
$zip->close();
return true;
} else {
return false;
}
}
}

View File

@ -11,7 +11,7 @@
*/ */
class IFM { class IFM {
const VERSION = '2.0'; const VERSION = '2.1';
public function __construct() { public function __construct() {
session_start(); session_start();
@ -514,15 +514,26 @@ class IFM {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( ! file_exists( $d['filename'] ) ) if( ! file_exists( $d['filename'] ) )
echo json_encode( array( "status" => "ERROR", "message" => "Directory not found" ) ); echo json_encode( array( "status" => "ERROR", "message" => "Directory not found" ) );
elseif ( ! $this->allowedFileName( $d['filename'] ) )
echo json_encode( array( "status" => "ERROR", "message" => "Filename not allowed" ) );
else { else {
unset( $zip ); unset( $zip );
$dfile = uniqid( "ifm-tmp-" ) . ".zip"; // temporary filename $dfile = uniqid( "ifm-tmp-" ) . ".zip"; // temporary filename
$zip = new zip_file( $dfile ); try {
$zip->add_files( $d['filename'] ); IFMZip::create_zip( realpath( $d['filename'] ), $dfile, ( $d['filename'] == "." ) );
$zip->create_archive( ); if( $d['filename'] == "." ) {
header( "Content-Disposition: attachment; filename=\"".$d['filename'].".zip\"" ); if( getcwd() == $this->getScriptRoot() )
echo file_get_contents( $dfile ); $d['filename'] = "root";
unlink( $dfile ); // delete temporary file else
$d['filename'] = basename( getcwd() );
}
header( "Content-Disposition: attachment; filename=\"".$d['filename'].".zip\"" );
readfile( $dfile );
} catch ( Exception $e ) {
echo "An error occured: " . $e->getMessage();
} finally {
if( file_exists( $dfile ) ) @unlink( $dfile );
}
} }
} }
} }
@ -684,7 +695,8 @@ class IFM {
} }
private function getScriptRoot() { private function getScriptRoot() {
return realpath( substr( $_SERVER["SCRIPT_FILENAME"], 0, strrpos( $_SERVER["SCRIPT_FILENAME"], "/" ) ) ); //return realpath( substr( $_SERVER["SCRIPT_FILENAME"], 0, strrpos( $_SERVER["SCRIPT_FILENAME"], "/" ) ) );
return dirname( $_SERVER["SCRIPT_FILENAME"] );
} }
private function chDirIfNecessary($d) { private function chDirIfNecessary($d) {
@ -768,6 +780,8 @@ class IFM {
return false; return false;
elseif( IFMConfig::showhiddenfiles != 1 && substr( $f, 0, 1 ) == "." ) elseif( IFMConfig::showhiddenfiles != 1 && substr( $f, 0, 1 ) == "." )
return false; return false;
elseif( ! $this->isPathValid( $f ) )
return false;
return true; return true;
} }