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
 * This reader caches the files of another reader
6
 * It allow fast access to files. This is usefull if the access to the reader
7
 * is slow (HTTP, FTP...), but will need more IO if the file is only extracted
8
 *
9
 * PHP versions 4 and 5
10
 *
11
 * This library is free software; you can redistribute it and/or
12
 * modify it under the terms of the GNU Lesser General Public
13
 * License as published by the Free Software Foundation; either
14
 * version 2.1 of the License, or (at your option) any later version.
15
 *
16
 * This library is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
 * Lesser General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Lesser General Public
22
 * License along with this library; if not, write to the Free Software
23
 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA
24
 *
25
 * @category   File Formats
26
 * @package    File_Archive
27
 * @author     Vincent Lascaux <vincentlascaux@php.net>
28
 * @copyright  1997-2005 The PHP Group
29
 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL
30
 * @version    CVS: $Id: Cache.php,v 1.1 2005/07/07 12:24:58 vincentlascaux Exp $
31
 * @link       http://pear.php.net/package/File_Archive
32
 */
33
 
34
require_once "File/Archive/Reader.php";
35
 
36
/**
37
 * This reader caches the files of another reader
38
 * It allow fast access to files. This is usefull if the access to the reader
39
 * is slow (HTTP, FTP...), but will need more IO if the file is only extracted
40
 */
