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