.htaccess
1 year ago
BZFile.php
1 year ago
File.php
1 year ago
FileInfo.php
1 day ago
GZFile.php
1 year ago
RegFile.php
1 day ago
index.html
1 year ago
web.config
1 year ago
FileInfo.php
167 lines
| 1 | <?php |
| 2 | /* |
| 3 | * |
| 4 | * JetBackup @ package |
| 5 | * Created By Idan Ben-Ezra |
| 6 | * |
| 7 | * Copyrights @ JetApps |
| 8 | * https://www.jetapps.com |
| 9 | * |
| 10 | **/ |
| 11 | namespace JetBackup\Archive\File; |
| 12 | |
| 13 | use JetBackup\Archive\Data\SetterGetter; |
| 14 | use JetBackup\Archive\Header\Header; |
| 15 | use JetBackup\Entities\Util; |
| 16 | use JetBackup\Exception\ArchiveException; |
| 17 | use JetBackup\JetBackup; |
| 18 | use JetBackup\Wordpress\Wordpress; |
| 19 | |
| 20 | class FileInfo extends SetterGetter { |
| 21 | |
| 22 | private $_is_socket; |
| 23 | |
| 24 | /** |
| 25 | * initialize dynamic defaults |
| 26 | * |
| 27 | * @param string $path The path of the file, can also be set later through setPath() |
| 28 | */ |
| 29 | public function __construct(string $path='') { |
| 30 | parent::__construct(); |
| 31 | $this->setPath($path); |
| 32 | } |
| 33 | |
| 34 | /** |
| 35 | * Factory to build FileInfo from existing file or directory |
| 36 | * |
| 37 | * @param string $path path to a file on the local file system |
| 38 | * @param string $as optional path to use inside the archive |
| 39 | * @throws ArchiveException |
| 40 | * @return FileInfo |
| 41 | */ |
| 42 | public static function fromPath(string $path, string $as=''):FileInfo { |
| 43 | clearstatcache(false, $path); |
| 44 | |
| 45 | if (!file_exists($path)) { |
| 46 | throw new ArchiveException("$path does not exist"); |
| 47 | } |
| 48 | |
| 49 | $stat = lstat($path); |
| 50 | $file = new FileInfo(); |
| 51 | |
| 52 | $group = Util::getgrgid($stat['gid']); |
| 53 | $group = $group ? $group['name'] : ''; |
| 54 | |
| 55 | $user = Util::getpwuid($stat['uid']); |
| 56 | $user = $user ? $user['name'] : ''; |
| 57 | |
| 58 | // If user set alternate wp-content folder, we will put it in its original location inside the archive |
| 59 | // We will handle re-creating links during the restore procedure |
| 60 | $isAlternateWpContent = Wordpress::getAlternateContentDir() && basename(Wordpress::getAlternateContentDir()) === basename($path) && is_link($path) ; |
| 61 | |
| 62 | $file->setPath($path); |
| 63 | $file->setMode($isAlternateWpContent ? 0040755 : $stat['mode']); |
| 64 | $file->setOwner($user); |
| 65 | $file->setGroup($group); |
| 66 | $file->setSize($stat['size']); |
| 67 | $file->setUid($stat['uid']); |
| 68 | $file->setGid($stat['gid']); |
| 69 | $file->setMtime($stat['mtime']); |
| 70 | // get the device type (major and minor) |
| 71 | if($stat['rdev']) { |
| 72 | $file->setDevMajor(($stat['rdev'] >> 8) & 0xFF); |
| 73 | $file->setDevMinor($stat['rdev'] & 0xFF); |
| 74 | } |
| 75 | |
| 76 | if(!$isAlternateWpContent && $file->isLink() && ($link_source = @readlink($path)) !== false) $file->setLink($link_source); |
| 77 | |
| 78 | if($stat['size'] > 0) { |
| 79 | // Calculate the maximum number of blocks that could be allocated |
| 80 | $maxBlocks = ceil($stat['size'] / $stat['blksize']); |
| 81 | |
| 82 | // Calculate sparseness as the ratio of allocated blocks to the maximum possible blocks |
| 83 | $sparseness = ($maxBlocks > 0) ? ($stat['blocks'] / $maxBlocks) : 1.0; |
| 84 | |
| 85 | $file->setSparseness($sparseness); |
| 86 | } |
| 87 | |
| 88 | if ($as) $file->setPath($as); |
| 89 | |
| 90 | return $file; |
| 91 | } |
| 92 | |
| 93 | public function getSize(): int { return !$this->isDir() && !$this->isLink() ? $this->get('size', 0) : 0; } |
| 94 | public function setSize(int $size):void { $this->set('size', $size); } |
| 95 | |
| 96 | public function getCompressedSize(): int { return $this->get('csize', 0); } |
| 97 | public function setCompressedSize(int $csize):void { $this->set('csize', $csize); } |
| 98 | |
| 99 | public function getMtime(): int { return $this->get('mtime', time()); } |
| 100 | public function setMtime(int $mtime):void { $this->set('mtime', $mtime); } |
| 101 | |
| 102 | public function getGid(): int { return $this->get('gid', 0); } |
| 103 | public function setGid(int $gid):void { $this->set('gid', $gid); } |
| 104 | |
| 105 | public function getUid(): int { return $this->get('uid', 0); } |
| 106 | public function setUid(int $uid):void { $this->set('uid', $uid); } |
| 107 | |
| 108 | public function getComment(): string { return $this->get('comment'); } |
| 109 | public function setComment(string $comment):void { $this->set('comment', $comment); } |
| 110 | |
| 111 | public function getOwner(): string { return $this->get('owner'); } |
| 112 | public function setOwner(string $owner):void { $this->set('owner', $owner); } |
| 113 | |
| 114 | public function getGroup(): string { return $this->get('group'); } |
| 115 | public function setGroup(string $group):void { $this->set('group', $group); } |
| 116 | |
| 117 | public function getFlagType(): string { return $this->get('flag', Header::REGTYPE); } |
| 118 | public function setFlagType(string $flag):void { $this->set('flag', $flag); } |
| 119 | |
| 120 | public function getLink(): string { return $this->get('link'); } |
| 121 | public function setLink(string $link):void { $this->set('link', $link); } |
| 122 | |
| 123 | public function getDevMajor(): string { return $this->get('device_major'); } |
| 124 | public function setDevMajor(string $device):void { $this->set('device_major', $device); } |
| 125 | |
| 126 | public function getDevMinor(): string { return $this->get('device_minor'); } |
| 127 | public function setDevMinor(string $device):void { $this->set('device_minor', $device); } |
| 128 | |
| 129 | public function getPath(): string { return $this->get('path'); } |
| 130 | public function setPath(string $path):void { $this->set('path', $this->cleanPath($path)); } |
| 131 | |
| 132 | public function getSparseness(): float { return $this->get('sparseness', 0.0); } |
| 133 | public function setSparseness(float $sparseness):void { $this->set('sparseness', $sparseness); } |
| 134 | |
| 135 | public function isDir():bool { return $this->getFlagType() == Header::DIRTYPE; } |
| 136 | public function isLink():bool { return $this->getFlagType() == Header::SYMTYPE; } |
| 137 | public function isSocket():bool { return !!$this->_is_socket; } |
| 138 | |
| 139 | public function getMode(): int { return $this->get('mode', 33188); } |
| 140 | public function setMode(int $mode):void { |
| 141 | switch($mode & 0170000) { |
| 142 | //default: throw new ArchiveException("Failed to determent the file type"); |
| 143 | case 0100000: $this->setFlagType(Header::REGTYPE); break; // regular file |
| 144 | // add '\0' -> AREGTYPE // regular file |
| 145 | // add '1' -> LNKTYPE // link (hrwxrwxrwx 2.txt link to 1.txt) |
| 146 | case 0120000: $this->setFlagType(Header::SYMTYPE); break; // reserved (symlink) |
| 147 | case 0020000: $this->setFlagType(Header::CHRTYPE); break; // character special |
| 148 | case 0060000: $this->setFlagType(Header::BLKTYPE); break; // block special |
| 149 | case 0040000: $this->setFlagType(Header::DIRTYPE); break; // directory |
| 150 | case 0010000: $this->setFlagType(Header::FIFOTYPE); break; // FIFO special |
| 151 | // add '7' -> CONTTYPE // reserved |
| 152 | case 0140000: $this->_is_socket = true; break; // FIFO special |
| 153 | } |
| 154 | |
| 155 | $this->set('mode', $mode); |
| 156 | } |
| 157 | |
| 158 | /** |
| 159 | * Cleans up a path and removes relative parts, also strips leading slashes |
| 160 | * |
| 161 | * @param string $path |
| 162 | * @return string |
| 163 | */ |
| 164 | protected function cleanPath(string $path):string { |
| 165 | return trim(Util::resolveRelativePath($path), JetBackup::SEP); |
| 166 | } |
| 167 | } |