41
class File_Archive_Reader_Cache extends File_Archive_Reader
42
{
43
    var $tmpFile;
44
    var $files = array();
45
    var $pos = 0;
46
    var $fromSource = true;
47
    var $endOfSource = false;
48
    var $source;
49
 
50
    /**
51
     * $source is the reader to filter
52
     */
53
    function File_Archive_Reader_Cache(&$source)
54
    {
55
        $this->source =& $source;
56
        $this->tmpFile = tmpfile();
57
    }
58
 
59
    function _writeEndOfFile()
60
    {
61
        $bufferSize = File_Archive::getOption('blockSize');
62
        while (($data = $this->source->getData($bufferSize))!=null) {
63
            fwrite($this->tmpFile, $data);
64
        }
65
    }
66
    /**
67
     * @see File_Archive_Reader::next()
68
     */
69
    function next()
70
    {
71
        //Write the end of the current file to the temp file
72
        if ($this->fromSource && !empty($this->files)) {
73
            $this->_writeEndOfFile();
74
        }
75
 
76
        if ($this->pos+1 < count($this->files) && !$this->fromSource) {
77
            $this->pos++;
78
            fseek($this->tmpFile, $this->files[$this->pos]['pos'], SEEK_SET);
79
            return true;
80
        } else {
81
            $this->fromSource = true;
82
            if ($this->endOfSource) {
83
                return false;
84
            }
85
 
86
            $ret = $this->source->next();
87
            if ($ret !== true) {
88
                $this->endOfSource = true;
89
                $this->source->close();
90
                return $ret;
91
            }
92
 
93
            $this->endOfSource = false;
94
            fseek($this->tmpFile, 0, SEEK_END);
95
            $this->files[] = array(
96
                'name' => $this->source->getFilename(),
97
                'stat' => $this->source->getStat(),
98
                'mime' => $this->source->getMime(),
99
                'pos'  => ftell($this->tmpFile)
100
            );
101
            $this->pos = count($this->files)-1;
102
 
103
            return true;
104
        }
105
    }
106
 
107
    /**
108
     * @see File_Archive_Reader::getFilename()
109
     */
110
    function getFilename() { return $this->files[$this->pos]['name']; }
111
    /**
112
     * @see File_Archive_Reader::getStat()
113
     */
114
    function getStat() { return $this->files[$this->pos]['stat']; }
115
    /**
116
     * @see File_Archive_Reader::getMime()
117
     */
118
    function getMime() { return $this->files[$this->pos]['mime']; }
119
    /**
120
     * @see File_Archive_Reader::getDataFilename()
121
     */
122
    function getDataFilename() { return null; }
123
    /**
124
     * @see File_Archive_Reader::getData()
125
     */
126
    function getData($length = -1)
127
    {
128
        if ($this->fromSource) {
129
            $data = $this->source->getData($length);
130
            if (PEAR::isError($data)) {
131
                return $data;
132
            }
133
 
134
            fwrite($this->tmpFile, $data);
135
            return $data;
136
        } else {
137
            if ($length == 0) {
138
                return '';
139
            }
140
 
141
            if ($length > 0 && $this->pos+1 < count($this->files)) {
142
                $maxSize = $this->files[$this->pos+1]['pos'] - ftell($this->tmpFile);
143
                if ($maxSize == 0) {
144
                    return null;
145
                }
146
                if ($length > $maxSize) {
147
                    $length = $maxSize;
148
                }
149
                return fread($this->tmpFile, $length);
150
            } else {
151
                $contents = '';
152
                $blockSize = File_Archive::getOption('blockSize');
153
                while (!feof($this->tmpFile)) {
154
                    $contents .= fread($this->tmpFile, $blockSize);
155
                }
156
                return $contents == '' ? null : $contents;
157
            }
158
        }
159
    }
160
    /**
161
     * @see File_Archive_Reader::skip()
162
     */
163
    function skip($length = -1)
164
    {
165
        if ($this->fromSource) {
166
            return strlen($this->getData($length));
167
        } else {
168
            if ($length >= 0 && $this->pos+1 < count($this->files)) {
169
                $maxSize = $this->files[$this->pos+1]['pos'] - ftell($this->tmpFile);
170
                if ($maxSize == 0) {
171
                    return null;
172
                }
173
                if ($length > $maxSize) {
174
                    $length = $maxSize;
175
                }
176
                fseek($this->tmpFile, $length, SEEK_CUR);
177
                return $length;
178
            } else {
179
                $before = ftell($this->tmpFile);
180
                fseek($this->tmpFile, 0, SEEK_SET);
181
                $after = fteel($this->tmpFile);
182
                return $after - $before;
183
            }
184
        }
185
    }
186
    /**
187
     * @see File_Archive_Reader::rewind()
188
     */
189
    function rewind($length = -1)
190
    {
191
        if ($this->fromSource) {
192
            $this->_writeEndOfFile();
193
            $this->fromSource = false;
194
        }
195
        $before = ftell($this->tmpFile);
196
        $pos = $this->files[$this->pos]['pos'];
197
        fseek($this->tmpFile, $pos, SEEK_SET);
198
        return $pos - $before;
199
    }
200
    /**
201
     * @see File_Archive_Reader::tell()
202
     */
203
    function tell()
204
    {
205
        return ftell($this->tmpFile) - $this->files[$this->pos]['pos'];
206
    }
207
    /**
208
     * @see File_Archive_Reader::close()
209
     */
210
    function close()
211
    {
212
        $this->fromSource = false;
213
        $this->pos = 0;
214
        fseek($this->tmpFile, 0, SEEK_SET);
215
    }
216
    function _closeAndReset()
217
    {
218
        $this->close();
219
 
220
        fclose($this->tmpFile);
221
        $this->tmpFile = tmpfile();
222
        $this->endOfSource = false;
223
        $this->files = array();
224
        $this->source->close();
225
    }
226
    /**
227
     * @see File_Archive_Reader::makeAppendWriter()
228
     */
229
    function makeAppendWriter()
230
    {
231
        $writer = $this->source->makeAppendWriter();
232
        if (!PEAR::isError($writer)) {
233
            $this->_closeAndReset();
234
        }
235
 
236
        return $writer;
237
    }
238
    /**
239
     * @see File_Archive_Reader::makeWriterRemoveFiles()
240
     */
241
    function makeWriterRemoveFiles($pred)
242
    {
243
        $writer = $this->source->makeWriterRemoveFiles($pred);
244
        if (!PEAR::isError($writer)) {
245
            $this->_closeAndReset();
246
        }
247
        return $writer;
248
    }
249
    /**
250
     * @see File_Archive_Reader::makeWriterRemoveBlocks()
251
     */
252
    function makeWriterRemoveBlocks($blocks, $seek = 0)
253
    {
254
        $writer = $this->source->makeWriterRemoveBlocks($blocks, $seek);
255
        if (!PEAR::isError($writer)) {
256
            $this->_closeAndReset();
257
        }
258
        return $writer;
259
    }
260
}
261
 
262
?>