- More loose definition regarding what gets to be a folder and what does not (More accurate, we lost folders before...)

- Changed some fread()s to fseek()s
- Much faster, single loop ( This might eat up more mem! Please report findings! )


git-svn-id: file:///svn/phpbb/trunk@5498 89ea8834-ac86-4346-8a33-228a782c2dd0
This commit is contained in:
David M 2006-01-27 06:51:52 +00:00
parent e77bc7e936
commit e78c215eba

View file

@ -154,60 +154,101 @@ class compress_zip extends compress
$dd_try = false; $dd_try = false;
fseek($this->fp, 0); fseek($this->fp, 0);
while (true) while (!feof($this->fp))
{ {
// Check if the signature is valid... // Check if the signature is valid...
$signature = fread($this->fp, 4); $signature = fread($this->fp, 4);
if (feof($this->fp))
{
break;
}
// TODO: Move the extraction loop inside the signature detection code, small speed boost
switch ($signature) switch ($signature)
{ {
// 'Local File Header' // 'Local File Header'
case "\x50\x4b\x03\x04": case "\x50\x4b\x03\x04":
// Get information about the zipped file but skip all the junk we don't need // Get information about the zipped file but skip all the junk we don't need
fread($this->fp, 4); fseek($this->fp, 4, SEEK_CUR);
$file['c_method'] = unpack("v", fread($this->fp, 2)); // compression method $c_method = current(unpack("v", fread($this->fp, 2))); // compression method
fread($this->fp, 8); fseek($this->fp, 4, SEEK_CUR);
$file['c_size'] = unpack("V", fread($this->fp, 4)); // compressed size $crc = current(unpack("V", fread($this->fp, 4))); // crc value
$file['uc_size'] = unpack("V", fread($this->fp, 4)); // uncompressed size $c_size = current(unpack("V", fread($this->fp, 4))); // compressed size
$file_name_length = unpack("v", fread($this->fp, 2)); // filename length $uc_size = current(unpack("V", fread($this->fp, 4))); // uncompressed size
$extra_field_length = unpack("v", fread($this->fp, 2)); // extra field length $file_name_length = current(unpack("v", fread($this->fp, 2))); // filename length
$file_name = fread($this->fp, $file_name_length[1]); // filename $extra_field_length = current(unpack("v", fread($this->fp, 2))); // extra field length
$file_name = fread($this->fp, $file_name_length); // filename
if ($extra_field_length[1]) if ($extra_field_length)
{ {
fread($this->fp, $extra_field_length[1]); fread($this->fp, $extra_field_length);
} }
$file['offset'] = ftell($this->fp); $target_filename = "$dst$file_name";
// Bypass the whole compressed contents, and look for the next file if (!$uc_size && !$crc && substr($file_name, -1, 1) == '/')
fseek($this->fp, $file['c_size'][1], SEEK_CUR); {
if (!is_dir($target_filename))
{
$str = '';
$folders = explode('/', $target_filename);
// Mount file table // Create and folders and subfolders if they do not exist
$seek_ary[$file_name] = array( foreach ($folders as $folder)
'c_method' => $file['c_method'][1], {
'c_size' => $file['c_size'][1], $str = (!empty($str)) ? $str . '/' . $folder : $folder;
'uc_size' => $file['uc_size'][1], if (!is_dir($str))
'offset' => $file['offset'] {
); if (!@mkdir($str, 0777))
{
trigger_error("Could not create directory $folder");
}
@chmod($str, 0777);
}
}
}
// This is a directory, we are not writting files
continue;
}
if (!$uc_size)
{
$content = '';
}
else
{
$content = fread($this->fp, $c_size);
}
$fp = fopen($target_filename, "w");
switch ($c_method)
{
case 0:
// Not compressed
fwrite($fp, $content);
break;
case 8:
// Deflate
fwrite($fp, gzinflate($content, $uc_size));
break;
case 12:
// Bzip2
fwrite($fp, bzdecompress($content));
break;
}
fclose($fp);
break; break;
// 'Central Directory Header' // 'Central Directory Header'
case "\x50\x4b\x01\x02": case "\x50\x4b\x01\x02":
fread($this->fp, 24); fseek($this->fp, 24, SEEK_CUR);
fread($this->fp, 12 + current(unpack("v", fread($this->fp, 2))) + current(unpack("v", fread($this->fp, 2))) + current(unpack("v", fread($this->fp, 2)))); fseek($this->fp, 12 + current(unpack("v", fread($this->fp, 2))) + current(unpack("v", fread($this->fp, 2))) + current(unpack("v", fread($this->fp, 2))), SEEK_CUR);
break; break;
// We safely end the loop as we are totally finished with looking for files and folders // Hit the end of the central directory record, we can safely end the loop as we are totally finished with looking for files and folders
case "\x50\x4b\x05\x06": case "\x50\x4b\x05\x06":
break 2; break 2;
// Look for the next signature... // 'Packed to Removable Disk', ignore it and look for the next signature...
case 'PK00': case 'PK00':
continue 2; continue 2;
@ -225,77 +266,6 @@ class compress_zip extends compress
} }
$dd_try = false; $dd_try = false;
} }
if (sizeof($seek_ary))
{
foreach ($seek_ary as $filename => $trash)
{
$dirname = dirname($filename);
if (!is_dir("$dst$dirname"))
{
$str = '';
$folders = explode('/', $dirname);
// Create and folders and subfolders if they do not exist
foreach ($folders as $folder)
{
$str = (!empty($str)) ? $str . '/' . $folder : $folder;
if (!is_dir("$dst$str"))
{
if (!@mkdir("$dst$str", 0777))
{
trigger_error("Could not create directory $folder");
}
@chmod("$dst$str", 0777);
}
}
}
if (substr($filename, -1, 1) == '/')
{
continue;
}
$target_filename = "$dst$filename";
$fdetails = &$seek_ary[$filename];
if (!$fdetails['uc_size'])
{
$fp = fopen($target_filename, "w");
fwrite($fp, '');
fclose($fp);
}
fseek($this->fp, $fdetails['offset']);
$mode = $fdetails['c_method'];
$content = fread($this->fp, $fdetails['c_size']);
$fp = fopen($target_filename, "w");
switch ($mode)
{
case 0:
// Not compressed
fwrite($fp, $content);
break;
case 8:
// Deflate
fwrite($fp, gzinflate($content, $fdetails['uc_size']));
break;
case 12:
// Bzip2
fwrite($fp, bzdecompress($content));
break;
}
fclose($fp);
}
}
} }
function close() function close()