2017-02-02 9 views
0

私のwikiを1.28に更新するために、古いPHPコードをリファクタリングする必要があります。 私は、選択されたページを文字列に保存するExport Pluginを持っています。 この文字列はzipファイルに追加され、gzcompressによって圧縮されます。php gzcompressで破損した.zipファイルが生成される

ファイルをダウンロードできますが、開こうとすると「ファイルが壊れています」と表示されます。私がwinrarでアーカイブを修復すれば、期待される出力ファイルが得られます。最初の場所で正しい.zipファイルを得るために解決する方法

私が使用している古いZipHelperと何か関係があるかもしれませんが、実際に何が起こっているのかわかりません。 php:

class ZipWriter 
{ 
    function __construct() 
    { 
    } 

    var $datasec   = array(); 
    var $ctrl_dir   = array(); 
    var $eof_ctrl_dir  = "\x50\x4b\x05\x06\x00\x00\x00\x00"; 
    var $old_offset   = 0; 
    var $filename   = ""; 
    var $filepointer; 
    var $writtenSizeCtrlDir = 0; 
    var $writtenSizeData = 0; 
    var $writtenFiles  = 0; 
    var $completeBuffer; 
    var $stream    = false; 

    function addFile($data, $name, $time = 0) 
    { 
     $name = str_replace('\\', '/', $name); 

     $dtime = dechex($this->unix2DosTime($time)); 
     $hexdtime = '\x' . $dtime[6] . $dtime[7] 
      . '\x' . $dtime[4] . $dtime[5] 
      . '\x' . $dtime[2] . $dtime[3] 
      . '\x' . $dtime[0] . $dtime[1]; 
     eval('$hexdtime = "' . $hexdtime . '";'); 

     $fr = "\x50\x4b\x03\x04"; 
     $fr .= "\x14\x00";   // ver needed to extract 
     $fr .= "\x00\x00";   // gen purpose bit flag 
     $fr .= "\x08\x00";   // compression method 
     $fr .= $hexdtime;    // last mod time and date 

     // "local file header" segment 
     $unc_len = strlen($data); 
     $crc  = crc32($data); 
     $zdata = gzcompress($data); 
     $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug 

     $c_len = strlen($zdata); 
     $fr .= pack('V', $crc);    // crc32 
     $fr .= pack('V', $c_len);   // compressed filesize 
     $fr .= pack('V', $unc_len);   // uncompressed filesize 
     $fr .= pack('v', strlen($name)); // length of filename 
     $fr .= pack('v', 0);    // extra field length 
     $fr .= $name; 

     // "file data" segment 
     $fr .= $zdata; 

     // "data descriptor" segment (optional but necessary if archive is not 
     // served as file) 
     $fr .= pack('V', $crc);     // crc32 
     $fr .= pack('V', $c_len);    // compressed filesize 
     $fr .= pack('V', $unc_len);    // uncompressed filesize 

     if ($this->stream) { 
      array_push($this->completeBuffer, $fr); 
     } else { 
      // write the compressed data to the zipfile 
      fputs($this->filepointer, $fr); 
     } 

     // count up the already written data size 
     $this->writtenSizeData = $this->writtenSizeData + strlen($fr); 

     //$new_offset  = strlen(implode('', $this->datasec)); 
     $new_offset = $this->writtenSizeData; 

     // now add to central directory record 
     $cdrec = "\x50\x4b\x01\x02"; 
     $cdrec .= "\x00\x00";    // version made by 
     $cdrec .= "\x14\x00";    // version needed to extract 
     $cdrec .= "\x00\x00";    // gen purpose bit flag 
     $cdrec .= "\x08\x00";    // compression method 
     $cdrec .= $hexdtime;     // last mod time & date 
     $cdrec .= pack('V', $crc);   // crc32 
     $cdrec .= pack('V', $c_len);   // compressed filesize 
     $cdrec .= pack('V', $unc_len);  // uncompressed filesize 
     $cdrec .= pack('v', strlen($name)); // length of filename 
     $cdrec .= pack('v', 0);    // extra field length 
     $cdrec .= pack('v', 0);    // file comment length 
     $cdrec .= pack('v', 0);    // disk number start 
     $cdrec .= pack('v', 0);    // internal file attributes 
     $cdrec .= pack('V', 32);   // external file attributes - 'archive' bit set 

     $cdrec .= pack('V', $this->old_offset); // relative offset of local header 
     $this->old_offset = $new_offset; 

     $cdrec .= $name; 

     // save to central directory 
     $this->ctrl_dir[] = $cdrec; 
     // count up written files 
     $this->writtenFiles++; 
    } // end of the 'addFile()' method 

} 

答えて

1

さまざまなファイル形式が混乱しています。 PHPのgzcompressはzlib形式を生成しますが、それを.zip形式のファイルとして解釈しようとしていますが、そうではありません。

PHPのこれらの関数の名前は、恐らくgzcompressがgzip形式を生成すると考えるかもしれないので、ひどく誤解を招くものです。 (いずれにしても、ではなく、のzip形式です。)しかし、いいえ、gzcompressはzlib形式を生成します。 gzip形式を使用する場合は、gzencodeを使用する必要があります。未処理のデフレート形式を使用する場合は、gzdeflateを使用する必要があります。したがって、2つの関数はgzで始まりますが、gzip形式を生成する関数は1つだけです。

これらのどれも、zip形式を生成しません。そのため、symcbeanに記載されているように、ZipArchive classを使用します。

+0

完全性のため.... PHPはZIP拡張子を持つZIPファイルをサポートしています:http://php.net/manual/en/book.zip.php – symcbean

関連する問題