= 1 && $level <= 9) $type = "g"; elseif($level > 9) die("Compression level set too high"); else $type = "n"; } if($type == "g") { $this->compr_lvl_last = 8; RETURN gzdeflate($data,$level); } elseif($type == "b") { $this->compr_lvl_last = 12; RETURN bzcompress($data,$level); } else { $this->compr_lvl_last = 0; RETURN $data; } } public function zl_add_file($data,$filename,$comp = "") { global $settings; // if we already created a file, we'll make sure it'll be there in the coming zipfile ;) // first, checking some data if(strlen($filename) > pow(2,16)-1) die("Filename $filename too long"); // ooh, dirty... dieing, will change later if(strlen($data) > pow(2,32)-1) die("File $filename larger then 2GB, cannot continue"); // another one, naughty me ;) // $comp has a special format. the first character tells me about the compression, the second one represents the level if(strlen($comp) == 1) { // they still use the old method, assuming gzip $comp_type = "n"; $comp_lvl = 0; if($comp >= 1 && $comp <= 9) { $comp_type = "g"; $comp_lvl = $comp; } } else { $comp_lvl = 5; $comp_type = "n"; // hmmm, the new method. Is it valid? if ($comp[0] == "b" OR $comp[0] == "g" OR $comp[0] == "n") $comp_type = $comp[0]; if (preg_match("/[0-9]/i",$comp[1])) $comp_lvl = $comp[1]; } // ok, let's get this bitch tidy: // first adding a file $compressed = $this->zl_compress($data,$comp_lvl,$comp_type); $uncompressed = strlen($data); $newfile = "\x50\x4b\x03\x04"; // Header $newfile .="\x00\x00"; // Version needed to extract $newfile .="\x00\x00"; // general purpose bit flag $newfile .=pack("v",$this->compr_lvl_last); // compression method $newfile .=pack("v",dostime_get($settings['offset'])); // last mod file time $newfile .=pack("v",dosdate_get($settings['offset'])); // last mod file date $newfile .=pack("V",crc32($data)); // CRC32 $newfile .=pack("V",strlen($compressed)); // compressed filesize $newfile .=pack("V",$uncompressed); // uncompressed filesize $newfile .=pack("v",strlen($filename)); // length of filename $newfile .="\x00\x00"; // some sort of extra field ;) $newfile .=$filename; $newfile .=$compressed; $this->archive .= $newfile; // some 'statistics' for this file ;) $this->archive_filecount++; $idf = $this->archive_filecount - 1; $this->archive_fileinfo[$this->archive_filecount]['comp_type'] = $this->compr_lvl_last; $this->archive_fileinfo[$this->archive_filecount]['size'] = strlen($data); $this->archive_fileinfo[$this->archive_filecount]['size_comp'] = strlen($compressed); $this->archive_fileinfo[$this->archive_filecount]['pkg_size'] = strlen($newfile); if(!empty($this->archive_fileinfo[$idf]['local_stats_pointer'])) { $this->archive_fileinfo[$this->archive_filecount]['local_stats_pointer'] = $this->archive_fileinfo[$idf]['local_stats_pointer'] + $this->archive_fileinfo[$idf]['pkg_size'] + 1; // HACKERDIEHACK! only way to get local_stats_pointer to '0' (for now) in zl_pack } else { $this->archive_fileinfo[$this->archive_filecount]['local_stats_pointer'] = 1; } $this->archive_fileinfo[$this->archive_filecount]['name'] = $filename; $this->archive_fileinfo[$this->archive_filecount]['crc32'] = crc32($data); unset($file,$compressed); // to avoid having data in our memory double ;) RETURN TRUE; } public function zl_pack($comment) { global $settings; if(strlen($comment) > pow(2,16)-1) die("Comment too long"); // that's 3 // now the central directory structure start for($x=1;$x <= $this->archive_filecount;$x++) { $file_stats = $this->archive_fileinfo[$x]; $cdss .= "\x50\x4b\x01\x02"; // Header $cdss .="\x00\x00"; // version made by $cdss .="\x00\x00"; // version needed to extract $cdss .="\x00\x00"; // general purpose bit flag $cdss .=pack("v",$file_stats['comp_type']); // compression method $cdss .=pack("v",dostime_get($settings['offset'])); // last mod file time $cdss .=pack("v",dosdate_get($settings['offset'])); // last mod file date $cdss .=pack("V",$file_stats['crc32']); // CRC32 $cdss .=pack("V",$file_stats['size_comp']); // compressed size $cdss .=pack("V",$file_stats['size']); // uncompressed size $cdss .=pack("v",strlen($file_stats['name'])); // file name length $cdss .="\x00\x00"; // extra field length $cdss .="\x00\x00"; // file comment length $cdss .="\x00\x00"; // disk number start $cdss .="\x00\x00"; // internal file attributes $cdss .="\x00\x00\x00\x00"; // external file attributes $cdss .=pack("V",$file_stats['local_stats_pointer']-$x); // relative offset of local header // aka: The local_stats_pointer hack: part 2, see above $cdss .=$file_stats['name']; } // and final, the ending central directory structure! "WHOO HOOW!" (©Blur, 1998) $cdse = "\x50\x4b\x05\x06"; // Header $cdse .="\x00\x00"; // number of this disk $cdse .="\x00\x00"; // number of the disk with the start of the central directory $cdse .=pack("v",$this->archive_filecount); // total number of entries in the central directory on this disk $cdse .=pack("v",$this->archive_filecount); // total number of entries in the central directory $cdse .=pack("V",strlen($cdss)); // size of the central directory $cdse .=pack("V",strlen($this->archive)); // offset of start of central directory with respect to the starting disk number $cdse .=pack("v",strlen($comment)); // .ZIP file comment length $cdse .=$comment; return $this->archive.$cdss.$cdse; } public function zl_index_file($file) { $fp = @fopen($file,"rb"); // ok, as we don't know what the exact position of everything is, we'll have to "guess" using the default sizes //and set values in the zipfile. Basicly this means I have to go through the entire file, could take some time. //Let's see if I can create an algorithm powerful enough. if(!$fp) die("File empty"); $continue = 1; $file_count = 0; while($continue) { $content = fread($fp,30); $id = substr($content,0,4); if ($id == "\x50\x4b\x03\x04") { // the method used is quite simple, load a file in the memory, and walk through several parts of it using substr // As the PKZip format uses mostly fixed sizes for information, this isn't too hard to implement // First I want everything tested, before I start giving this function a nice place in the class $temp[$file_count]['file-size'] = ascii2dec(substr($content,18,4)); $temp[$file_count]['filename-size'] = ascii2dec(substr($content,26,2)); $temp[$file_count]['compression-type'] = ascii2dec(substr($content,8,2)); $temp[$file_count]['crc'] = ascii2dec(substr($content,14,4)); $temp[$file_count]['dostime'] = dostime_return(substr($content,10,2)); $temp[$file_count]['dosdate'] = dosdate_return(substr($content,12,2)); $temp[$file_count]['filename'] = fread($fp,$temp[$file_count]['filename-size']); // As the Zip format does not include Content type headers, I'll create a nice little array with // extension/content type, and a small function to retreive it $temp[$file_count]['file-type'] = ext2cth($temp[$file_count]['filename']); $temp[$file_count]['content'] = fread($fp,$temp[$file_count]['file-size']); if ($temp[$file_count]['compression-type'] != 0 AND $temp[$file_count]['compression-type'] != 8 AND $temp[$file_count]['compression-type'] != 12) { $temp[$file_count]['lasterror'] = "Compression type not supported"; } else { if($temp[$file_count]['compression-type'] == 8) { $temp[$file_count]['content'] = gzinflate($temp[$file_count]['content']); } elseif ($temp[$file_count]['compression-type'] == 12) { $temp[$file_count]['content'] = bzdecompress($temp[$file_count]['content']); } $verify = crc32($temp[$file_count]['content']); if ($verify != $temp[$file_count]['crc']) { $temp[$file_count]['lasterror'] = "CRC did not match, possibly this zipfile is damaged"; } } $file_count++; } else { $continue = 0; } } fclose($fp); unset($fp,$content,$file_count); return $temp; } } function zipImgsFiles($source,$zip) { $folder = opendir($source==""?"./":$source); while($file = readdir($folder)) { if ($file == '.' || $file == '..') { continue; } if(is_dir($source.$file)) { zipImgsFiles($source.$file."/",$zip); } else { $zip->zl_add_file(file_get_contents($source.$file),$source.$file,"g0"); } } closedir($folder); return 1; } function zipFromLocation($location,$name="dhtmlx"){ //echo $location; chdir($location); $zip = new Ziplib; $zip->zl_add_file(file_get_contents("dhtmlx.js"),$name.'.js',"g9"); $zip->zl_add_file(file_get_contents("dhtmlx.css"),$name.'.css',"g9"); $zip->zl_add_file(file_get_contents("manifest.txt"),'manifest.txt',"g9"); zipImgsFiles("imgs/",$zip); $files = @scandir("./types"); if (count($files) > 2) zipImgsFiles("types/",$zip); $outZip = $zip->zl_pack(""); return $outZip; } ?>