1<?php
2
3$disapproval_ಠ_ಠ_of_php = 'unicode var';
4
5$test = function($a) { $lambda = 1; }
6
7/**
8 *  Zip class file
9 *
10 *  @package     fnord.bb
11 *  @subpackage  archive
12 */
13
14// Unlock?
15if(!defined('UNLOCK') || !UNLOCK)
16  die();
17
18// Load the parent archive class
19require_once(ROOT_PATH.'/classes/archive.class.php');
20
21class Zip\Zippಠ_ಠ_ {
22
23}
24
25/**
26 *  Zip class
27 *
28 *  @author      Manni <manni@fnord.name>
29 *  @copyright   Copyright (c) 2006, Manni
30 *  @version     1.0
31 *  @link        http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
32 *  @link        http://mannithedark.is-a-geek.net/
33 *  @since       1.0
34 *  @package     fnord.bb
35 *  @subpackage  archive
36 */
37class Zip extends Archive {
38 /**
39  *  Outputs the zip file
40  *
41  *  This function creates the zip file with the dirs and files given.
42  *  If the optional parameter $file is given, the zip file is will be
43  *  saved at that location. Otherwise the function returns the zip file's content.
44  *
45  *  @access                   public
46  *
47  *  @link                     http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
48  *  @param  string $filename  The path where the zip file will be saved
49  *
50  *  @return bool|string       Returns either true if the fil is sucessfully created or the content of the zip file
51  */
52  function out($filename = false) {
53    // Empty output
54    $file_data = array(); // Data of the file part
55    $cd_data   = array(); // Data of the central directory
56
57    // Sort dirs and files by path length
58    uksort($this->dirs,  'sort_by_length');
59    uksort($this->files, 'sort_by_length');
60
61    // Handle dirs
62    foreach($this->dirs as $dir) {
63      $dir .= '/';
64      // File part
65
66      // Reset dir data
67      $dir_data = '';
68
69      // Local file header
70      $dir_data .= "\x50\x4b\x03\x04";      // Local file header signature
71      $dir_data .= pack("v", 10);           // Version needed to extract
72      $dir_data .= pack("v", 0);            // General purpose bit flag
73      $dir_data .= pack("v", 0);            // Compression method
74      $dir_data .= pack("v", 0);            // Last mod file time
75      $dir_data .= pack("v", 0);            // Last mod file date
76      $dir_data .= pack("V", 0);            // crc-32
77      $dir_data .= pack("V", 0);            // Compressed size
78      $dir_data .= pack("V", 0);            // Uncompressed size
79      $dir_data .= pack("v", strlen($dir)); // File name length
80      $dir_data .= pack("v", 0);            // Extra field length
81
82      $dir_data .= $dir;                    // File name
83      $dir_data .= '';                      // Extra field (is empty)
84
85      // File data
86      $dir_data .= '';                      // Dirs have no file data
87
88      // Data descriptor
89      $dir_data .= pack("V", 0);            // crc-32
90      $dir_data .= pack("V", 0);            // Compressed size
91      $dir_data .= pack("V", 0);            // Uncompressed size
92
93      // Save current offset
94      $offset = strlen(implode('', $file_data));
95
96      // Append dir data to the file part
97      $file_data[] = $dir_data;
98
99      // Central directory
100
101      // Reset dir data
102      $dir_data = '';
103
104      // File header
105      $dir_data .= "\x50\x4b\x01\x02";      // Local file header signature
106      $dir_data .= pack("v", 0);            // Version made by
107      $dir_data .= pack("v", 10);           // Version needed to extract
108      $dir_data .= pack("v", 0);            // General purpose bit flag
109      $dir_data .= pack("v", 0);            // Compression method
110      $dir_data .= pack("v", 0);            // Last mod file time
111      $dir_data .= pack("v", 0);            // Last mod file date
112      $dir_data .= pack("V", 0);            // crc-32
113      $dir_data .= pack("V", 0);            // Compressed size
114      $dir_data .= pack("V", 0);            // Uncompressed size
115      $dir_data .= pack("v", strlen($dir)); // File name length
116      $dir_data .= pack("v", 0);            // Extra field length
117      $dir_data .= pack("v", 0);            // File comment length
118      $dir_data .= pack("v", 0);            // Disk number start
119      $dir_data .= pack("v", 0);            // Internal file attributes
120      $dir_data .= pack("V", 16);           // External file attributes
121      $dir_data .= pack("V", $offset);      // Relative offset of local header
122
123      $dir_data .= $dir;                    // File name
124      $dir_data .= '';                      // Extra field (is empty)
125      $dir_data .= '';                      // File comment (is empty)
126
127      /*
128      // Data descriptor
129      $dir_data .= pack("V", 0);            // crc-32
130      $dir_data .= pack("V", 0);            // Compressed size
131      $dir_data .= pack("V", 0);            // Uncompressed size
132      */
133
134      // Append dir data to the central directory data
135      $cd_data[] = $dir_data;
136    }
137
138    // Handle files
139    foreach($this->files as $name => $file) {
140      // Get values
141      $content = $file[0];
142
143      // File part
144
145      // Reset file data
146      $fd = '';
147
148      // Detect possible compressions
149      // Use deflate
150      if(function_exists('gzdeflate')) {
151        $method = 8;
152
153        // Compress file content
154        $compressed_data = gzdeflate($content);
155
156      // Use bzip2
157      } elseif(function_exists('bzcompress')) {
158        $method = 12;
159
160        // Compress file content
161        $compressed_data = bzcompress($content);
162
163      // No compression
164      } else {
165        $method = 0;
166
167        // Do not compress the content :P
168        $compressed_data = $content;
169      }
170
171      // Local file header
172      $fd .= "\x50\x4b\x03\x04";                  // Local file header signature
173      $fd .= pack("v", 20);                       // Version needed to extract
174      $fd .= pack("v", 0);                        // General purpose bit flag
175      $fd .= pack("v", $method);                  // Compression method
176      $fd .= pack("v", 0);                        // Last mod file time
177      $fd .= pack("v", 0);                        // Last mod file date
178      $fd .= pack("V", crc32($content));          // crc-32
179      $fd .= pack("V", strlen($compressed_data)); // Compressed size
180      $fd .= pack("V", strlen($content));         // Uncompressed size
181      $fd .= pack("v", strlen($name));            // File name length
182      $fd .= pack("v", 0);                        // Extra field length
183
184      $fd .= $name;                               // File name
185      $fd .= '';                                  // Extra field (is empty)
186
187      // File data
188      $fd .= $compressed_data;
189
190      // Data descriptor
191      $fd .= pack("V", crc32($content));          // crc-32
192      $fd .= pack("V", strlen($compressed_data)); // Compressed size
193      $fd .= pack("V", strlen($content));         // Uncompressed size
194
195      // Save current offset
196      $offset = strlen(implode('', $file_data));
197
198      // Append file data to the file part
199      $file_data[] = $fd;
200
201      // Central directory
202
203      // Reset file data
204      $fd = '';
205
206      // File header
207      $fd .= "\x50\x4b\x01\x02";                  // Local file header signature
208      $fd .= pack("v", 0);                        // Version made by
209      $fd .= pack("v", 20);                       // Version needed to extract
210      $fd .= pack("v", 0);                        // General purpose bit flag
211      $fd .= pack("v", $method);                  // Compression method
212      $fd .= pack("v", 0);                        // Last mod file time
213      $fd .= pack("v", 0);                        // Last mod file date
214      $fd .= pack("V", crc32($content));          // crc-32
215      $fd .= pack("V", strlen($compressed_data)); // Compressed size
216      $fd .= pack("V", strlen($content));         // Uncompressed size
217      $fd .= pack("v", strlen($name));            // File name length
218      $fd .= pack("v", 0);                        // Extra field length
219      $fd .= pack("v", 0);                        // File comment length
220      $fd .= pack("v", 0);                        // Disk number start
221      $fd .= pack("v", 0);                        // Internal file attributes
222      $fd .= pack("V", 32);                       // External file attributes
223      $fd .= pack("V", $offset);                  // Relative offset of local header
224
225      $fd .= $name;                               // File name
226      $fd .= '';                                  // Extra field (is empty)
227      $fd .= '';                                  // File comment (is empty)
228
229      /*
230      // Data descriptor
231      $fd .= pack("V", crc32($content));          // crc-32
232      $fd .= pack("V", strlen($compressed_data)); // Compressed size
233      $fd .= pack("V", strlen($content));         // Uncompressed size
234      */
235
236      // Append file data to the central directory data
237      $cd_data[] = $fd;
238    }
239
240    // Digital signature
241    $digital_signature = '';
242    $digital_signature .= "\x50\x4b\x05\x05";  // Header signature
243    $digital_signature .= pack("v", 0);        // Size of data
244    $digital_signature .= '';                  // Signature data (is empty)
245
246    $tmp_file_data = implode('', $file_data);  // File data
247    $tmp_cd_data   = implode('', $cd_data).    // Central directory
248                     $digital_signature;       // Digital signature
249
250    // End of central directory
251    $eof_cd = '';
252    $eof_cd .= "\x50\x4b\x05\x06";                // End of central dir signature
253    $eof_cd .= pack("v", 0);                      // Number of this disk
254    $eof_cd .= pack("v", 0);                      // Number of the disk with the start of the central directory
255    $eof_cd .= pack("v", count($cd_data));        // Total number of entries in the central directory on this disk
256    $eof_cd .= pack("v", count($cd_data));        // Total number of entries in the central directory
257    $eof_cd .= pack("V", strlen($tmp_cd_data));   // Size of the central directory
258    $eof_cd .= pack("V", strlen($tmp_file_data)); // Offset of start of central directory with respect to the starting disk number
259    $eof_cd .= pack("v", 0);                      // .ZIP file comment length
260    $eof_cd .= '';                                // .ZIP file comment (is empty)
261
262    // Content of the zip file
263    $data = $tmp_file_data.
264            // $extra_data_record.
265            $tmp_cd_data.
266            $eof_cd;
267
268    // Return content?
269    if(!$filename)
270      return $data;
271
272    // Write to file
273    return file_put_contents($filename, $data);
274  }
275
276 /**
277  *  Load a zip file
278  *
279  *  This function loads the files and dirs from a zip file from the harddrive.
280  *
281  *  @access                public
282  *
283  *  @param  string $file   The path to the zip file
284  *  @param  bool   $reset  Reset the files and dirs before adding the zip file's content?
285  *
286  *  @return bool           Returns true if the file was loaded sucessfully
287  */
288  function load_file($file, $reset = true) {
289    // Check whether the file exists
290    if(!file_exists($file))
291      return false;
292
293    // Load the files content
294    $content = @file_get_contents($file);
295
296    // Return false if the file cannot be opened
297    if(!$content)
298      return false;
299
300    // Read the zip
301    return $this->load_string($content, $reset);
302  }
303
304 /**
305  *  Load a zip string
306  *
307  *  This function loads the files and dirs from a string
308  *
309  *  @access                 public
310  *
311  *  @param  string $string  The string the zip is generated from
312  *  @param  bool   $reset   Reset the files and dirs before adding the zip file's content?
313  *
314  *  @return bool            Returns true if the string was loaded sucessfully
315  */
316  function load_string($string, $reset = true) {
317    // Reset the zip?
318    if($reset) {
319      $this->dirs  = array();
320      $this->files = array();
321    }
322
323    // Get the starting position of the end of central directory record
324    $start = strpos($string, "\x50\x4b\x05\x06");
325
326    // Error
327    if($start === false)
328      die('Could not find the end of central directory record');
329
330    // Get the ecdr
331    $eof_cd = substr($string, $start+4, 18);
332
333    // Unpack the ecdr infos
334    $eof_cd = unpack('vdisc1/'.
335                     'vdisc2/'.
336                     'ventries1/'.
337                     'ventries2/'.
338                     'Vsize/'.
339                     'Voffset/'.
340                     'vcomment_lenght', $eof_cd);
341
342    // Do not allow multi disc zips
343    if($eof_cd['disc1'] != 0)
344      die('multi disk stuff is not yet implemented :/');
345
346    // Save the interesting values
347    $cd_entries = $eof_cd['entries1'];
348    $cd_size    = $eof_cd['size'];
349    $cd_offset  = $eof_cd['offset'];
350
351    // Get the central directory record
352    $cdr = substr($string, $cd_offset, $cd_size);
353
354    // Reset the position and the list of the entries
355    $pos     = 0;
356    $entries = array();
357
358    // Handle cdr
359    while($pos < strlen($cdr)) {
360      // Check header signature
361      // Digital signature
362      if(substr($cdr, $pos, 4) == "\x50\x4b\x05\x05") {
363        // Get digital signature size
364        $tmp_info = unpack('vsize', substr($cdr, $pos + 4, 2));
365
366        // Read out the digital signature
367        $digital_sig = substr($header, $pos + 6, $tmp_info['size']);
368
369        break;
370      }
371
372      // Get file header
373      $header = substr($cdr, $pos, 46);
374
375      // Unpack the header information
376      $header_info = @unpack('Vheader/'.
377                             'vversion_made_by/'.
378                             'vversion_needed/'.
379                             'vgeneral_purpose/'.
380                             'vcompression_method/'.
381                             'vlast_mod_time/'.
382                             'vlast_mod_date/'.
383                             'Vcrc32/'.
384                             'Vcompressed_size/'.
385                             'Vuncompressed_size/'.
386                             'vname_length/'.
387                             'vextra_length/'.
388                             'vcomment_length/'.
389                             'vdisk_number/'.
390                             'vinternal_attributes/'.
391                             'Vexternal_attributes/'.
392                             'Voffset',
393                             $header);
394
395      // Valid header?
396      if($header_info['header'] != 33639248)
397        return false;
398
399      // New position
400      $pos += 46;
401
402      // Read out the file name
403      $header_info['name'] = substr($cdr, $pos, $header_info['name_length']);
404
405      // New position
406      $pos += $header_info['name_length'];
407
408      // Read out the extra stuff
409      $header_info['extra'] = substr($cdr, $pos, $header_info['extra_length']);
410
411      // New position
412      $pos += $header_info['extra_length'];
413
414      // Read out the comment
415      $header_info['comment'] = substr($cdr, $pos, $header_info['comment_length']);
416
417      // New position
418      $pos += $header_info['comment_length'];
419
420      // Append this file/dir to the entry list
421      $entries[] = $header_info;
422    }
423
424    // Check whether all entries where read sucessfully
425    if(count($entries) != $cd_entries)
426      return false;
427
428    // Handle files/dirs
429    foreach($entries as $entry) {
430      // Is a dir?
431      if($entry['external_attributes'] & 16) {
432        $this->add_dir($entry['name']);
433        continue;
434      }
435
436      // Get local file header
437      $header = substr($string, $entry['offset'], 30);
438
439      // Unpack the header information
440      $header_info = @unpack('Vheader/'.
441                             'vversion_needed/'.
442                             'vgeneral_purpose/'.
443                             'vcompression_method/'.
444                             'vlast_mod_time/'.
445                             'vlast_mod_date/'.
446                             'Vcrc32/'.
447                             'Vcompressed_size/'.
448                             'Vuncompressed_size/'.
449                             'vname_length/'.
450                             'vextra_length',
451                             $header);
452
453      // Valid header?
454      if($header_info['header'] != 67324752)
455        return false;
456
457      // Get content start position
458      $start = $entry['offset'] + 30 + $header_info['name_length'] + $header_info['extra_length'];
459
460      // Get the compressed data
461      $data = substr($string, $start, $header_info['compressed_size']);
462
463      // Detect compression type
464      switch($header_info['compression_method']) {
465        // No compression
466        case 0:
467          // Ne decompression needed
468          $content = $data;
469          break;
470
471        // Gzip
472        case 8:
473          if(!function_exists('gzinflate'))
474            return false;
475
476          // Uncompress data
477          $content = gzinflate($data);
478          break;
479
480        // Bzip2
481        case 12:
482          if(!function_exists('bzdecompress'))
483            return false;
484
485          // Decompress data
486          $content = bzdecompress($data);
487          break;
488
489        // Compression not supported -> error
490        default:
491          return false;
492      }
493
494      // Try to add file
495      if(!$this->add_file($entry['name'], $content))
496        return false;
497    }
498
499    return true;
500  }
501}
502
503function &byref() {
504    $x = array();
505    return $x;
506}
507
508// Test highlighting of magic methods and variables
509class MagicClass {
510  public $magic_str;
511  public $ordinary_str;
512
513  public function __construct($some_var) {
514    $this->magic_str = __FILE__;
515    $this->ordinary_str = $some_var;
516  }
517
518  public function __toString() {
519    return $this->magic_str;
520  }
521
522  public function nonMagic() {
523    return $this->ordinary_str;
524  }
525}
526
527$magic = new MagicClass(__DIR__);
528__toString();
529$magic->nonMagic();
530$magic->__toString();
531
532     echo <<<EOF
533
534     Test the heredocs...
535
536     EOF;
537
538echo <<<"some_delimiter"
539more heredoc testing
540continues on this line
541some_delimiter;
542
543?>
544
545