xref: /dokuwiki/vendor/splitbrain/php-archive/src/FileInfo.php (revision 361134418da8d033cd456de05c7a57c3cb528004)
1605f8e8dSAndreas Gohr<?php
2605f8e8dSAndreas Gohr
3605f8e8dSAndreas Gohrnamespace splitbrain\PHPArchive;
4605f8e8dSAndreas Gohr
5605f8e8dSAndreas Gohr/**
6605f8e8dSAndreas Gohr * Class FileInfo
7605f8e8dSAndreas Gohr *
8605f8e8dSAndreas Gohr * stores meta data about a file in an Archive
9605f8e8dSAndreas Gohr *
10605f8e8dSAndreas Gohr * @author  Andreas Gohr <andi@splitbrain.org>
11605f8e8dSAndreas Gohr * @package splitbrain\PHPArchive
12605f8e8dSAndreas Gohr * @license MIT
13605f8e8dSAndreas Gohr */
14605f8e8dSAndreas Gohrclass FileInfo
15605f8e8dSAndreas Gohr{
16605f8e8dSAndreas Gohr
17605f8e8dSAndreas Gohr    protected $isdir = false;
18605f8e8dSAndreas Gohr    protected $path = '';
19605f8e8dSAndreas Gohr    protected $size = 0;
20605f8e8dSAndreas Gohr    protected $csize = 0;
21605f8e8dSAndreas Gohr    protected $mtime = 0;
22605f8e8dSAndreas Gohr    protected $mode = 0664;
23605f8e8dSAndreas Gohr    protected $owner = '';
24605f8e8dSAndreas Gohr    protected $group = '';
25605f8e8dSAndreas Gohr    protected $uid = 0;
26605f8e8dSAndreas Gohr    protected $gid = 0;
27605f8e8dSAndreas Gohr    protected $comment = '';
28605f8e8dSAndreas Gohr
29605f8e8dSAndreas Gohr    /**
30605f8e8dSAndreas Gohr     * initialize dynamic defaults
31605f8e8dSAndreas Gohr     *
32605f8e8dSAndreas Gohr     * @param string $path The path of the file, can also be set later through setPath()
33605f8e8dSAndreas Gohr     */
34605f8e8dSAndreas Gohr    public function __construct($path = '')
35605f8e8dSAndreas Gohr    {
36605f8e8dSAndreas Gohr        $this->mtime = time();
37605f8e8dSAndreas Gohr        $this->setPath($path);
38605f8e8dSAndreas Gohr    }
39605f8e8dSAndreas Gohr
40605f8e8dSAndreas Gohr    /**
41605f8e8dSAndreas Gohr     * Factory to build FileInfo from existing file or directory
42605f8e8dSAndreas Gohr     *
43605f8e8dSAndreas Gohr     * @param string $path path to a file on the local file system
44605f8e8dSAndreas Gohr     * @param string $as   optional path to use inside the archive
45605f8e8dSAndreas Gohr     * @throws FileInfoException
46605f8e8dSAndreas Gohr     * @return FileInfo
47605f8e8dSAndreas Gohr     */
48605f8e8dSAndreas Gohr    public static function fromPath($path, $as = '')
49605f8e8dSAndreas Gohr    {
50605f8e8dSAndreas Gohr        clearstatcache(false, $path);
51605f8e8dSAndreas Gohr
52605f8e8dSAndreas Gohr        if (!file_exists($path)) {
53605f8e8dSAndreas Gohr            throw new FileInfoException("$path does not exist");
54605f8e8dSAndreas Gohr        }
55605f8e8dSAndreas Gohr
56605f8e8dSAndreas Gohr        $stat = stat($path);
57605f8e8dSAndreas Gohr        $file = new FileInfo();
58605f8e8dSAndreas Gohr
59605f8e8dSAndreas Gohr        $file->setPath($path);
60605f8e8dSAndreas Gohr        $file->setIsdir(is_dir($path));
61605f8e8dSAndreas Gohr        $file->setMode(fileperms($path));
62605f8e8dSAndreas Gohr        $file->setOwner(fileowner($path));
63605f8e8dSAndreas Gohr        $file->setGroup(filegroup($path));
64530d6729SAndreas Gohr        $file->setSize(filesize($path));
65605f8e8dSAndreas Gohr        $file->setUid($stat['uid']);
66605f8e8dSAndreas Gohr        $file->setGid($stat['gid']);
67605f8e8dSAndreas Gohr        $file->setMtime($stat['mtime']);
68605f8e8dSAndreas Gohr
69605f8e8dSAndreas Gohr        if ($as) {
70605f8e8dSAndreas Gohr            $file->setPath($as);
71605f8e8dSAndreas Gohr        }
72605f8e8dSAndreas Gohr
73605f8e8dSAndreas Gohr        return $file;
74605f8e8dSAndreas Gohr    }
75605f8e8dSAndreas Gohr
76605f8e8dSAndreas Gohr    /**
77*36113441SAndreas Gohr     * @return int the filesize. always 0 for directories
78605f8e8dSAndreas Gohr     */
79605f8e8dSAndreas Gohr    public function getSize()
80605f8e8dSAndreas Gohr    {
81*36113441SAndreas Gohr        if($this->isdir) return 0;
82605f8e8dSAndreas Gohr        return $this->size;
83605f8e8dSAndreas Gohr    }
84605f8e8dSAndreas Gohr
85605f8e8dSAndreas Gohr    /**
86605f8e8dSAndreas Gohr     * @param int $size
87605f8e8dSAndreas Gohr     */
88605f8e8dSAndreas Gohr    public function setSize($size)
89605f8e8dSAndreas Gohr    {
90605f8e8dSAndreas Gohr        $this->size = $size;
91605f8e8dSAndreas Gohr    }
92605f8e8dSAndreas Gohr
93605f8e8dSAndreas Gohr    /**
94605f8e8dSAndreas Gohr     * @return int
95605f8e8dSAndreas Gohr     */
96605f8e8dSAndreas Gohr    public function getCompressedSize()
97605f8e8dSAndreas Gohr    {
98605f8e8dSAndreas Gohr        return $this->csize;
99605f8e8dSAndreas Gohr    }
100605f8e8dSAndreas Gohr
101605f8e8dSAndreas Gohr    /**
102605f8e8dSAndreas Gohr     * @param int $csize
103605f8e8dSAndreas Gohr     */
104605f8e8dSAndreas Gohr    public function setCompressedSize($csize)
105605f8e8dSAndreas Gohr    {
106605f8e8dSAndreas Gohr        $this->csize = $csize;
107605f8e8dSAndreas Gohr    }
108605f8e8dSAndreas Gohr
109605f8e8dSAndreas Gohr    /**
110605f8e8dSAndreas Gohr     * @return int
111605f8e8dSAndreas Gohr     */
112605f8e8dSAndreas Gohr    public function getMtime()
113605f8e8dSAndreas Gohr    {
114605f8e8dSAndreas Gohr        return $this->mtime;
115605f8e8dSAndreas Gohr    }
116605f8e8dSAndreas Gohr
117605f8e8dSAndreas Gohr    /**
118605f8e8dSAndreas Gohr     * @param int $mtime
119605f8e8dSAndreas Gohr     */
120605f8e8dSAndreas Gohr    public function setMtime($mtime)
121605f8e8dSAndreas Gohr    {
122605f8e8dSAndreas Gohr        $this->mtime = $mtime;
123605f8e8dSAndreas Gohr    }
124605f8e8dSAndreas Gohr
125605f8e8dSAndreas Gohr    /**
126605f8e8dSAndreas Gohr     * @return int
127605f8e8dSAndreas Gohr     */
128605f8e8dSAndreas Gohr    public function getGid()
129605f8e8dSAndreas Gohr    {
130605f8e8dSAndreas Gohr        return $this->gid;
131605f8e8dSAndreas Gohr    }
132605f8e8dSAndreas Gohr
133605f8e8dSAndreas Gohr    /**
134605f8e8dSAndreas Gohr     * @param int $gid
135605f8e8dSAndreas Gohr     */
136605f8e8dSAndreas Gohr    public function setGid($gid)
137605f8e8dSAndreas Gohr    {
138605f8e8dSAndreas Gohr        $this->gid = $gid;
139605f8e8dSAndreas Gohr    }
140605f8e8dSAndreas Gohr
141605f8e8dSAndreas Gohr    /**
142605f8e8dSAndreas Gohr     * @return int
143605f8e8dSAndreas Gohr     */
144605f8e8dSAndreas Gohr    public function getUid()
145605f8e8dSAndreas Gohr    {
146605f8e8dSAndreas Gohr        return $this->uid;
147605f8e8dSAndreas Gohr    }
148605f8e8dSAndreas Gohr
149605f8e8dSAndreas Gohr    /**
150605f8e8dSAndreas Gohr     * @param int $uid
151605f8e8dSAndreas Gohr     */
152605f8e8dSAndreas Gohr    public function setUid($uid)
153605f8e8dSAndreas Gohr    {
154605f8e8dSAndreas Gohr        $this->uid = $uid;
155605f8e8dSAndreas Gohr    }
156605f8e8dSAndreas Gohr
157605f8e8dSAndreas Gohr    /**
158605f8e8dSAndreas Gohr     * @return string
159605f8e8dSAndreas Gohr     */
160605f8e8dSAndreas Gohr    public function getComment()
161605f8e8dSAndreas Gohr    {
162605f8e8dSAndreas Gohr        return $this->comment;
163605f8e8dSAndreas Gohr    }
164605f8e8dSAndreas Gohr
165605f8e8dSAndreas Gohr    /**
166605f8e8dSAndreas Gohr     * @param string $comment
167605f8e8dSAndreas Gohr     */
168605f8e8dSAndreas Gohr    public function setComment($comment)
169605f8e8dSAndreas Gohr    {
170605f8e8dSAndreas Gohr        $this->comment = $comment;
171605f8e8dSAndreas Gohr    }
172605f8e8dSAndreas Gohr
173605f8e8dSAndreas Gohr    /**
174605f8e8dSAndreas Gohr     * @return string
175605f8e8dSAndreas Gohr     */
176605f8e8dSAndreas Gohr    public function getGroup()
177605f8e8dSAndreas Gohr    {
178605f8e8dSAndreas Gohr        return $this->group;
179605f8e8dSAndreas Gohr    }
180605f8e8dSAndreas Gohr
181605f8e8dSAndreas Gohr    /**
182605f8e8dSAndreas Gohr     * @param string $group
183605f8e8dSAndreas Gohr     */
184605f8e8dSAndreas Gohr    public function setGroup($group)
185605f8e8dSAndreas Gohr    {
186605f8e8dSAndreas Gohr        $this->group = $group;
187605f8e8dSAndreas Gohr    }
188605f8e8dSAndreas Gohr
189605f8e8dSAndreas Gohr    /**
190605f8e8dSAndreas Gohr     * @return boolean
191605f8e8dSAndreas Gohr     */
192605f8e8dSAndreas Gohr    public function getIsdir()
193605f8e8dSAndreas Gohr    {
194605f8e8dSAndreas Gohr        return $this->isdir;
195605f8e8dSAndreas Gohr    }
196605f8e8dSAndreas Gohr
197605f8e8dSAndreas Gohr    /**
198605f8e8dSAndreas Gohr     * @param boolean $isdir
199605f8e8dSAndreas Gohr     */
200605f8e8dSAndreas Gohr    public function setIsdir($isdir)
201605f8e8dSAndreas Gohr    {
202605f8e8dSAndreas Gohr        // default mode for directories
203605f8e8dSAndreas Gohr        if ($isdir && $this->mode === 0664) {
204605f8e8dSAndreas Gohr            $this->mode = 0775;
205605f8e8dSAndreas Gohr        }
206605f8e8dSAndreas Gohr        $this->isdir = $isdir;
207605f8e8dSAndreas Gohr    }
208605f8e8dSAndreas Gohr
209605f8e8dSAndreas Gohr    /**
210605f8e8dSAndreas Gohr     * @return int
211605f8e8dSAndreas Gohr     */
212605f8e8dSAndreas Gohr    public function getMode()
213605f8e8dSAndreas Gohr    {
214605f8e8dSAndreas Gohr        return $this->mode;
215605f8e8dSAndreas Gohr    }
216605f8e8dSAndreas Gohr
217605f8e8dSAndreas Gohr    /**
218605f8e8dSAndreas Gohr     * @param int $mode
219605f8e8dSAndreas Gohr     */
220605f8e8dSAndreas Gohr    public function setMode($mode)
221605f8e8dSAndreas Gohr    {
222605f8e8dSAndreas Gohr        $this->mode = $mode;
223605f8e8dSAndreas Gohr    }
224605f8e8dSAndreas Gohr
225605f8e8dSAndreas Gohr    /**
226605f8e8dSAndreas Gohr     * @return string
227605f8e8dSAndreas Gohr     */
228605f8e8dSAndreas Gohr    public function getOwner()
229605f8e8dSAndreas Gohr    {
230605f8e8dSAndreas Gohr        return $this->owner;
231605f8e8dSAndreas Gohr    }
232605f8e8dSAndreas Gohr
233605f8e8dSAndreas Gohr    /**
234605f8e8dSAndreas Gohr     * @param string $owner
235605f8e8dSAndreas Gohr     */
236605f8e8dSAndreas Gohr    public function setOwner($owner)
237605f8e8dSAndreas Gohr    {
238605f8e8dSAndreas Gohr        $this->owner = $owner;
239605f8e8dSAndreas Gohr    }
240605f8e8dSAndreas Gohr
241605f8e8dSAndreas Gohr    /**
242605f8e8dSAndreas Gohr     * @return string
243605f8e8dSAndreas Gohr     */
244605f8e8dSAndreas Gohr    public function getPath()
245605f8e8dSAndreas Gohr    {
246605f8e8dSAndreas Gohr        return $this->path;
247605f8e8dSAndreas Gohr    }
248605f8e8dSAndreas Gohr
249605f8e8dSAndreas Gohr    /**
250605f8e8dSAndreas Gohr     * @param string $path
251605f8e8dSAndreas Gohr     */
252605f8e8dSAndreas Gohr    public function setPath($path)
253605f8e8dSAndreas Gohr    {
254605f8e8dSAndreas Gohr        $this->path = $this->cleanPath($path);
255605f8e8dSAndreas Gohr    }
256605f8e8dSAndreas Gohr
257605f8e8dSAndreas Gohr    /**
258605f8e8dSAndreas Gohr     * Cleans up a path and removes relative parts, also strips leading slashes
259605f8e8dSAndreas Gohr     *
260605f8e8dSAndreas Gohr     * @param string $path
261605f8e8dSAndreas Gohr     * @return string
262605f8e8dSAndreas Gohr     */
263605f8e8dSAndreas Gohr    protected function cleanPath($path)
264605f8e8dSAndreas Gohr    {
265605f8e8dSAndreas Gohr        $path    = str_replace('\\', '/', $path);
266605f8e8dSAndreas Gohr        $path    = explode('/', $path);
267605f8e8dSAndreas Gohr        $newpath = array();
268605f8e8dSAndreas Gohr        foreach ($path as $p) {
269605f8e8dSAndreas Gohr            if ($p === '' || $p === '.') {
270605f8e8dSAndreas Gohr                continue;
271605f8e8dSAndreas Gohr            }
272605f8e8dSAndreas Gohr            if ($p === '..') {
273605f8e8dSAndreas Gohr                array_pop($newpath);
274605f8e8dSAndreas Gohr                continue;
275605f8e8dSAndreas Gohr            }
276605f8e8dSAndreas Gohr            array_push($newpath, $p);
277605f8e8dSAndreas Gohr        }
278605f8e8dSAndreas Gohr        return trim(implode('/', $newpath), '/');
279605f8e8dSAndreas Gohr    }
280605f8e8dSAndreas Gohr
281605f8e8dSAndreas Gohr    /**
282605f8e8dSAndreas Gohr     * Strip given prefix or number of path segments from the filename
283605f8e8dSAndreas Gohr     *
284605f8e8dSAndreas Gohr     * The $strip parameter allows you to strip a certain number of path components from the filenames
285605f8e8dSAndreas Gohr     * found in the tar file, similar to the --strip-components feature of GNU tar. This is triggered when
286605f8e8dSAndreas Gohr     * an integer is passed as $strip.
287605f8e8dSAndreas Gohr     * Alternatively a fixed string prefix may be passed in $strip. If the filename matches this prefix,
288605f8e8dSAndreas Gohr     * the prefix will be stripped. It is recommended to give prefixes with a trailing slash.
289605f8e8dSAndreas Gohr     *
290605f8e8dSAndreas Gohr     * @param  int|string $strip
291605f8e8dSAndreas Gohr     * @return FileInfo
292605f8e8dSAndreas Gohr     */
293605f8e8dSAndreas Gohr    public function strip($strip)
294605f8e8dSAndreas Gohr    {
295605f8e8dSAndreas Gohr        $filename = $this->getPath();
296605f8e8dSAndreas Gohr        $striplen = strlen($strip);
297605f8e8dSAndreas Gohr        if (is_int($strip)) {
298605f8e8dSAndreas Gohr            // if $strip is an integer we strip this many path components
299605f8e8dSAndreas Gohr            $parts = explode('/', $filename);
300605f8e8dSAndreas Gohr            if (!$this->getIsdir()) {
301605f8e8dSAndreas Gohr                $base = array_pop($parts); // keep filename itself
302605f8e8dSAndreas Gohr            } else {
303605f8e8dSAndreas Gohr                $base = '';
304605f8e8dSAndreas Gohr            }
305605f8e8dSAndreas Gohr            $filename = join('/', array_slice($parts, $strip));
306605f8e8dSAndreas Gohr            if ($base) {
307605f8e8dSAndreas Gohr                $filename .= "/$base";
308605f8e8dSAndreas Gohr            }
309605f8e8dSAndreas Gohr        } else {
310605f8e8dSAndreas Gohr            // if strip is a string, we strip a prefix here
311605f8e8dSAndreas Gohr            if (substr($filename, 0, $striplen) == $strip) {
312605f8e8dSAndreas Gohr                $filename = substr($filename, $striplen);
313605f8e8dSAndreas Gohr            }
314605f8e8dSAndreas Gohr        }
315605f8e8dSAndreas Gohr
316605f8e8dSAndreas Gohr        $this->setPath($filename);
317605f8e8dSAndreas Gohr    }
318605f8e8dSAndreas Gohr
319605f8e8dSAndreas Gohr    /**
320605f8e8dSAndreas Gohr     * Does the file match the given include and exclude expressions?
321605f8e8dSAndreas Gohr     *
322605f8e8dSAndreas Gohr     * Exclude rules take precedence over include rules
323605f8e8dSAndreas Gohr     *
324605f8e8dSAndreas Gohr     * @param string $include Regular expression of files to include
325605f8e8dSAndreas Gohr     * @param string $exclude Regular expression of files to exclude
326605f8e8dSAndreas Gohr     * @return bool
327605f8e8dSAndreas Gohr     */
328605f8e8dSAndreas Gohr    public function match($include = '', $exclude = '')
329605f8e8dSAndreas Gohr    {
330605f8e8dSAndreas Gohr        $extract = true;
331605f8e8dSAndreas Gohr        if ($include && !preg_match($include, $this->getPath())) {
332605f8e8dSAndreas Gohr            $extract = false;
333605f8e8dSAndreas Gohr        }
334605f8e8dSAndreas Gohr        if ($exclude && preg_match($exclude, $this->getPath())) {
335605f8e8dSAndreas Gohr            $extract = false;
336605f8e8dSAndreas Gohr        }
337605f8e8dSAndreas Gohr
338605f8e8dSAndreas Gohr        return $extract;
339605f8e8dSAndreas Gohr    }
340605f8e8dSAndreas Gohr}
341605f8e8dSAndreas Gohr
342605f8e8dSAndreas Gohrclass FileInfoException extends \Exception
343605f8e8dSAndreas Gohr{
344605f8e8dSAndreas Gohr}