xref: /plugin/upgrade/myvendor/splitbrain/php-archive/src/FileInfo.php (revision ab8e5256dbaece2751c4414d6cf7b761cb71998a)
1*ab8e5256SAndreas Gohr<?php
2*ab8e5256SAndreas Gohr
3*ab8e5256SAndreas Gohrnamespace splitbrain\PHPArchive;
4*ab8e5256SAndreas Gohr
5*ab8e5256SAndreas Gohr/**
6*ab8e5256SAndreas Gohr * Class FileInfo
7*ab8e5256SAndreas Gohr *
8*ab8e5256SAndreas Gohr * stores meta data about a file in an Archive
9*ab8e5256SAndreas Gohr *
10*ab8e5256SAndreas Gohr * @author  Andreas Gohr <andi@splitbrain.org>
11*ab8e5256SAndreas Gohr * @package splitbrain\PHPArchive
12*ab8e5256SAndreas Gohr * @license MIT
13*ab8e5256SAndreas Gohr */
14*ab8e5256SAndreas Gohrclass FileInfo
15*ab8e5256SAndreas Gohr{
16*ab8e5256SAndreas Gohr
17*ab8e5256SAndreas Gohr    protected $isdir = false;
18*ab8e5256SAndreas Gohr    protected $path = '';
19*ab8e5256SAndreas Gohr    protected $size = 0;
20*ab8e5256SAndreas Gohr    protected $csize = 0;
21*ab8e5256SAndreas Gohr    protected $mtime = 0;
22*ab8e5256SAndreas Gohr    protected $mode = 0664;
23*ab8e5256SAndreas Gohr    protected $owner = '';
24*ab8e5256SAndreas Gohr    protected $group = '';
25*ab8e5256SAndreas Gohr    protected $uid = 0;
26*ab8e5256SAndreas Gohr    protected $gid = 0;
27*ab8e5256SAndreas Gohr    protected $comment = '';
28*ab8e5256SAndreas Gohr
29*ab8e5256SAndreas Gohr    /**
30*ab8e5256SAndreas Gohr     * initialize dynamic defaults
31*ab8e5256SAndreas Gohr     *
32*ab8e5256SAndreas Gohr     * @param string $path The path of the file, can also be set later through setPath()
33*ab8e5256SAndreas Gohr     */
34*ab8e5256SAndreas Gohr    public function __construct($path = '')
35*ab8e5256SAndreas Gohr    {
36*ab8e5256SAndreas Gohr        $this->mtime = time();
37*ab8e5256SAndreas Gohr        $this->setPath($path);
38*ab8e5256SAndreas Gohr    }
39*ab8e5256SAndreas Gohr
40*ab8e5256SAndreas Gohr    /**
41*ab8e5256SAndreas Gohr     * Handle calls to deprecated methods
42*ab8e5256SAndreas Gohr     *
43*ab8e5256SAndreas Gohr     * @param string $name
44*ab8e5256SAndreas Gohr     * @param array $arguments
45*ab8e5256SAndreas Gohr     * @return mixed
46*ab8e5256SAndreas Gohr     */
47*ab8e5256SAndreas Gohr    public function __call($name, $arguments)
48*ab8e5256SAndreas Gohr    {
49*ab8e5256SAndreas Gohr        if($name === 'match') {
50*ab8e5256SAndreas Gohr            trigger_error('FileInfo::match() is deprecated, use FileInfo::matchExpression() instead.', E_USER_NOTICE);
51*ab8e5256SAndreas Gohr            return call_user_func_array([$this, $name], $arguments);
52*ab8e5256SAndreas Gohr        }
53*ab8e5256SAndreas Gohr
54*ab8e5256SAndreas Gohr        trigger_error('Call to undefined method FileInfo::'.$name.'()', E_USER_ERROR);
55*ab8e5256SAndreas Gohr        return null;
56*ab8e5256SAndreas Gohr    }
57*ab8e5256SAndreas Gohr
58*ab8e5256SAndreas Gohr    /**
59*ab8e5256SAndreas Gohr     * Factory to build FileInfo from existing file or directory
60*ab8e5256SAndreas Gohr     *
61*ab8e5256SAndreas Gohr     * @param string $path path to a file on the local file system
62*ab8e5256SAndreas Gohr     * @param string $as   optional path to use inside the archive
63*ab8e5256SAndreas Gohr     * @throws FileInfoException
64*ab8e5256SAndreas Gohr     * @return FileInfo
65*ab8e5256SAndreas Gohr     */
66*ab8e5256SAndreas Gohr    public static function fromPath($path, $as = '')
67*ab8e5256SAndreas Gohr    {
68*ab8e5256SAndreas Gohr        clearstatcache(false, $path);
69*ab8e5256SAndreas Gohr
70*ab8e5256SAndreas Gohr        if (!file_exists($path)) {
71*ab8e5256SAndreas Gohr            throw new FileInfoException("$path does not exist");
72*ab8e5256SAndreas Gohr        }
73*ab8e5256SAndreas Gohr
74*ab8e5256SAndreas Gohr        $stat = stat($path);
75*ab8e5256SAndreas Gohr        $file = new FileInfo();
76*ab8e5256SAndreas Gohr
77*ab8e5256SAndreas Gohr        $file->setPath($path);
78*ab8e5256SAndreas Gohr        $file->setIsdir(is_dir($path));
79*ab8e5256SAndreas Gohr        $file->setMode(fileperms($path));
80*ab8e5256SAndreas Gohr        $file->setOwner(fileowner($path));
81*ab8e5256SAndreas Gohr        $file->setGroup(filegroup($path));
82*ab8e5256SAndreas Gohr        $file->setSize(filesize($path));
83*ab8e5256SAndreas Gohr        $file->setUid($stat['uid']);
84*ab8e5256SAndreas Gohr        $file->setGid($stat['gid']);
85*ab8e5256SAndreas Gohr        $file->setMtime($stat['mtime']);
86*ab8e5256SAndreas Gohr
87*ab8e5256SAndreas Gohr        if ($as) {
88*ab8e5256SAndreas Gohr            $file->setPath($as);
89*ab8e5256SAndreas Gohr        }
90*ab8e5256SAndreas Gohr
91*ab8e5256SAndreas Gohr        return $file;
92*ab8e5256SAndreas Gohr    }
93*ab8e5256SAndreas Gohr
94*ab8e5256SAndreas Gohr    /**
95*ab8e5256SAndreas Gohr     * @return int the filesize. always 0 for directories
96*ab8e5256SAndreas Gohr     */
97*ab8e5256SAndreas Gohr    public function getSize()
98*ab8e5256SAndreas Gohr    {
99*ab8e5256SAndreas Gohr        if($this->isdir) return 0;
100*ab8e5256SAndreas Gohr        return $this->size;
101*ab8e5256SAndreas Gohr    }
102*ab8e5256SAndreas Gohr
103*ab8e5256SAndreas Gohr    /**
104*ab8e5256SAndreas Gohr     * @param int $size
105*ab8e5256SAndreas Gohr     */
106*ab8e5256SAndreas Gohr    public function setSize($size)
107*ab8e5256SAndreas Gohr    {
108*ab8e5256SAndreas Gohr        $this->size = $size;
109*ab8e5256SAndreas Gohr    }
110*ab8e5256SAndreas Gohr
111*ab8e5256SAndreas Gohr    /**
112*ab8e5256SAndreas Gohr     * @return int
113*ab8e5256SAndreas Gohr     */
114*ab8e5256SAndreas Gohr    public function getCompressedSize()
115*ab8e5256SAndreas Gohr    {
116*ab8e5256SAndreas Gohr        return $this->csize;
117*ab8e5256SAndreas Gohr    }
118*ab8e5256SAndreas Gohr
119*ab8e5256SAndreas Gohr    /**
120*ab8e5256SAndreas Gohr     * @param int $csize
121*ab8e5256SAndreas Gohr     */
122*ab8e5256SAndreas Gohr    public function setCompressedSize($csize)
123*ab8e5256SAndreas Gohr    {
124*ab8e5256SAndreas Gohr        $this->csize = $csize;
125*ab8e5256SAndreas Gohr    }
126*ab8e5256SAndreas Gohr
127*ab8e5256SAndreas Gohr    /**
128*ab8e5256SAndreas Gohr     * @return int
129*ab8e5256SAndreas Gohr     */
130*ab8e5256SAndreas Gohr    public function getMtime()
131*ab8e5256SAndreas Gohr    {
132*ab8e5256SAndreas Gohr        return $this->mtime;
133*ab8e5256SAndreas Gohr    }
134*ab8e5256SAndreas Gohr
135*ab8e5256SAndreas Gohr    /**
136*ab8e5256SAndreas Gohr     * @param int $mtime
137*ab8e5256SAndreas Gohr     */
138*ab8e5256SAndreas Gohr    public function setMtime($mtime)
139*ab8e5256SAndreas Gohr    {
140*ab8e5256SAndreas Gohr        $this->mtime = $mtime;
141*ab8e5256SAndreas Gohr    }
142*ab8e5256SAndreas Gohr
143*ab8e5256SAndreas Gohr    /**
144*ab8e5256SAndreas Gohr     * @return int
145*ab8e5256SAndreas Gohr     */
146*ab8e5256SAndreas Gohr    public function getGid()
147*ab8e5256SAndreas Gohr    {
148*ab8e5256SAndreas Gohr        return $this->gid;
149*ab8e5256SAndreas Gohr    }
150*ab8e5256SAndreas Gohr
151*ab8e5256SAndreas Gohr    /**
152*ab8e5256SAndreas Gohr     * @param int $gid
153*ab8e5256SAndreas Gohr     */
154*ab8e5256SAndreas Gohr    public function setGid($gid)
155*ab8e5256SAndreas Gohr    {
156*ab8e5256SAndreas Gohr        $this->gid = $gid;
157*ab8e5256SAndreas Gohr    }
158*ab8e5256SAndreas Gohr
159*ab8e5256SAndreas Gohr    /**
160*ab8e5256SAndreas Gohr     * @return int
161*ab8e5256SAndreas Gohr     */
162*ab8e5256SAndreas Gohr    public function getUid()
163*ab8e5256SAndreas Gohr    {
164*ab8e5256SAndreas Gohr        return $this->uid;
165*ab8e5256SAndreas Gohr    }
166*ab8e5256SAndreas Gohr
167*ab8e5256SAndreas Gohr    /**
168*ab8e5256SAndreas Gohr     * @param int $uid
169*ab8e5256SAndreas Gohr     */
170*ab8e5256SAndreas Gohr    public function setUid($uid)
171*ab8e5256SAndreas Gohr    {
172*ab8e5256SAndreas Gohr        $this->uid = $uid;
173*ab8e5256SAndreas Gohr    }
174*ab8e5256SAndreas Gohr
175*ab8e5256SAndreas Gohr    /**
176*ab8e5256SAndreas Gohr     * @return string
177*ab8e5256SAndreas Gohr     */
178*ab8e5256SAndreas Gohr    public function getComment()
179*ab8e5256SAndreas Gohr    {
180*ab8e5256SAndreas Gohr        return $this->comment;
181*ab8e5256SAndreas Gohr    }
182*ab8e5256SAndreas Gohr
183*ab8e5256SAndreas Gohr    /**
184*ab8e5256SAndreas Gohr     * @param string $comment
185*ab8e5256SAndreas Gohr     */
186*ab8e5256SAndreas Gohr    public function setComment($comment)
187*ab8e5256SAndreas Gohr    {
188*ab8e5256SAndreas Gohr        $this->comment = $comment;
189*ab8e5256SAndreas Gohr    }
190*ab8e5256SAndreas Gohr
191*ab8e5256SAndreas Gohr    /**
192*ab8e5256SAndreas Gohr     * @return string
193*ab8e5256SAndreas Gohr     */
194*ab8e5256SAndreas Gohr    public function getGroup()
195*ab8e5256SAndreas Gohr    {
196*ab8e5256SAndreas Gohr        return $this->group;
197*ab8e5256SAndreas Gohr    }
198*ab8e5256SAndreas Gohr
199*ab8e5256SAndreas Gohr    /**
200*ab8e5256SAndreas Gohr     * @param string $group
201*ab8e5256SAndreas Gohr     */
202*ab8e5256SAndreas Gohr    public function setGroup($group)
203*ab8e5256SAndreas Gohr    {
204*ab8e5256SAndreas Gohr        $this->group = $group;
205*ab8e5256SAndreas Gohr    }
206*ab8e5256SAndreas Gohr
207*ab8e5256SAndreas Gohr    /**
208*ab8e5256SAndreas Gohr     * @return boolean
209*ab8e5256SAndreas Gohr     */
210*ab8e5256SAndreas Gohr    public function getIsdir()
211*ab8e5256SAndreas Gohr    {
212*ab8e5256SAndreas Gohr        return $this->isdir;
213*ab8e5256SAndreas Gohr    }
214*ab8e5256SAndreas Gohr
215*ab8e5256SAndreas Gohr    /**
216*ab8e5256SAndreas Gohr     * @param boolean $isdir
217*ab8e5256SAndreas Gohr     */
218*ab8e5256SAndreas Gohr    public function setIsdir($isdir)
219*ab8e5256SAndreas Gohr    {
220*ab8e5256SAndreas Gohr        // default mode for directories
221*ab8e5256SAndreas Gohr        if ($isdir && $this->mode === 0664) {
222*ab8e5256SAndreas Gohr            $this->mode = 0775;
223*ab8e5256SAndreas Gohr        }
224*ab8e5256SAndreas Gohr        $this->isdir = $isdir;
225*ab8e5256SAndreas Gohr    }
226*ab8e5256SAndreas Gohr
227*ab8e5256SAndreas Gohr    /**
228*ab8e5256SAndreas Gohr     * @return int
229*ab8e5256SAndreas Gohr     */
230*ab8e5256SAndreas Gohr    public function getMode()
231*ab8e5256SAndreas Gohr    {
232*ab8e5256SAndreas Gohr        return $this->mode;
233*ab8e5256SAndreas Gohr    }
234*ab8e5256SAndreas Gohr
235*ab8e5256SAndreas Gohr    /**
236*ab8e5256SAndreas Gohr     * @param int $mode
237*ab8e5256SAndreas Gohr     */
238*ab8e5256SAndreas Gohr    public function setMode($mode)
239*ab8e5256SAndreas Gohr    {
240*ab8e5256SAndreas Gohr        $this->mode = $mode;
241*ab8e5256SAndreas Gohr    }
242*ab8e5256SAndreas Gohr
243*ab8e5256SAndreas Gohr    /**
244*ab8e5256SAndreas Gohr     * @return string
245*ab8e5256SAndreas Gohr     */
246*ab8e5256SAndreas Gohr    public function getOwner()
247*ab8e5256SAndreas Gohr    {
248*ab8e5256SAndreas Gohr        return $this->owner;
249*ab8e5256SAndreas Gohr    }
250*ab8e5256SAndreas Gohr
251*ab8e5256SAndreas Gohr    /**
252*ab8e5256SAndreas Gohr     * @param string $owner
253*ab8e5256SAndreas Gohr     */
254*ab8e5256SAndreas Gohr    public function setOwner($owner)
255*ab8e5256SAndreas Gohr    {
256*ab8e5256SAndreas Gohr        $this->owner = $owner;
257*ab8e5256SAndreas Gohr    }
258*ab8e5256SAndreas Gohr
259*ab8e5256SAndreas Gohr    /**
260*ab8e5256SAndreas Gohr     * @return string
261*ab8e5256SAndreas Gohr     */
262*ab8e5256SAndreas Gohr    public function getPath()
263*ab8e5256SAndreas Gohr    {
264*ab8e5256SAndreas Gohr        return $this->path;
265*ab8e5256SAndreas Gohr    }
266*ab8e5256SAndreas Gohr
267*ab8e5256SAndreas Gohr    /**
268*ab8e5256SAndreas Gohr     * @param string $path
269*ab8e5256SAndreas Gohr     */
270*ab8e5256SAndreas Gohr    public function setPath($path)
271*ab8e5256SAndreas Gohr    {
272*ab8e5256SAndreas Gohr        $this->path = $this->cleanPath($path);
273*ab8e5256SAndreas Gohr    }
274*ab8e5256SAndreas Gohr
275*ab8e5256SAndreas Gohr    /**
276*ab8e5256SAndreas Gohr     * Cleans up a path and removes relative parts, also strips leading slashes
277*ab8e5256SAndreas Gohr     *
278*ab8e5256SAndreas Gohr     * @param string $path
279*ab8e5256SAndreas Gohr     * @return string
280*ab8e5256SAndreas Gohr     */
281*ab8e5256SAndreas Gohr    protected function cleanPath($path)
282*ab8e5256SAndreas Gohr    {
283*ab8e5256SAndreas Gohr        $path    = str_replace('\\', '/', $path);
284*ab8e5256SAndreas Gohr        $path    = explode('/', $path);
285*ab8e5256SAndreas Gohr        $newpath = array();
286*ab8e5256SAndreas Gohr        foreach ($path as $p) {
287*ab8e5256SAndreas Gohr            if ($p === '' || $p === '.') {
288*ab8e5256SAndreas Gohr                continue;
289*ab8e5256SAndreas Gohr            }
290*ab8e5256SAndreas Gohr            if ($p === '..') {
291*ab8e5256SAndreas Gohr                array_pop($newpath);
292*ab8e5256SAndreas Gohr                continue;
293*ab8e5256SAndreas Gohr            }
294*ab8e5256SAndreas Gohr            array_push($newpath, $p);
295*ab8e5256SAndreas Gohr        }
296*ab8e5256SAndreas Gohr        return trim(implode('/', $newpath), '/');
297*ab8e5256SAndreas Gohr    }
298*ab8e5256SAndreas Gohr
299*ab8e5256SAndreas Gohr    /**
300*ab8e5256SAndreas Gohr     * Strip given prefix or number of path segments from the filename
301*ab8e5256SAndreas Gohr     *
302*ab8e5256SAndreas Gohr     * The $strip parameter allows you to strip a certain number of path components from the filenames
303*ab8e5256SAndreas Gohr     * found in the tar file, similar to the --strip-components feature of GNU tar. This is triggered when
304*ab8e5256SAndreas Gohr     * an integer is passed as $strip.
305*ab8e5256SAndreas Gohr     * Alternatively a fixed string prefix may be passed in $strip. If the filename matches this prefix,
306*ab8e5256SAndreas Gohr     * the prefix will be stripped. It is recommended to give prefixes with a trailing slash.
307*ab8e5256SAndreas Gohr     *
308*ab8e5256SAndreas Gohr     * @param  int|string $strip
309*ab8e5256SAndreas Gohr     */
310*ab8e5256SAndreas Gohr    public function strip($strip)
311*ab8e5256SAndreas Gohr    {
312*ab8e5256SAndreas Gohr        $filename = $this->getPath();
313*ab8e5256SAndreas Gohr        $striplen = strlen($strip);
314*ab8e5256SAndreas Gohr        if (is_int($strip)) {
315*ab8e5256SAndreas Gohr            // if $strip is an integer we strip this many path components
316*ab8e5256SAndreas Gohr            $parts = explode('/', $filename);
317*ab8e5256SAndreas Gohr            if (!$this->getIsdir()) {
318*ab8e5256SAndreas Gohr                $base = array_pop($parts); // keep filename itself
319*ab8e5256SAndreas Gohr            } else {
320*ab8e5256SAndreas Gohr                $base = '';
321*ab8e5256SAndreas Gohr            }
322*ab8e5256SAndreas Gohr            $filename = join('/', array_slice($parts, $strip));
323*ab8e5256SAndreas Gohr            if ($base) {
324*ab8e5256SAndreas Gohr                $filename .= "/$base";
325*ab8e5256SAndreas Gohr            }
326*ab8e5256SAndreas Gohr        } else {
327*ab8e5256SAndreas Gohr            // if strip is a string, we strip a prefix here
328*ab8e5256SAndreas Gohr            if (substr($filename, 0, $striplen) == $strip) {
329*ab8e5256SAndreas Gohr                $filename = substr($filename, $striplen);
330*ab8e5256SAndreas Gohr            }
331*ab8e5256SAndreas Gohr        }
332*ab8e5256SAndreas Gohr
333*ab8e5256SAndreas Gohr        $this->setPath($filename);
334*ab8e5256SAndreas Gohr    }
335*ab8e5256SAndreas Gohr
336*ab8e5256SAndreas Gohr    /**
337*ab8e5256SAndreas Gohr     * Does the file match the given include and exclude expressions?
338*ab8e5256SAndreas Gohr     *
339*ab8e5256SAndreas Gohr     * Exclude rules take precedence over include rules
340*ab8e5256SAndreas Gohr     *
341*ab8e5256SAndreas Gohr     * @param string $include Regular expression of files to include
342*ab8e5256SAndreas Gohr     * @param string $exclude Regular expression of files to exclude
343*ab8e5256SAndreas Gohr     * @return bool
344*ab8e5256SAndreas Gohr     */
345*ab8e5256SAndreas Gohr    public function matchExpression($include = '', $exclude = '')
346*ab8e5256SAndreas Gohr    {
347*ab8e5256SAndreas Gohr        $extract = true;
348*ab8e5256SAndreas Gohr        if ($include && !preg_match($include, $this->getPath())) {
349*ab8e5256SAndreas Gohr            $extract = false;
350*ab8e5256SAndreas Gohr        }
351*ab8e5256SAndreas Gohr        if ($exclude && preg_match($exclude, $this->getPath())) {
352*ab8e5256SAndreas Gohr            $extract = false;
353*ab8e5256SAndreas Gohr        }
354*ab8e5256SAndreas Gohr
355*ab8e5256SAndreas Gohr        return $extract;
356*ab8e5256SAndreas Gohr    }
357*ab8e5256SAndreas Gohr}
358*ab8e5256SAndreas Gohr
359