28 define(
'IDENTIFIER_OLE', pack(
'CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1));
75 public function read($sFileName)
78 if(!is_readable($sFileName)) {
79 throw new Exception(
"Could not open " . $sFileName .
" for reading! File does not exist, or it is not readable.");
83 $this->data = file_get_contents($sFileName);
87 throw new Exception(
'The filename ' . $sFileName .
' is not recognised as an OLE file');
91 $this->numBigBlockDepotBlocks =
self::_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
94 $this->rootStartBlock =
self::_GetInt4d($this->data, self::ROOT_START_BLOCK_POS);
97 $this->sbdStartBlock =
self::_GetInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS);
100 $this->extensionBlock =
self::_GetInt4d($this->data, self::EXTENSION_BLOCK_POS);
103 $this->numExtensionBlocks =
self::_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS);
105 $bigBlockDepotBlocks = array();
108 $bbdBlocks = $this->numBigBlockDepotBlocks;
110 if ($this->numExtensionBlocks != 0) {
114 for ($i = 0; $i < $bbdBlocks; ++$i) {
119 for ($j = 0; $j < $this->numExtensionBlocks; ++$j) {
120 $pos = ($this->extensionBlock + 1) * self::BIG_BLOCK_SIZE;
121 $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1);
123 for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) {
128 $bbdBlocks += $blocksToRead;
129 if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
135 $this->bigBlockChain = array();
137 $bbs = self::BIG_BLOCK_SIZE / 4;
138 for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) {
139 $pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;
141 for ($j = 0 ; $j < $bbs; ++$j) {
149 $sbdBlock = $this->sbdStartBlock;
150 $this->smallBlockChain = array();
152 while ($sbdBlock != -2) {
153 $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE;
155 for ($j = 0; $j < $bbs; ++$j) {
161 $sbdBlock = $this->bigBlockChain[$sbdBlock];
165 $block = $this->rootStartBlock;
178 if (is_null($stream)) {
184 if ($this->props[$stream][
'size'] < self::SMALL_BLOCK_THRESHOLD) {
185 $rootdata = $this->
_readData($this->props[$this->rootentry][
'startBlock']);
187 $block = $this->props[$stream][
'startBlock'];
189 while ($block != -2) {
191 $streamData .= substr($rootdata,
$pos, self::SMALL_BLOCK_SIZE);
193 $block = $this->smallBlockChain[$block];
199 if ($this->props[$stream][
'size'] % self::BIG_BLOCK_SIZE != 0) {
203 if ($numBlocks == 0)
return '';
205 $block = $this->props[$stream][
'startBlock'];
207 while ($block != -2) {
208 $pos = ($block + 1) * self::BIG_BLOCK_SIZE;
209 $streamData .= substr($this->data,
$pos, self::BIG_BLOCK_SIZE);
210 $block = $this->bigBlockChain[$block];
228 while ($block != -2) {
229 $pos = ($block + 1) * self::BIG_BLOCK_SIZE;
230 $data .= substr($this->data,
$pos, self::BIG_BLOCK_SIZE);
231 $block = $this->bigBlockChain[$block];
243 $entryLen = strlen($this->entry);
244 while ($offset < $entryLen) {
246 $d = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE);
249 $nameSize = ord(
$d[self::SIZE_OF_NAME_POS]) | (ord(
$d[self::SIZE_OF_NAME_POS+1]) << 8);
252 $type = ord(
$d[self::TYPE_POS]);
260 $name = str_replace(
"\x00",
"", substr(
$d,0,$nameSize));
262 $this->props[] = array (
265 'startBlock' => $startBlock,
270 $this->wrkbook = count($this->props) - 1;
275 $this->rootentry = count($this->props) - 1;
279 if (
$name == chr(5) .
'SummaryInformation') {
281 $this->summaryInformation = count($this->props) - 1;
285 if (
$name == chr(5) .
'DocumentSummaryInformation') {
287 $this->documentSummaryInformation = count($this->props) - 1;
308 if ($_or_24 >= 128) {
310 $_ord_24 = -abs((256 - $_or_24) << 24);
312 $_ord_24 = ($_or_24 & 127) << 24;
314 return ord(
$data[
$pos]) | (ord(
$data[$pos + 1]) << 8) | (ord(
$data[$pos + 2]) << 16) | $_ord_24;