1<?php
2// this corrupt zip maker uses portions of Vincent Lascaux's File_Archive to create
3// specifically corrupted zip archives for unit-testing zip support in the phar extension
4// and was modified by Greg Beaver
5/**
6 * ZIP archive writer
7 *
8 * PHP versions 4 and 5
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA
23 *
24 * @category   File Formats
25 * @package    File_Archive
26 * @author     Vincent Lascaux <vincentlascaux@php.net>
27 * @copyright  1997-2005 The PHP Group
28 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL
29 * @link       http://pear.php.net/package/File_Archive
30 */
31
32/**
33 * ZIP archive writer
34 */
35class corrupt_zipmaker
36{
37    /**
38    * @var int Current position in the writer
39    * @access private
40    */
41    var $offset = 0;
42
43    /**
44    * @var string Optional comment to add to the zip
45    * @access private
46    */
47    var $comment = "";
48
49    /**
50    * @var string Data written at the end of the ZIP file
51    * @access private
52    */
53    var $central = "";
54
55    /**
56    * @var string Data written at the start of the ZIP file
57    * @access private
58    */
59    var $start = "";
60
61    /**
62    * Set a comment on the ZIP file
63    */
64    function setComment($comment) { $this->comment = $comment; }
65
66    /**
67    * @param int $time Unix timestamp of the date to convert
68    * @return the date formatted as a ZIP date
69    */
70    function getMTime($time)
71    {
72        $mtime = ($time !== null ? getdate($time) : getdate());
73        $mtime = preg_replace(
74                "/(..){1}(..){1}(..){1}(..){1}/",
75                "\\x\\4\\x\\3\\x\\2\\x\\1",
76                dechex(($mtime['year']-1980<<25)|
77                    ($mtime['mon'    ]<<21)|
78                    ($mtime['mday'   ]<<16)|
79                    ($mtime['hours'  ]<<11)|
80                    ($mtime['minutes']<<5)|
81                    ($mtime['seconds']>>1)));
82        eval('$mtime = "'.$mtime.'";');
83        return $mtime;
84    }
85
86    private function getFileEntry($compmethod, $mtime, $crc32, $complength, $uncomplength, $filename, $data, $corrupt, $fakecomp)
87    {
88        switch ($corrupt) {
89            case null :
90                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $compmethod) .
91                        $mtime .
92                        pack("VVVvv", $crc32, $complength, $uncomplength, strlen($filename), 0x00) .
93                        $filename .
94                        $data;
95                break;
96            case 'compress' :
97                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $fakecomp) .
98                        $mtime .
99                        pack("VVVvv", $crc32, $complength, $uncomplength, strlen($filename), 0x00) .
100                        $filename .
101                        $data;
102                break;
103            case 'encrypt' :
104                $file = "PK\x03\x04\x14\x00\x01\x00" . pack('v', $compmethod) .
105                        $mtime .
106                        pack("VVVvv", $crc32, $complength, $uncomplength, strlen($filename), 0x00) .
107                        $filename .
108                        $data;
109                break;
110            case 'crc32' :
111                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $compmethod) .
112                        $mtime .
113                        pack("VVVvv", $crc32 + 1, $complength, $uncomplength, strlen($filename), 0x00) .
114                        $filename .
115                        $data;
116                break;
117            case 'complength' :
118                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $compmethod) .
119                        $mtime .
120                        pack("VVVvv", $crc32, $complength + 1, $uncomplength, strlen($filename), 0x00) .
121                        $filename .
122                        $data;
123                break;
124            case 'uncomplength' :
125                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $compmethod) .
126                        $mtime .
127                        pack("VVVvv", $crc32, $complength, $uncomplength - 1, strlen($filename), 0x00) .
128                        $filename .
129                        $data;
130                break;
131            case 'filename_len' :
132                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $compmethod) .
133                        $mtime .
134                        pack("VVVvv", $crc32, $complength, $uncomplength, strlen($filename) - 1, 0x00) .
135                        $filename .
136                        $data;
137                break;
138            case 'extra_len' :
139                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $compmethod) .
140                        $mtime .
141                        pack("VVVvv", $crc32, $complength, $uncomplength, strlen($filename), 1) .
142                        $filename .
143                        $data;
144                break;
145            case 'filename' :
146                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $compmethod) .
147                        $mtime .
148                        pack("VVVvv", $crc32, $complength, $uncomplength, strlen($filename), 0x00) .
149                        substr($filename, 1) .
150                        $data;
151                break;
152            case 'data' :
153                $file = "PK\x03\x04\x14\x00\x00\x00" . pack('v', $compmethod) .
154                        $mtime .
155                        pack("VVVvv", $crc32, $complength, $uncomplength, strlen($filename), 0x00) .
156                        $filename .
157                        substr($data, 1);
158                break;
159        }
160        return $file;
161    }
162
163    private function getCentralEntry($compmethod, $mtime, $crc32, $complength, $uncomplength, $filename, $comment, $corrupt, &$offset, $fakecomp)
164    {
165        settype($comment, 'string');
166        switch ($corrupt) {
167            case null :
168                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $compmethod) .
169                        $mtime .
170                        pack("VVVvvvvvVV", $crc32, $complength, $uncomplength, strlen($filename), 0x00,strlen($comment),0x00,0x00,
171                            0x0000, $this->offset).
172                        $filename . $comment;
173                $offset = strlen($central);
174                break;
175            case 'encrypt' :
176                $central = "PK\x01\x02\x00\x00\x14\x00\x01\x00" . pack('v', $compmethod) .
177                        $mtime .
178                        pack("VVVvvvvvVV", $crc32, $complength, $uncomplength, strlen($filename), 0x00,strlen($comment),0x00,0x00,
179                            0x0000, $this->offset).
180                        $filename . $comment;
181                $offset = strlen($central);
182                break;
183            case 'compress' :
184                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $fakecomp) .
185                        $mtime .
186                        pack("VVVvvvvvVV", $crc32, $complength, $uncomplength, strlen($filename), 0x00,strlen($comment),0x00,0x00,
187                            0x0000, $this->offset).
188                        $filename . $comment;
189                $offset = strlen($central);
190                break;
191            case 'crc32' :
192                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $compmethod) .
193                        $mtime .
194                        pack("VVVvvvvvVV", $crc32 + 1, $complength, $uncomplength, strlen($filename), 0x00,strlen($comment),0x00,0x00,
195                            0x0000, $this->offset).
196                        $filename . $comment;
197                $offset = strlen($central);
198                break;
199            case 'complength' :
200                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $compmethod) .
201                        $mtime .
202                        pack("VVVvvvvvVV", $crc32, $complength - 1, $uncomplength, strlen($filename), 0x00,strlen($comment),0x00,0x00,
203                            0x0000, $this->offset).
204                        $filename . $comment;
205                $offset = strlen($central);
206                break;
207            case 'uncomplength' :
208                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $compmethod) .
209                        $mtime .
210                        pack("VVVvvvvvVV", $crc32, $complength, $uncomplength - 1, strlen($filename), 0x00,strlen($comment),0x00,0x00,
211                            0x0000, $this->offset).
212                        $filename . $comment;
213                $offset = strlen($central);
214                break;
215            case 'filename_len' :
216                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $compmethod) .
217                        $mtime .
218                        pack("VVVvvvvvVV", $crc32, $complength, $uncomplength, strlen($filename) - 1, 0x00,strlen($comment),0x00,0x00,
219                            0x0000, $this->offset).
220                        $filename . $comment;
221                $offset = strlen($central);
222                break;
223            case 'offset' :
224                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $compmethod) .
225                        $mtime .
226                        pack("VVVvvvvvVV", $crc32, $complength, $uncomplength, strlen($filename), 0x00,strlen($comment),0x00,0x00,
227                            0x0000, $this->offset - 1).
228                        $filename . $comment;
229                $offset = strlen($central) - 1;
230                break;
231            case 'comment' :
232                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $compmethod) .
233                        $mtime .
234                        pack("VVVvvvvvVV", $crc32, $complength, $uncomplength, strlen($filename), 0x00,strlen($comment) + 1,0x00,0x00,
235                            0x0000, $this->offset).
236                        $filename . $comment;
237                $offset = strlen($central);
238                break;
239            case 'extralen1' :
240                $extra = 'nu' . 0xffff; // way huge size
241                $central = "PK\x01\x02\x00\x00\x14\x00\x00\x00" . pack('v', $compmethod) .
242                        $mtime .
243                        pack("VVVvvvvvVV", $crc32, $complength, $uncomplength, strlen($filename), strlen($extra),strlen($comment),0x00,0x00,
244                            0x0000, $this->offset).
245                        $filename . $extra . $comment;
246                $offset = strlen($central);
247                break;
248        }
249        return $central;
250    }
251
252    function addFile($filename, $mtime, $data, $comment = null, $compress = null, $filecorrupt = null, $centralcorrupt = null, $fakecomp = 1)
253    {
254        $mtime = $this->getMTime($mtime ? $mtime : null);
255
256        $uncomplength = strlen($data);
257        $crc32 = crc32($data) & 0xFFFFFFFF;
258        $compmethod = 0;
259        switch ($compress) {
260            case 'gz' :
261                $data = gzcompress($data);
262                $compmethod = 8;
263                break;
264            case 'bz2' :
265                $data = bzcompress($data);
266                $compmethod = 12;
267                break;
268        }
269        $complength = strlen($data);
270
271        $this->start .= ($file = $this->getFileEntry($compmethod, $mtime, $crc32, $complength, $uncomplength, $filename, $data, $filecorrupt, $fakecomp));
272
273        $offset = 0;
274        $this->central .= $this->getCentralEntry($compmethod, $mtime, $crc32, $complength, $uncomplength, $filename, $comment, $centralcorrupt, $offset, $fakecomp);
275
276        $this->offset += $offset;
277        $this->count++;
278    }
279
280    function writeZip($zipfile, $corrupt = null)
281    {
282        $write = $this->start . $this->central;
283        switch ($corrupt) {
284            case null :
285                $write .= "PK\x05\x06\x00\x00\x00\x00" .
286                    pack("vvVVv", $this->count, $this->count,
287                    $this->offset, strlen($this->start),
288                    strlen($this->comment)) . $this->comment;
289                break;
290            case 'disknumber' :
291                $write .= "PK\x05\x06\x01\x00\x01\x00" .
292                    pack("vvVVv", $this->count, $this->count,
293                    $this->offset, strlen($this->start),
294                    strlen($this->comment)) . $this->comment;
295                break;
296            case 'count1' :
297                $write .= "PK\x05\x06\x00\x00\x00\x00" .
298                    pack("vvVVv", $this->count + 1, $this->count,
299                    $this->offset, strlen($this->start),
300                    strlen($this->comment)) . $this->comment;
301                break;
302            case 'count2' :
303                $write .= "PK\x05\x06\x00\x00\x00\x00" .
304                    pack("vvVVv", $this->count, $this->count + 1,
305                    $this->offset, strlen($this->start),
306                    strlen($this->comment)) . $this->comment;
307                break;
308            case 'cdir_offset' :
309                $write .= "PK\x05\x06\x00\x00\x00\x00" .
310                    pack("vvVVv", $this->count, $this->count,
311                    $this->offset, strlen($this->start) - 3,
312                    strlen($this->comment)) . $this->comment;
313                break;
314            case 'cdir_len' :
315                $write .= "PK\x05\x06\x00\x00\x00\x00" .
316                    pack("vvVVv", $this->count, $this->count,
317                    $this->offset - 5, strlen($this->start),
318                    strlen($this->comment)) . $this->comment;
319                break;
320            case 'comment' :
321                $write .= "PK\x05\x06\x00\x00\x00\x00" .
322                    pack("vvVVv", $this->count, $this->count,
323                    strlen($this->start), $this->offset + 1,
324                    strlen($this->comment) + 1) . $this->comment;
325                break;
326            case 'none' :
327        }
328        file_put_contents($zipfile, $write);
329    }
330}
331?>
332