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
 * Recursively uncompress every file it finds
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: Uncompress.php,v 1.34 2007/01/15 21:43:54 pfischer Exp $
29
 * @link       http://pear.php.net/package/File_Archive
30
 */
31
 
32
require_once "File/Archive/Reader.php";
33
require_once "File/Archive/Reader/ChangeName/AddDirectory.php";
34
 
35
/**
36
 * Recursively uncompress every file it finds
37
 */
38
class File_Archive_Reader_Uncompress extends File_Archive_Reader_Relay
39
{
40
    /**
41
     * @var Array Stack of readers
42
     * @access private
43
     */
44
    var $readers = array();
45
 
46
    /**
47
     * @var array of readers to close when closing $this
48
     * @access private
49
     */
50
    var $toClose = array();
51
 
52
    /**
53
     * @var File_Archive_Reader Reader from which all started (usefull to be
54
     *      able to close)
55
     * @access private
56
     */
57
    var $startReader;
58
 
59
    /**
60
     * @var Int Maximum depth of uncompression after the basicDir
61
     *          (that may contain some uncompression also)
62
     *          -1 means no limit
63
     * @access private
64
     */
65
    var $uncompressionLevel;
66
 
67
    /**
68
     * @var array Only files starting with $baseDir will be reported
69
     *      This array contains explode('/', $directoryName)
70
     * @access private
71
     */
72
    var $baseDir = '';
73
 
74
    /**
75
     * @var int Compression level required to go to reach the baseDir
76
     *          or null if it is currently being computed
77
     * @access private
78
     */
79
    var $baseDirCompressionLevel = null;
80
 
81
    /**
82
     * @var int We are selecting substr($baseDir, 0, $baseDirProgression)
83
     */
84
    var $baseDirProgression = 0;
85
 
86
    /**
87
     * @var boolean Flag set to indicate that the current file has not been
88
     *              displayed
89
     */
90
    var $currentFileNotDisplayed = false;
91
 
92
    function File_Archive_Reader_Uncompress(
93
                        &$innerReader, $uncompressionLevel = -1)
94
    {
95
        parent::File_Archive_Reader_Relay($innerReader);
96
        $this->startReader =& $innerReader;
97
        $this->uncompressionLevel = $uncompressionLevel;
98
    }
99
 
100
    /**
101
     * Attempt to change the current source (if the current file is an archive)
102
     * If this is the case, push the current source onto the stack and make the
103
     * good archive reader the current source. A file is considered as an
104
     * archive if its extension is one of tar, gz, zip, tgz
105
     *
106
     * @return bool whether the source has been pushed or not
107
     * @access private
108
     */
109
    function push()
110
    {
111
        $filename  = $this->source->getFilename();
112
 
113
        if (substr($filename, -1) == '/') { //it's a directory
114
            return false;
115
        }
116
 
117
 
118
        if ($this->uncompressionLevel >= 0 &&
119
            $this->baseDirCompressionLevel !== null &&
120
            count($this->readers) >= $this->uncompressionLevel
121
           ) {
122
           return false;
123
        }
124
 
125
        // Check the extension of the file (maybe we need to uncompress it?)
126
        $extensions = explode('.', strtolower($filename));
127
 
128
        $reader =& $this->source;
129
        $nbUncompressions = 0;
130
 
131
        while (($extension = array_pop($extensions)) !== null) {
132
            $nbUncompressions++;
133
            unset($next);
134
            $next = File_Archive::readArchive($extension, $reader, $nbUncompressions == 1);
135
            if ($next === false) {
136
                $extensions = array();
137
            } else {
138
                unset($reader);
139
                $reader =& $next;
140
            }
141
        }
142
        if ($nbUncompressions == 1) {
143
            return false;
144
        } else {
145
            $this->readers[count($this->readers)] =& $this->source;
146
            unset($this->source);
147
            $this->source = new File_Archive_Reader_ChangeName_AddDirectory(
148
                $filename, $reader
149
            );
150
            return true;
151
        }
152
    }
153
    /**
154
     * @see File_Archive_Reader::close()
155
     */
156
    function next()
157
    {
158
        if ($this->currentFileNotDisplayed) {
159
            $this->currentFileNotDisplayed = false;
160
            return true;
161
        }
162
 
163
        do {
164
            do {
165
                $selection = substr($this->baseDir, 0, $this->baseDirProgression);
166
                if ($selection === false) {
167
                    $selection = '';
168
                }
169
 
170
                $error = $this->source->select($selection, false);
171
                if (PEAR::isError($error)) {
172
                    return $error;
173
                }
174
                if (!$error) {
175
                    if (empty($this->readers)) {
176
                        return false;
177
                    }
178
                    $this->source->close();
179
                    unset($this->source);
180
                    $this->source =& $this->readers[count($this->readers)-1];
181
                    unset($this->readers[count($this->readers)-1]);
182
                }
183
            } while (!$error);
184
 
185
            $filename = $this->source->getFilename();
186
            if (strlen($filename) < strlen($this->baseDir)) {
187
                $goodFile = (strncmp($filename, $this->baseDir, strlen($filename)) == 0 &&
188
                             $this->baseDir{strlen($filename)} == '/');
189
                if ($goodFile) {
190
                    if (strlen($filename) + 2 < strlen($this->baseDirProgression)) {
191
                        $this->baseDirProgression = strpos($this->baseDir, '/', strlen($filename)+2);
192
                        if ($this->baseDirProgression === false) {
193
                            $this->baseDirProgression = strlen($this->baseDir);
194
                        }
195
                    } else {
196
                        $this->baseDirProgression = strlen($this->baseDir);
197
                    }
198
                }
199
            } else {
200
                $goodFile = (strncmp($filename, $this->baseDir, strlen($this->baseDir)) == 0);
201
                if ($goodFile) {
202
                    $this->baseDirProgression = strlen($this->baseDir);
203
                }
204
            }
205
        } while (($goodFile && $this->push()) || !$goodFile);
206
 
207
        return true;
208
    }
209
 
210
    /**
211
     * Efficiently filter out the files which URL does not start with $baseDir
212
     * Throws an error if the $baseDir can't be found
213
     * @return bool Whether baseDir was a directory or a file
214
     */
215
    function setBaseDir($baseDir)
216
    {
217
        $this->baseDir = $baseDir;
218
        $this->baseDirProgression = strpos($baseDir, '/');
219
        if ($this->baseDirProgression === false) {
220
            $this->baseDirProgression = strlen($baseDir);
221
        }
222
 
223
        $error = $this->next();
224
        if ($error === false) {
225
            return PEAR::raiseError("No directory $baseDir in inner reader");
226
        } else if (PEAR::isError($error)) {
227
            return $error;
228
        }
229
 
230
        $this->currentFileNotDisplayed = true;
231
        return strlen($this->getFilename())>strlen($baseDir);
232
    }
233
    /**
234
     * @see File_Archive_Reader::select()
235
     */
236
    function select($filename, $close = true)
237
    {
238
        if ($close) {
239
            $error = $this->close();
240
            if (PEAR::isError($close)) {
241
                return $error;
242
            }
243
        }
244
 
245
        $oldBaseDir = $this->baseDir;
246
        $oldProgression = $this->baseDirProgression;
247
 
248
        $this->baseDir = $filename;
249
        $this->baseDirProgression = 0;
250
 
251
        $res = $this->next();
252
 
253
        $this->baseDir = $oldBaseDir;
254
        $this->baseDirProgression = $oldProgression;
255
 
256
        return $res;
257
    }
258
 
259
    /**
260
     * @see File_Archive_Reader::close()
261
     */
262
    function close()
263
    {
264
        for ($i=0; $i<count($this->readers); ++$i) {
265
            $this->readers[$i]->close();
266
        }
267
        //var_dump($this->toClose);
268
        for ($i=0; $i<count($this->toClose); ++$i) {
269
            if ($this->toClose[$i] !== null) {
270
                $this->toClose[$i]->close();
271
            }
272
        }
273
 
274
        $this->readers = array();
275
        $this->toClose = array();
276
        $error = parent::close();
277
        $this->baseDirCompressionLevel = null;
278
        $this->baseDirProgression = 0;
279
 
280
        unset($this->source);
281
        $this->source =& $this->startReader;
282
        $this->source->close();
283
        $this->currentFileNotDisplayed = false;
284
 
285
        return $error;
286
    }
287
 
288
    /**
289
     * @see File_Archive_Reader::makeAppendWriter()
290
     */
291
    function makeAppendWriter()
292
    {
293
        //The reader needs to be open so that the base dir is found
294
        $error = $this->next();
295
        if (PEAR::isError($error)) {
296
            return $error;
297
        }
298
 
299
        return parent::makeAppendWriter();
300
    }
301
 
302
    /**
303
     * @see File_Archive_Reader::makeWriterRemoveFiles()
304
     */
305
    function makeWriterRemoveFiles($pred)
306
    {
307
        //The reader needs to be open so that the base dir is found
308
        $error = $this->next();
309
        if (PEAR::isError($error)) {
310
            return $error;
311
        }
312
 
313
        return parent::makeWriterRemoveFiles($pred);
314
    }
315
}
316
 
317
?>