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
 * Uncompress a file that was compressed in the Bzip2 format
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: Bzip2.php,v 1.20 2008/06/05 21:30:46 cbrunet Exp $
29
 * @link       http://pear.php.net/package/File_Archive
30
 */
31
 
32
require_once "File/Archive/Reader/Archive.php";
33
require_once "File/Archive/Writer/Files.php";
34
 
35
/**
36
 * Uncompress a file that was compressed in the Bzip2 format
37
 */
38
class File_Archive_Reader_Bzip2 extends File_Archive_Reader_Archive
39
{
40
    var $nbRead = 0;
41
    var $bzfile = null;
42
    var $tmpName = null;
43
    var $filePos = 0;
44
 
45
    /**
46
     * @see File_Archive_Reader::close()
47
     */
48
    function close($innerClose = true)
49
    {
50
        if ($this->bzfile !== null)
51
            bzclose($this->bzfile);
52
        if ($this->tmpName !== null)
53
            unlink($this->tmpName);
54
 
55
        $this->bzfile = null;
56
        $this->tmpName = null;
57
        $this->nbRead = 0;
58
        $this->filePos = 0;
59
        return parent::close($innerClose);
60
    }
61
 
62
    /**
63
     * @see File_Archive_Reader::next()
64
     */
65
    function next()
66
    {
67
        if (!parent::next()) {
68
            return false;
69
        }
70
 
71
        $this->nbRead++;
72
        if ($this->nbRead > 1) {
73
            return false;
74
        }
75
 
76
        $dataFilename = $this->source->getDataFilename();
77
        if ($dataFilename !== null)
78
        {
79
            $this->tmpName = null;
80
            $this->bzfile = @bzopen($dataFilename, 'r');
81
            if ($this->bzfile === false) {
82
                return PEAR::raiseError("bzopen failed to open $dataFilename");
83
            }
84
        } else {
85
            $this->tmpName = tempnam(File_Archive::getOption('tmpDirectory'), 'far');
86
 
87
            //Generate the tmp data
88
            $dest = new File_Archive_Writer_Files();
89
            $dest->newFile($this->tmpName);
90
            $this->source->sendData($dest);
91
            $dest->close();
92
 
93
            $this->bzfile = bzopen($this->tmpName, 'r');
94
        }
95
 
96
        return true;
97
    }
98
    /**
99
     * Return the name of the single file contained in the archive
100
     * deduced from the name of the archive (the extension is removed)
101
     *
102
     * @see File_Archive_Reader::getFilename()
103
     */
104
    function getFilename()
105
    {
106
        $name = $this->source->getFilename();
107
        $pos = strrpos($name, ".");
108
        if ($pos === false || $pos === 0) {
109
            return $name;
110
        } else {
111
            return substr($name, 0, $pos);
112
        }
113
    }
114
    /**
115
     * @see File_Archive_Reader::getData()
116
     */
117
    function getData($length = -1)
118
    {
119
        if ($length == -1) {
120
            $data = '';
121
            do {
122
                $newData = bzread($this->bzfile);
123
                $data .= $newData;
124
            } while ($newData != '');
125
            $this->filePos += strlen($data);
126
        } else if ($length == 0) {
127
            return '';
128
        } else {
129
            $data = '';
130
 
131
            //The loop is here to correct what appears to be a bzread bug
132
            while (strlen($data) < $length) {
133
                $newData = bzread($this->bzfile, $length - strlen($data));
134
                if ($newData == '') {
135
                    break;
136
                }
137
                $data .= $newData;
138
            }
139
            $this->filePos += strlen($data);
140
        }
141
 
142
        return $data == '' ? null : $data;
143
    }
144
 
145
    /**
146
     * @see File_Archive_Reader::rewind
147
     */
148
    function rewind($length = -1)
149
    {
150
        $before = $this->filePos;
151
 
152
        bzclose($this->bzfile);
153
        if ($this->tmpName === null) {
154
            $this->bzfile = bzopen($this->source->getDataFilename(), 'r');
155
        } else {
156
            $this->bzfile = bzopen($this->tmpName, 'r');
157
        }
158
        $this->filePos = 0;
159
 
160
        if ($length != -1) {
161
            $this->skip($before - $length);
162
        }
163
        return $before - $this->filePos;
164
    }
165
 
166
    /**
167
     * @see File_Archive_Reader::tell()
168
     */
169
    function tell()
170
    {
171
        return $this->filePos;
172
    }
173
 
174
    /**
175
     * @see File_Archive_Reader::makeAppendWriter()
176
     */
177
    function makeAppendWriter()
178
    {
179
        return PEAR::raiseError('Unable to append files to a bzip2 archive');
180
    }
181
 
182
    /**
183
     * @see File_Archive_Reader::makeWriterRemoveFiles()
184
     */
185
    function makeWriterRemoveFiles($pred)
186
    {
187
        return PEAR::raiseError('Unable to remove files from a bzip2 archive');
188
    }
189
 
190
    /**
191
     * @see File_Archive_Reader::makeWriterRemoveBlocks()
192
     */
193
    function makeWriterRemoveBlocks($blocks, $seek = 0)
194
    {
195
        require_once "File/Archive/Writer/Bzip2.php";
196
 
197
        if ($this->nbRead == 0) {
198
            return PEAR::raiseError('No file selected');
199
        }
200
 
201
        //Uncompress data to a temporary file
202
        $tmp = tmpfile();
203
        $expectedPos = $this->filePos + $seek;
204
 
205
        $this->rewind();
206
 
207
        //Read the begining of the file
208
        while ($this->filePos < $expectedPos &&
209
               ($data = $this->getData(min($expectedPos - $this->filePos, 8192))) !== null) {
210
            fwrite($tmp, $data);
211
        }
212
 
213
        $keep = false;
214
        foreach ($blocks as $length) {
215
            if ($keep) {
216
                $expectedPos = $this->filePos + $length;
217
                while ($this->filePos < $expectedPos &&
218
                       ($data = $this->getData(min($expectedPos - $this->filePos, 8192))) !== null) {
219
                    fwrite($tmp, $data);
220
                }
221
            } else {
222
                $this->skip($length);
223
            }
224
            $keep = !$keep;
225
        }
226
        if ($keep) {
227
            //Read the end of the file
228
            while(($data = $this->getData(8192)) !== null) {
229
                fwrite($tmp, $data);
230
            }
231
        }
232
        fseek($tmp, 0);
233
 
234
        //Create the writer
235
        $this->source->rewind();
236
        $innerWriter = $this->source->makeWriterRemoveBlocks(array());   //Truncate the source
237
        unset($this->source);
238
        $writer = new File_Archive_Writer_Bzip2(null, $innerWriter);
239
 
240
        //And compress data from the temporary file
241
        while (!feof($tmp)) {
242
            $data = fread($tmp, 8192);
243
            $writer->writeData($data);
244
        }
245
        fclose($tmp);
246
 
247
        //Do not close inner writer since makeWriter was called
248
        $this->close();
249
 
250
        return $writer;
251
    }
252
}
253
 
254
?>