2017-02-02 1 views
0

위키를 1.28로 업데이트하기 위해 일부 오래된 PHP 코드를 리팩토링해야합니다. 나는 선택한 페이지를 문자열로 저장하는 내보내기 플러그인이 있습니다. 이 문자열은 zip 파일에 추가되며 gzcompress로 압축됩니다.php gzcompress가 손상된 .zip 파일을 생성합니다.

파일을 다운로드 할 수 있지만 열려고하면 "파일이 손상되었습니다."라고 표시됩니다. winrar로 아카이브를 복구하면 예상되는 출력 파일을 얻게됩니다. 올바른 .zip 파일을 얻으려면 먼저 어떻게 해결해야합니까?

이전 ZipHelper와 관련이있을 수 있습니다.하지만 실제로 어떤 일이 일어나고 있는지 전혀 알지 못합니다. ph :

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 형식을 생성한다고 생각할 수 있습니다. (어떤 방식으로도 이 아닙니다.)하지만 아니요, gzcompress은 zlib 형식을 생성합니다. gzip 형식을 원하면 gzencode을 사용해야합니다. 원시 수축 양식을 원하면 gzdeflate을 사용해야합니다. 따라서 두 함수는 gz으로 시작하지만 gzip 형식을 생성하는 함수는 하나뿐입니다.

그 중 어느 것도 zip 형식을 생성하지 않습니다. symcbean에서 언급했듯이 ZipArchive class을 사용합니다.

+0

완벽을 기하기 위해 .... PHP는 ZIP 확장자를 가진 ZIP 파일을 지원합니다 : http://php.net/manual/en/book.zip.php – symcbean

관련 문제