119 $fh = fopen($file,
'rb');
121 throw new ReaderException(
"Can't open file $file");
123 $this->_file_handle = $fh;
125 $signature = fread($fh, 8);
126 if (
"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) {
127 throw new ReaderException(
"File doesn't seem to be an OLE container.");
130 if (fread($fh, 2) !=
"\xFE\xFF") {
132 throw new ReaderException(
'Only Little-Endian encoding is supported.');
163 for (
$i = 0;
$i < 109; ++
$i) {
169 for (
$i = 0;
$i < $mbbatBlockCount; ++
$i) {
171 for ($j = 0; $j < $this->bigBlockSize / 4 - 1; ++$j) {
179 for (
$i = 0;
$i < $bbatBlockCount; ++
$i) {
182 for ($j = 0; $j < $this->bigBlockSize / 4; ++$j) {
189 $shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4;
190 $sbatFh = $this->
getStream($sbatFirstBlockId);
191 for ($blockId = 0; $blockId < $shortBlockCount; ++$blockId) {
221 static $isRegistered =
false;
222 if (!$isRegistered) {
223 stream_wrapper_register(
'ole-chainedblockstream', ChainedBlockStream::class);
224 $isRegistered =
true;
230 $GLOBALS[
'_OLE_INSTANCES'][] = $this;
232 $instanceId = end(
$keys);
234 $path =
'ole-chainedblockstream://oleInstanceId=' . $instanceId;
235 if ($blockIdOrPps instanceof
OLE\PPS) {
236 $path .=
'&blockId=' . $blockIdOrPps->startBlock;
237 $path .=
'&size=' . $blockIdOrPps->Size;
239 $path .=
'&blockId=' . $blockIdOrPps;
242 return fopen(
$path,
'rb');
254 [, $tmp] = unpack(
'c', fread($fh, 1));
268 [, $tmp] = unpack(
'v', fread($fh, 2));
282 [, $tmp] = unpack(
'V', fread($fh, 4));
298 for ($pos = 0;
true; $pos += 128) {
299 fseek($fh, $pos, SEEK_SET);
300 $nameUtf16 = fread($fh, 64);
302 $nameUtf16 = substr($nameUtf16, 0, $nameLength - 2);
304 $name = str_replace(
"\x00",
'', $nameUtf16);
313 $pps =
new OLE\PPS(
null,
null,
null,
null,
null,
null,
null,
null,
null, []);
321 throw new Exception(
'Unsupported PPS type');
323 fseek($fh, 1, SEEK_CUR);
329 fseek($fh, 20, SEEK_CUR);
334 $pps->No = count($this->_list);
335 $this->_list[] = $pps;
345 foreach ($this->_list as $pps) {
346 if ($pps->Type == self::OLE_PPS_TYPE_DIR || $pps->Type == self::OLE_PPS_TYPE_ROOT) {
347 $nos = [$pps->DirPps];
350 $no = array_pop($nos);
352 $childPps = $this->_list[$no];
353 $nos[] = $childPps->PrevPps;
354 $nos[] = $childPps->NextPps;
355 $pps->children[] = $childPps;
374 return isset($this->_list[
$index]) &&
375 ($pps = $this->_list[
$index]) &&
376 ($pps->PrevPps == -1 ||
377 $this->ppsTreeComplete($pps->PrevPps)) &&
378 ($pps->NextPps == -1 ||
379 $this->ppsTreeComplete($pps->NextPps)) &&
380 ($pps->DirPps == -1 ||
381 $this->ppsTreeComplete($pps->DirPps));
394 if (isset($this->_list[
$index])) {
411 if (isset($this->_list[
$index])) {
425 return count($this->_list);
444 if (!isset($this->_list[
$index]) || ($position >= $this->_list[
$index]->
Size) || ($position < 0)) {
448 $data = stream_get_contents($fh, $length, $position);
464 if (isset($this->_list[
$index])) {
465 return $this->_list[
$index]->Size;
481 $iMax = strlen($ascii);
482 for (
$i = 0;
$i < $iMax; ++
$i) {
483 $rawname .= $ascii[
$i]
501 return "\x00\x00\x00\x00\x00\x00\x00\x00";
503 $dateTime = Date::dateTimeFromTimestamp(
"$date");
511 $big_date = $days * 24 * 3600 + (float) $dateTime->format(
'U');
513 $big_date *= 10000000;
515 $high_part = floor($big_date / $factor);
517 $low_part = floor((($big_date / $factor) - $high_part) * $factor);
522 for (
$i = 0;
$i < 4; ++
$i) {
523 $hex = $low_part % 0x100;
524 $res .= pack(
'c', $hex);
527 for (
$i = 0;
$i < 4; ++
$i) {
528 $hex = $high_part % 0x100;
529 $res .= pack(
'c', $hex);
545 if (strlen($oleTimestamp) != 8) {
546 throw new ReaderException(
'Expecting 8 byte string');
550 $unpackedTimestamp = unpack(
'v4', $oleTimestamp);
551 $timestampHigh = (float) $unpackedTimestamp[4] * 65536 + (
float) $unpackedTimestamp[3];
552 $timestampLow = (float) $unpackedTimestamp[2] * 65536 + (
float) $unpackedTimestamp[1];
555 $timestampHigh /= 10000000;
556 $timestampLow /= 10000000;
562 $unixTimestamp = floor(65536.0 * 65536.0 * $timestampHigh + $timestampLow - $days * 24 * 3600 + 0.5);
An exception for terminatinating execution or to throw for unit testing.
static evaluate($value)
Help some functions with large results operate correctly on 32-bit, by returning result as int when p...
Class for creating File PPS's for OLE containers.
Class for creating Root PPS's for OLE containers.
Class for creating PPS's for OLE containers.
static OLE2LocalDate($oleTimestamp)
Returns a timestamp from an OLE container's date.
static localDateToOLE($date)
Utility function Returns a string for the OLE container with the date given.
static readInt4($fh)
Reads an unsigned long (4 octets).
isRoot($index)
Checks whether a PPS is a Root PPS or not.
const OLE_DATA_SIZE_SMALL
isFile($index)
Checks whether a PPS is a File PPS or not.
read($file)
Reads an OLE container from the contents of the file given.
getStream($blockIdOrPps)
Returns a stream for use with fread() etc.
getDataLength($index)
Gets the data length from a PPS If there is no PPS for the index given, it will return 0.
static readInt1($fh)
Reads a signed char.
ppsTreeComplete($index)
It checks whether the PPS tree is complete (all PPS's read) starting with the given PPS (not necessar...
readPpsWks($blockId)
Gets information about all PPS's on the OLE container from the PPS WK's creates an OLE_PPS object for...
static readInt2($fh)
Reads an unsigned short (2 octets).
static ascToUcs($ascii)
Utility function to transform ASCII text to Unicode.
getData($index, $position, $length)
Gets data from a PPS If there is no PPS for the index given, it will return an empty string.
ppsTotal()
Gives the total number of PPS's found in the OLE container.
$GLOBALS['_OLE_INSTANCES']
foreach($_POST as $key=> $value) $res