version = (int) $version; $this->uid = (int) $uid; $this->gid = (int) $gid; } /** * Returns the Header ID (type) of this Extra Field. * The Header ID is an unsigned short integer (two bytes) * which must be constant during the life cycle of this object. * * @return int */ public function getHeaderId() { return self::HEADER_ID; } /** * Populate data from this array as if it was in local file data. * * @param string $buffer the buffer to read data from * @param ZipEntry|null $entry * * @throws ZipException * * @return NewUnixExtraField */ public static function unpackLocalFileData($buffer, ZipEntry $entry = null) { $length = \strlen($buffer); if ($length < 3) { throw new ZipException(sprintf('X7875_NewUnix length is too short, only %s bytes', $length)); } $offset = 0; $data = unpack('Cversion/CuidSize', $buffer); $offset += 2; $uidSize = $data['uidSize']; $gid = self::readSizeIntegerLE(substr($buffer, $offset, $uidSize), $uidSize); $offset += $uidSize; $gidSize = unpack('C', $buffer[$offset])[1]; $offset++; $uid = self::readSizeIntegerLE(substr($buffer, $offset, $gidSize), $gidSize); return new self($data['version'], $gid, $uid); } /** * Populate data from this array as if it was in central directory data. * * @param string $buffer the buffer to read data from * @param ZipEntry|null $entry * * @throws ZipException * * @return NewUnixExtraField */ public static function unpackCentralDirData($buffer, ZipEntry $entry = null) { return self::unpackLocalFileData($buffer, $entry); } /** * The actual data to put into local file data - without Header-ID * or length specifier. * * @return string the data */ public function packLocalFileData() { return pack( 'CCVCV', $this->version, 4, // UIDSize $this->uid, 4, // GIDSize $this->gid ); } /** * The actual data to put into central directory - without Header-ID or * length specifier. * * @return string the data */ public function packCentralDirData() { return $this->packLocalFileData(); } /** * @param string $data * @param int $size * * @throws ZipException * * @return int */ private static function readSizeIntegerLE($data, $size) { $format = [ 1 => 'C', // unsigned byte 2 => 'v', // unsigned short LE 4 => 'V', // unsigned int LE ]; if (!isset($format[$size])) { throw new ZipException(sprintf('Invalid size bytes: %d', $size)); } return unpack($format[$size], $data)[1]; } /** * @return int */ public function getUid() { return $this->uid; } /** * @param int $uid */ public function setUid($uid) { $this->uid = $uid & 0xffffffff; } /** * @return int */ public function getGid() { return $this->gid; } /** * @param int $gid */ public function setGid($gid) { $this->gid = $gid & 0xffffffff; } /** * @return int */ public function getVersion() { return $this->version; } /** * @return string */ public function __toString() { return sprintf( '0x%04x NewUnix: UID=%d GID=%d', self::HEADER_ID, $this->uid, $this->gid ); } }