Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
 
4
/**
5
 * ZIP archive writer
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA
22
 *
23
 * @category   File Formats
24
 * @package    File_Archive
25
 * @author     Vincent Lascaux <vincentlascaux@php.net>
26
 * @copyright  1997-2005 The PHP Group
27
 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL
28
 * @version    CVS: $Id: Zip.php,v 1.20 2005/08/15 18:03:03 vincentlascaux Exp $
29
 * @link       http://pear.php.net/package/File_Archive
30
 */
31
 
32
require_once "File/Archive/Writer/MemoryArchive.php";
33
 
34
/**
35
 * ZIP archive writer
36
 */
37
class File_Archive_Writer_Zip extends File_Archive_Writer_MemoryArchive
38
{
39
    /**
40
     * @var int Compression level
41
     * @access private
42
     */
43
    var $compressionLevel;
44
 
45
    /**
46
     * @var int Current position in the writer
47
     * @access private
48
     */
49
    var $offset = 0;
50
 
51
    /**
52
     * @var string Optionnal comment to add to the zip
53
     * @access private
54
     */
55
    var $comment = "";
56
 
57
    /**
58
     * @var string Data written at the end of the ZIP file
59
     * @access private
60
     */
61
    var $central = "";
62
 
63
    function File_Archive_Writer_Zip($filename, &$innerWriter,
64
                                     $stat=array(), $autoClose = true)
65
    {
66
        global $_File_Archive_Options;
67
        parent::File_Archive_Writer_MemoryArchive(
68
                    $filename, $innerWriter, $stat, $autoClose
69
                );
70
 
71
        $this->compressionLevel = File_Archive::getOption('zipCompressionLevel', 9);
72
    }
73
 
74
    /**
75
     * Change the level of the compression. This may be done between two files
76
     *
77
     * @param Int $compressionLevel New compression level from 0 to 9
78
     */
79
    function setCompressionLevel($compressionLevel)
80
    {
81
        $this->compressionLevel = $compressionLevel;
82
    }
83
 
84
    /**
85
     * Set a comment on the ZIP file
86
     */
87
    function setComment($comment) { $this->comment = $comment; }
88
 
89
    /**
90
     * @param int $time Unix timestamp of the date to convert
91
     * @return the date formated as a ZIP date
92
     */
93
    function getMTime($time)
94
    {
95
        $mtime = ($time !== null ? getdate($time) : getdate());
96
        $mtime = preg_replace(
97
                     "/(..){1}(..){1}(..){1}(..){1}/",
98
                     "\\x\\4\\x\\3\\x\\2\\x\\1",
99
                     dechex(($mtime['year']-1980<<25)|
100
                            ($mtime['mon'    ]<<21)|
101
                            ($mtime['mday'   ]<<16)|
102
                            ($mtime['hours'  ]<<11)|
103
                            ($mtime['minutes']<<5)|
104
                            ($mtime['seconds']>>1)));
105
        eval('$mtime = "'.$mtime.'";');
106
        return $mtime;
107
    }
108
 
109
    /**
110
     * Inform the archive that $filename is present.
111
     * Consequences are the same as appendFileData, but no data is output
112
     * to the inner writer.
113
     * This is used by File_Archive_Reader_Zip::makeWriter()
114
     *
115
     * @param string $filename name of the file
116
     * @param array $stat stats of the file, indexes 9 and 7 must be present
117
     * @param int $crc32 checksum of the file
118
     * @param int $compLength length of the compressed data
119
     */
120
    function alreadyWrittenFile($filename, $stat, $crc32, $complength)
121
    {
122
        $filename = preg_replace("/^(\.{1,2}(\/|\\\))+/","",$filename);
123
 
124
        $mtime = $this->getMTime(isset($stat[9]) ? $stat[9] : null);
125
        $normlength = $stat[7];
126
 
127
        $this->nbFiles++;
128
 
129
        $this->central .= "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00".
130
                   $mtime.
131
                   pack("VVVvvvvvVV",
132
                       $crc32, $complength, $normlength,
133
                       strlen($filename), 0x00,0x00,0x00,0x00,
134
                       0x0000,$this->offset).
135
                   $filename;
136
 
137
        $this->offset += 30 + strlen($filename) + $complength;
138
    }
139
 
140
    /**
141
     * @see    File_Archive_Writer_MemoryArchive::appendFileData()
142
     * @access protected
143
     */
144
    function appendFileData($filename, $stat, $data)
145
    {
146
        $crc32 = crc32($data);
147
        $normlength = strlen($data);
148
        $data = gzcompress($data,$this->compressionLevel);
149
        $data = substr($data,2,strlen($data)-6);
150
 
151
        return $this->appendCompressedData($filename, $stat, $data, $crc32, $normlength);
152
    }
153
 
154
    function appendCompressedData($filename, $stat, $data, $crc32, $normlength)
155
    {
156
        $filename = preg_replace("/^(\.{1,2}(\/|\\\))+/","",$filename);
157
        $mtime = $this->getMTime(isset($stat[9]) ? $stat[9] : null);
158
 
159
        $complength = strlen($data);
160
 
161
        $zipData = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".
162
                   $mtime.
163
                   pack("VVVvv",
164
                        $crc32,
165
                        $complength,
166
                        $normlength,
167
                        strlen($filename),
168
                        0x00).
169
                   $filename.
170
                   $data;
171
 
172
        $error = $this->innerWriter->writeData($zipData);
173
        if (PEAR::isError($error)) {
174
            return $error;
175
        }
176
 
177
        $this->central .= "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00".
178
                   $mtime.
179
                   pack("VVVvvvvvVV",
180
                       $crc32, $complength, $normlength,
181
                       strlen($filename), 0x00,0x00,0x00,0x00,
182
                       0x0000,$this->offset).
183
                   $filename;
184
 
185
        $this->offset += strlen($zipData);
186
    }
187
 
188
    function appendFile($filename, $dataFilename)
189
    {
190
        //Try to read from the cache
191
        $cache = File_Archive::getOption('cache', null);
192
        if ($cache !== null && $this->compressionLevel > 0) {
193
            $id = realpath($dataFilename);
194
            $id = urlencode($id);
195
            $id = str_replace('_', '%5F', $id);
196
 
197
            $group = 'FileArchiveZip'.$this->compressionLevel;
198
            $mtime = filemtime($dataFilename);
199
 
200
            //Tries to read from cache
201
            if (($data = $cache->get($id, $group)) !== false) {
202
                $info = unpack('Vmtime/Vcrc/Vnlength', substr($data, 0, 12));
203
                $data = substr($data, 12);
204
            }
205
 
206
            //If cache failed or file modified since then
207
            if ($data === false ||
208
                $info['mtime'] != $mtime) {
209
 
210
                $data = file_get_contents($dataFilename);
211
 
212
                $info = array(
213
                        'crc' => crc32($data),
214
                        'nlength' => strlen($data),
215
                        'mtime' => $mtime
216
                       );
217
 
218
                $data = gzcompress($data,$this->compressionLevel);
219
                $data = substr($data,2,strlen($data)-6);
220
                $data = pack('VVV', $info['mtime'], $info['crc'], $info['nlength']).$data;
221
                $cache->save($data, $id, $group);
222
            }
223
 
224
            return $this->appendCompressedData(
225
                                    $filename,
226
                                    stat($dataFilename),
227
                                    $data,
228
                                    $info['crc'],
229
                                    $info['nlength']
230
                   );
231
 
232
        }
233
 
234
        //If no cache system, use the standard way
235
        return parent::appendFile($filename, $dataFilename);
236
    }
237
 
238
    /**
239
     * @see    File_Archive_Writer_MemoryArchive::sendFooter()
240
     * @access protected
241
     */
242
    function sendFooter()
243
    {
244
        return $this->innerWriter->writeData(
245
            $this->central.
246
            "\x50\x4b\x05\x06\x00\x00\x00\x00".
247
            pack("vvVVv",
248
                $this->nbFiles,$this->nbFiles,
249
                strlen($this->central),$this->offset,
250
                strlen($this->comment)).
251
            $this->comment
252
        );
253
    }
254
    /**
255
     * @see File_Archive_Writer::getMime()
256
     */
257
    function getMime() { return "application/zip"; }
258
}
259
 
260
?>