<?php
/**
*
* @author A. Grandt <php@grandt.com>
*
* Classes to assist in handling extra fields
*
*/
namespace ZipMerge\Zip\Core\ExtraField;
use com\grandt\BinStringStatic;
abstract class AbstractExtraField {
const HEADER_UNIX_TYPE_1 = 'UX'; // \x55\x58 or 0x5855 It has been replaced by the extended-timestamp extra block 'UT' (0x5455) and the Unix type 2 extra block 'Ux' (0x7855).
const HEADER_UNIX_TYPE_2 = 'Ux'; // \x55\x78 or 0x7855
const HEADER_UNIX_TYPE_3 = 'ux'; // \x75\x78 or 0x7875
const HEADER_EXTENDED_TIMESTAMP = 'UT'; // \x55\x54 or 0x5455
const HEADER_UNICODE_PATH = 'up'; // \x75\x70 or 0x7075
const HEADER_UNICODE_COMMENT = 'uc'; // \x75\x63 or 0x6375
public $header = null;
public $length = 0;
public $localData = "";
public $centralData = null;
/**
* 4.5 Extensible data fields
* --------------------------
*
* 4.5.1 In order to allow different programs and different types
* of information to be stored in the 'extra' field in .ZIP
* files, the following structure MUST be used for all
* programs storing data in this field:
*
* header1+data1 + header2+data2 . . .
*
* Each header should consist of:
*
* Header ID - 2 bytes
* Data Size - 2 bytes
*
* Note: all fields stored in Intel low-byte/high-byte order.
*
* The Header ID field indicates the type of data that is in
* the following data block.
*
* Header IDs of 0 thru 31 are reserved for use by PKWARE.
* The remaining IDs can be used by third party vendors for
* proprietary usage.
*
* @param resource $handle
* @param bool $isLocalHeader
*/
public function __construct($handle = null, $isLocalHeader = true) {
if ($handle != null) {
$this->header = fread($handle, 2);
$arr = unpack('v', fread($handle, 2));
$this->length = $arr[1];
if($isLocalHeader) {
$this->localData = fread($handle, $this->length);
} else {
$this->centralData = fread($handle, $this->length);
}
}
}
/**
* @return string The version of the field for the Local Header.
*/
abstract public function getLocalField();
/**
* @return string The version of the field for the Central Header.
*/
abstract public function getCentralField();
/**
*
* @param resource $handle
* @param bool $isLocalHeader default true
* @return GenericExtraField|UnicodeCommentExtraField|UnicodePathExtraField|ExtendedTimeStampExtraField
*/
public static function decodeField($handle, $isLocalHeader = true) {
$header = fread($handle, 2);
fseek($handle, -2, SEEK_CUR);
switch ($header) {
case self::HEADER_UNICODE_PATH:
return new UnicodePathExtraField($handle);
case self::HEADER_UNICODE_COMMENT:
return new UnicodeCommentExtraField($handle);
case self::HEADER_EXTENDED_TIMESTAMP:
return new ExtendedTimeStampExtraField($handle);
default:
return new GenericExtraField($handle, $isLocalHeader);
}
}
public static function encodeField($header, $data) {
if ($header != null) {
return $header . pack('v', BinStringStatic::_strlen($data)) . $data;
}
return '';
}
public function setFieldData($localFieldData, $centralFieldData = null) {
$this->localData = $localFieldData;
$this->centralData = $centralFieldData;
}
}