source: documentation/trunk/packages/dokuwiki-2011-05-25a/inc/ZipLib.class.php@ 25027

Last change on this file since 25027 was 25027, checked in by jmt12, 12 years ago

Adding the packages directory, and within it a configured version of dokuwiki all ready to run

File size: 17.4 KB
Line 
1<?php
2
3/**
4 * @author bouchon
5 * @link http://dev.maxg.info
6 * @link http://forum.maxg.info
7 *
8 * Modified for Dokuwiki
9 * @author Christopher Smith <[email protected]>
10 */
11class ZipLib {
12
13 var $datasec;
14 var $ctrl_dir = array();
15 var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
16 var $old_offset = 0;
17 var $dirs = Array(".");
18
19 function get_List($zip_name) {
20 $zip = @fopen($zip_name, 'rb');
21 if(!$zip) return(0);
22 $centd = $this->ReadCentralDir($zip,$zip_name);
23
24 @rewind($zip);
25 @fseek($zip, $centd['offset']);
26
27 for ($i=0; $i<$centd['entries']; $i++) {
28 $header = $this->ReadCentralFileHeaders($zip);
29 $header['index'] = $i;
30
31 $info['filename'] = $header['filename'];
32 $info['stored_filename'] = $header['stored_filename'];
33 $info['size'] = $header['size'];
34 $info['compressed_size'] = $header['compressed_size'];
35 $info['crc'] = strtoupper(dechex( $header['crc'] ));
36 $info['mtime'] = $header['mtime'];
37 $info['comment'] = $header['comment'];
38 $info['folder'] = ($header['external']==0x41FF0010||$header['external']==16)?1:0;
39 $info['index'] = $header['index'];
40 $info['status'] = $header['status'];
41 $ret[]=$info;
42
43 unset($header);
44 }
45 return $ret;
46 }
47
48 function Add($files,$compact) {
49 if(!is_array($files[0])) $files=Array($files);
50
51 for($i=0;$files[$i];$i++){
52 $fn = $files[$i];
53 if(!in_Array(dirname($fn[0]),$this->dirs))
54 $this->add_Dir(dirname($fn[0]));
55 if(basename($fn[0]))
56 $ret[basename($fn[0])]=$this->add_File($fn[1],$fn[0],$compact);
57 }
58 return $ret;
59 }
60
61 /**
62 * Zips recursively the $folder directory, from the $basedir directory
63 */
64 function Compress($folder, $basedir=null, $parent=null) {
65 $full_path = $basedir."/".$parent.$folder;
66 $zip_path = $parent.$folder;
67 if ($zip_path) {
68 $zip_path .= "/";
69 $this->add_dir($zip_path);
70 }
71 $dir = new DirectoryIterator($full_path);
72 foreach($dir as $file) {
73 if(!$file->isDot()) {
74 $filename = $file->getFilename();
75 if($file->isDir()) {
76 $this->Compress($filename, $basedir, $zip_path);
77 } else {
78 $content = join('', file($full_path.'/'.$filename));
79 $this->add_File($content, $zip_path.$filename);
80 }
81 }
82 }
83 }
84
85 /**
86 * Returns the Zip file
87 */
88 function get_file() {
89 $data = implode('', $this -> datasec);
90 $ctrldir = implode('', $this -> ctrl_dir);
91
92 return $data . $ctrldir . $this -> eof_ctrl_dir .
93 pack('v', count($this->ctrl_dir)).pack('v', count($this->ctrl_dir)).
94 pack('V', strlen($ctrldir)) . pack('V', strlen($data)) . "\x00\x00";
95 }
96
97 function add_dir($name) {
98 $name = str_replace("\\", "/", $name);
99 $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
100
101 $fr .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name) );
102 $fr .= pack("v", 0 ).$name.pack("V", 0).pack("V", 0).pack("V", 0);
103 $this -> datasec[] = $fr;
104
105 $new_offset = strlen(implode("", $this->datasec));
106
107 $cdrec = "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
108 $cdrec .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name) );
109 $cdrec .= pack("v", 0 ).pack("v", 0 ).pack("v", 0 ).pack("v", 0 );
110 $ext = "\xff\xff\xff\xff";
111 $cdrec .= pack("V", 16 ).pack("V", $this -> old_offset ).$name;
112
113 $this -> ctrl_dir[] = $cdrec;
114 $this -> old_offset = $new_offset;
115 $this -> dirs[] = $name;
116 }
117
118 /**
119 * Add a file named $name from a string $data
120 */
121 function add_File($data, $name, $compact = 1) {
122 $name = str_replace('\\', '/', $name);
123 $dtime = dechex($this->DosTime());
124
125 $hexdtime = pack('H*',$dtime[6].$dtime[7].
126 $dtime[4].$dtime[5].
127 $dtime[2].$dtime[3].
128 $dtime[0].$dtime[1]);
129
130 if($compact){
131 $fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".$hexdtime;
132 }else{
133 $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00".$hexdtime;
134 }
135 $unc_len = strlen($data);
136 $crc = crc32($data);
137
138 if($compact){
139 $zdata = gzcompress($data);
140 $c_len = strlen($zdata);
141 $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
142 }else{
143 $zdata = $data;
144 }
145 $c_len=strlen($zdata);
146 $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
147 $fr .= pack('v', strlen($name)).pack('v', 0).$name.$zdata;
148
149 $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
150
151 $this -> datasec[] = $fr;
152 $new_offset = strlen(implode('', $this->datasec));
153 if($compact) {
154 $cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00";
155 } else {
156 $cdrec = "\x50\x4b\x01\x02\x14\x00\x0a\x00\x00\x00\x00\x00";
157 }
158 $cdrec .= $hexdtime.pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
159 $cdrec .= pack('v', strlen($name) ).pack('v', 0 ).pack('v', 0 );
160 $cdrec .= pack('v', 0 ).pack('v', 0 ).pack('V', 32 );
161 $cdrec .= pack('V', $this -> old_offset );
162
163 $this -> old_offset = $new_offset;
164 $cdrec .= $name;
165 $this -> ctrl_dir[] = $cdrec;
166 return true;
167 }
168
169 function DosTime() {
170 $timearray = getdate();
171 if ($timearray['year'] < 1980) {
172 $timearray['year'] = 1980;
173 $timearray['mon'] = 1;
174 $timearray['mday'] = 1;
175 $timearray['hours'] = 0;
176 $timearray['minutes'] = 0;
177 $timearray['seconds'] = 0;
178 }
179 return (($timearray['year'] - 1980) << 25) |
180 ($timearray['mon'] << 21) |
181 ($timearray['mday'] << 16) |
182 ($timearray['hours'] << 11) |
183 ($timearray['minutes'] << 5) |
184 ($timearray['seconds'] >> 1);
185 }
186
187 /**
188 * Extract a zip file $zn to the $to directory
189 */
190 function Extract ( $zn, $to, $index = Array(-1) ) {
191 if(!@is_dir($to)) $this->_mkdir($to);
192 $ok = 0;
193 $zip = @fopen($zn,'rb');
194 if(!$zip) return(-1);
195 $cdir = $this->ReadCentralDir($zip,$zn);
196 $pos_entry = $cdir['offset'];
197
198 if(!is_array($index)){
199 $index = array($index);
200 }
201 for($i=0; isset($index[$i]);$i++){
202 if(intval($index[$i])!=$index[$i]||$index[$i]>$cdir['entries'])
203 return(-1);
204 }
205
206 for ($i=0; $i<$cdir['entries']; $i++) {
207 @fseek($zip, $pos_entry);
208 $header = $this->ReadCentralFileHeaders($zip);
209 $header['index'] = $i;
210 $pos_entry = ftell($zip);
211 @rewind($zip);
212 fseek($zip, $header['offset']);
213 if(in_array("-1",$index)||in_array($i,$index)){
214 $stat[$header['filename']]=$this->ExtractFile($header, $to, $zip);
215 }
216 }
217 fclose($zip);
218 return $stat;
219 }
220
221 function ReadFileHeader($zip, $header) {
222 $binary_data = fread($zip, 30);
223 $data = unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);
224
225 $header['filename'] = fread($zip, $data['filename_len']);
226 if ($data['extra_len'] != 0) {
227 $header['extra'] = fread($zip, $data['extra_len']);
228 } else {
229 $header['extra'] = '';
230 }
231
232 $header['compression'] = $data['compression'];
233 foreach (array('size','compressed_size','crc') as $hd) { // On ODT files, these headers are 0. Keep the previous value.
234 if ($data[$hd] != 0) $header[$hd] = $data[$hd];
235 }
236 $header['flag'] = $data['flag'];
237 $header['mdate'] = $data['mdate'];
238 $header['mtime'] = $data['mtime'];
239
240 if ($header['mdate'] && $header['mtime']){
241 $hour = ($header['mtime']&0xF800)>>11;
242 $minute = ($header['mtime']&0x07E0)>>5;
243 $seconde = ($header['mtime']&0x001F)*2;
244 $year = (($header['mdate']&0xFE00)>>9)+1980;
245 $month = ($header['mdate']&0x01E0)>>5;
246 $day = $header['mdate']&0x001F;
247 $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
248 } else {
249 $header['mtime'] = time();
250 }
251
252 $header['stored_filename'] = $header['filename'];
253 $header['status'] = "ok";
254 return $header;
255 }
256
257 function ReadCentralFileHeaders($zip){
258 $binary_data = fread($zip, 46);
259 $header = unpack('vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $binary_data);
260
261 if ($header['filename_len'] != 0){
262 $header['filename'] = fread($zip,$header['filename_len']);
263 }else{
264 $header['filename'] = '';
265 }
266
267 if ($header['extra_len'] != 0){
268 $header['extra'] = fread($zip, $header['extra_len']);
269 }else{
270 $header['extra'] = '';
271 }
272
273 if ($header['comment_len'] != 0){
274 $header['comment'] = fread($zip, $header['comment_len']);
275 }else{
276 $header['comment'] = '';
277 }
278
279 if ($header['mdate'] && $header['mtime']) {
280 $hour = ($header['mtime'] & 0xF800) >> 11;
281 $minute = ($header['mtime'] & 0x07E0) >> 5;
282 $seconde = ($header['mtime'] & 0x001F)*2;
283 $year = (($header['mdate'] & 0xFE00) >> 9) + 1980;
284 $month = ($header['mdate'] & 0x01E0) >> 5;
285 $day = $header['mdate'] & 0x001F;
286 $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
287 } else {
288 $header['mtime'] = time();
289 }
290
291 $header['stored_filename'] = $header['filename'];
292 $header['status'] = 'ok';
293 if (substr($header['filename'], -1) == '/') $header['external'] = 0x41FF0010;
294
295 return $header;
296 }
297
298 function ReadCentralDir($zip,$zip_name) {
299 $size = filesize($zip_name);
300 if ($size < 277){
301 $maximum_size = $size;
302 } else {
303 $maximum_size=277;
304 }
305
306 @fseek($zip, $size-$maximum_size);
307 $pos = ftell($zip);
308 $bytes = 0x00000000;
309
310 while ($pos < $size) {
311 $byte = @fread($zip, 1);
312 $bytes=(($bytes << 8) & 0xFFFFFFFF) | Ord($byte);
313 if ($bytes == 0x504b0506){
314 $pos++;
315 break;
316 }
317 $pos++;
318 }
319
320 $data=unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size',
321 fread($zip, 18));
322
323 if ($data['comment_size'] != 0){
324 $centd['comment'] = fread($zip, $data['comment_size']);
325 } else {
326 $centd['comment'] = '';
327 }
328 $centd['entries'] = $data['entries'];
329 $centd['disk_entries'] = $data['disk_entries'];
330 $centd['offset'] = $data['offset'];
331 $centd['disk_start'] = $data['disk_start'];
332 $centd['size'] = $data['size'];
333 $centd['disk'] = $data['disk'];
334 return $centd;
335 }
336
337 function ExtractFile($header,$to,$zip) {
338 $header = $this->readfileheader($zip, $header);
339
340 if(substr($to,-1)!="/") $to.="/";
341 if(substr($header['filename'],-1)=="/") {
342 $this->_mkdir($to.$header['filename']);
343 return +2;
344 }
345
346 if (!$this->_mkdir($to.dirname($header['filename']))) return (-1);
347
348 if (!array_key_exists("external", $header) || (!($header['external']==0x41FF0010)&&!($header['external']==16))) {
349 if ($header['compression']==0) {
350 $fp = @fopen($to.$header['filename'], 'wb');
351 if(!$fp) return(-1);
352 $size = $header['compressed_size'];
353
354 while ($size != 0) {
355 $read_size = ($size < 2048 ? $size : 2048);
356 $buffer = fread($zip, $read_size);
357 $binary_data = pack('a'.$read_size, $buffer);
358 @fwrite($fp, $binary_data, $read_size);
359 $size -= $read_size;
360 }
361 fclose($fp);
362 touch($to.$header['filename'], $header['mtime']);
363
364 }else{
365 if (!is_dir(dirname($to.$header['filename']))) $this->_mkdir(dirname($to.$header['filename']));
366 $fp = fopen($to.$header['filename'].'.gz','wb');
367 if(!$fp) return(-1);
368 $binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($header['compression']),
369 Chr(0x00), time(), Chr(0x00), Chr(3));
370
371 fwrite($fp, $binary_data, 10);
372 $size = $header['compressed_size'];
373
374 while ($size != 0) {
375 $read_size = ($size < 1024 ? $size : 1024);
376 $buffer = fread($zip, $read_size);
377 $binary_data = pack('a'.$read_size, $buffer);
378 @fwrite($fp, $binary_data, $read_size);
379 $size -= $read_size;
380 }
381
382 $binary_data = pack('VV', $header['crc'], $header['size']);
383 fwrite($fp, $binary_data,8);
384 fclose($fp);
385
386 $gzp = @gzopen($to.$header['filename'].'.gz','rb');
387 if(!$gzp){
388 @gzclose($gzp);
389 @unlink($to.$header['filename']);
390 die("Archive is compressed whereas ZLIB is not enabled.");
391 }
392 $fp = @fopen($to.$header['filename'],'wb');
393 if(!$fp) return(-1);
394 $size = $header['size'];
395
396 while ($size != 0) {
397 $read_size = ($size < 2048 ? $size : 2048);
398 $buffer = gzread($gzp, $read_size);
399 $binary_data = pack('a'.$read_size, $buffer);
400 @fwrite($fp, $binary_data, $read_size);
401 $size -= $read_size;
402 }
403 fclose($fp);
404 gzclose($gzp);
405
406 touch($to.$header['filename'], $header['mtime']);
407 @unlink($to.$header['filename'].'.gz');
408 }
409 }
410 return true;
411 }
412
413 /**
414 * centralize mkdir calls and use dokuwiki io functions
415 *
416 * @author Christopher Smith <[email protected]>
417 */
418 function _mkdir($d) {
419 return io_mkdir_p($d);
420 }
421
422
423 function ExtractStr($zn, $name) {
424 $ok = 0;
425 $zip = @fopen($zn,'rb');
426 if(!$zip) return(null);
427 $cdir = $this->ReadCentralDir($zip,$zn);
428 $pos_entry = $cdir['offset'];
429
430 for ($i=0; $i<$cdir['entries']; $i++) {
431 @fseek($zip, $pos_entry);
432 $header = $this->ReadCentralFileHeaders($zip);
433 $header['index'] = $i;
434 $pos_entry = ftell($zip);
435 @rewind($zip);
436 fseek($zip, $header['offset']);
437 if ($name == $header['stored_filename'] || $name == $header['filename']) {
438 $str = $this->ExtractStrFile($header, $zip);
439 fclose($zip);
440 return $str;
441 }
442
443 }
444 fclose($zip);
445 return null;
446 }
447
448 function ExtractStrFile($header,$zip) {
449 $hdr = $this->readfileheader($zip);
450 $binary_data = '';
451 if (!($header['external']==0x41FF0010) && !($header['external']==16)) {
452 if ($header['compression']==0) {
453 while ($size != 0) {
454 $read_size = ($size < 2048 ? $size : 2048);
455 $buffer = fread($zip, $read_size);
456 $binary_data .= pack('a'.$read_size, $buffer);
457 $size -= $read_size;
458 }
459 return $binary_data;
460 } else {
461 $size = $header['compressed_size'];
462 if ($size == 0) {
463 return '';
464 }
465 //Just in case
466 if ($size > ($this->_ret_bytes(ini_get('memory_limit'))/2)) {
467 die("Compressed file is to huge to be uncompress in memory.");
468 }
469 while ($size != 0)
470 {
471 $read_size = ($size < 2048 ? $size : 2048);
472 $buffer = fread($zip, $read_size);
473 $binary_data .= pack('a'.$read_size, $buffer);
474 $size -= $read_size;
475 }
476 $str = gzinflate($binary_data, $header['size']);
477 if ($header['crc'] == crc32($str)) {
478 return $str;
479 } else {
480 die("Crc Error");
481 }
482 }
483 }
484 return null;
485 }
486
487 function _ret_bytes($val) {
488 $val = trim($val);
489 $last = $val{strlen($val)-1};
490 switch($last) {
491 case 'k':
492 case 'K':
493 return (int) $val * 1024;
494 break;
495 case 'm':
496 case 'M':
497 return (int) $val * 1048576;
498 break;
499 default:
500 return $val;
501 }
502 }
503}
504
Note: See TracBrowser for help on using the repository browser.