2 define('NUM_BIG_BLOCK_DEPOT_BLOCKS_POS', 0x2c);
3 define('SMALL_BLOCK_DEPOT_BLOCK_POS', 0x3c);
4 define('ROOT_START_BLOCK_POS', 0x30);
5 define('BIG_BLOCK_SIZE', 0x200);
6 define('SMALL_BLOCK_SIZE', 0x40);
7 define('EXTENSION_BLOCK_POS', 0x44);
8 define('NUM_EXTENSION_BLOCK_POS', 0x48);
9 define('PROPERTY_STORAGE_BLOCK_SIZE', 0x80);
10 define('BIG_BLOCK_DEPOT_BLOCKS_POS', 0x4c);
11 define('SMALL_BLOCK_THRESHOLD', 0x1000);
12 // property storage offsets
13 define('SIZE_OF_NAME_POS', 0x40);
14 define('TYPE_POS', 0x42);
15 define('START_BLOCK_POS', 0x74);
16 define('SIZE_POS', 0x78);
17 define('IDENTIFIER_OLE', pack("CCCCCCCC",0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1));
19 //echo 'ROOT_START_BLOCK_POS = '.ROOT_START_BLOCK_POS."\n";
21 //echo bin2hex($data[ROOT_START_BLOCK_POS])."\n";
23 //echo $data[ROOT_START_BLOCK_POS];
26 function GetInt4d($data, $pos) {
27 return ord($data[$pos]) |
(ord($data[$pos+
1]) << 8) |
(ord($data[$pos+
2]) << 16) |
(ord($data[$pos+
3]) << 24);
40 function read($sFileName){
42 // check if file exist and is readable (Darko Miljanovic)
43 if(!is_readable($sFileName)) {
48 $this->data
= @file_get_contents
($sFileName);
53 //echo IDENTIFIER_OLE;
55 if (substr($this->data
, 0, 8) != IDENTIFIER_OLE
) {
59 $this->numBigBlockDepotBlocks
= GetInt4d($this->data
, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS
);
60 $this->sbdStartBlock
= GetInt4d($this->data
, SMALL_BLOCK_DEPOT_BLOCK_POS
);
61 $this->rootStartBlock
= GetInt4d($this->data
, ROOT_START_BLOCK_POS
);
62 $this->extensionBlock
= GetInt4d($this->data
, EXTENSION_BLOCK_POS
);
63 $this->numExtensionBlocks
= GetInt4d($this->data
, NUM_EXTENSION_BLOCK_POS
);
66 echo $this->numBigBlockDepotBlocks." ";
67 echo $this->sbdStartBlock." ";
68 echo $this->rootStartBlock." ";
69 echo $this->extensionBlock." ";
70 echo $this->numExtensionBlocks." ";
72 //echo "sbdStartBlock = $this->sbdStartBlock\n";
73 $bigBlockDepotBlocks = array();
74 $pos = BIG_BLOCK_DEPOT_BLOCKS_POS
;
76 $bbdBlocks = $this->numBigBlockDepotBlocks
;
78 if ($this->numExtensionBlocks
!= 0) {
79 $bbdBlocks = (BIG_BLOCK_SIZE
- BIG_BLOCK_DEPOT_BLOCKS_POS
)/4;
82 for ($i = 0; $i < $bbdBlocks; $i++
) {
83 $bigBlockDepotBlocks[$i] = GetInt4d($this->data
, $pos);
88 for ($j = 0; $j < $this->numExtensionBlocks
; $j++
) {
89 $pos = ($this->extensionBlock +
1) * BIG_BLOCK_SIZE
;
90 $blocksToRead = min($this->numBigBlockDepotBlocks
- $bbdBlocks, BIG_BLOCK_SIZE
/ 4 - 1);
92 for ($i = $bbdBlocks; $i < $bbdBlocks +
$blocksToRead; $i++
) {
93 $bigBlockDepotBlocks[$i] = GetInt4d($this->data
, $pos);
97 $bbdBlocks +
= $blocksToRead;
98 if ($bbdBlocks < $this->numBigBlockDepotBlocks
) {
99 $this->extensionBlock
= GetInt4d($this->data
, $pos);
103 // var_dump($bigBlockDepotBlocks);
108 $this->bigBlockChain
= array();
110 for ($i = 0; $i < $this->numBigBlockDepotBlocks
; $i++
) {
111 $pos = ($bigBlockDepotBlocks[$i] +
1) * BIG_BLOCK_SIZE
;
113 for ($j = 0 ; $j < BIG_BLOCK_SIZE
/ 4; $j++
) {
114 $this->bigBlockChain
[$index] = GetInt4d($this->data
, $pos);
120 //var_dump($this->bigBlockChain);
122 // readSmallBlockDepot();
125 $sbdBlock = $this->sbdStartBlock
;
126 $this->smallBlockChain
= array();
128 while ($sbdBlock != -2) {
130 $pos = ($sbdBlock +
1) * BIG_BLOCK_SIZE
;
132 for ($j = 0; $j < BIG_BLOCK_SIZE
/ 4; $j++
) {
133 $this->smallBlockChain
[$index] = GetInt4d($this->data
, $pos);
138 $sbdBlock = $this->bigBlockChain
[$sbdBlock];
142 // readData(rootStartBlock)
143 $block = $this->rootStartBlock
;
145 $this->entry
= $this->__readData($block);
148 while ($block != -2) {
149 $pos = ($block + 1) * BIG_BLOCK_SIZE;
150 $this->entry = $this->entry.substr($this->data, $pos, BIG_BLOCK_SIZE);
151 $block = $this->bigBlockChain[$block];
154 //echo '==='.$this->entry."===";
155 $this->__readPropertySets();
159 function __readData($bl) {
164 while ($block != -2) {
165 $pos = ($block +
1) * BIG_BLOCK_SIZE
;
166 $data = $data.substr($this->data
, $pos, BIG_BLOCK_SIZE
);
167 //echo "pos = $pos data=$data\n";
168 $block = $this->bigBlockChain
[$block];
173 function __readPropertySets(){
175 //var_dump($this->entry);
176 while ($offset < strlen($this->entry
)) {
177 $d = substr($this->entry
, $offset, PROPERTY_STORAGE_BLOCK_SIZE
);
179 $nameSize = ord($d[SIZE_OF_NAME_POS
]) |
(ord($d[SIZE_OF_NAME_POS+
1]) << 8);
181 $type = ord($d[TYPE_POS
]);
182 //$maxBlock = strlen($d) / BIG_BLOCK_SIZE - 1;
184 $startBlock = GetInt4d($d, START_BLOCK_POS
);
185 $size = GetInt4d($d, SIZE_POS
);
188 for ($i = 0; $i < $nameSize ; $i++
) {
192 $name = str_replace("\x00", "", $name);
194 $this->props
[] = array (
197 'startBlock' => $startBlock,
200 if (($name == "Workbook") ||
($name == "Book")) {
201 $this->wrkbook
= count($this->props
) - 1;
204 if ($name == "Root Entry") {
205 $this->rootentry
= count($this->props
) - 1;
208 //echo "name ==$name=\n";
211 $offset +
= PROPERTY_STORAGE_BLOCK_SIZE
;
217 function getWorkBook(){
218 if ($this->props
[$this->wrkbook
]['size'] < SMALL_BLOCK_THRESHOLD
){
219 // getSmallBlockStream(PropertyStorage ps)
221 $rootdata = $this->__readData($this->props
[$this->rootentry
]['startBlock']);
224 $block = $this->props
[$this->wrkbook
]['startBlock'];
227 while ($block != -2) {
228 $pos = $block * SMALL_BLOCK_SIZE
;
229 $streamData .= substr($rootdata, $pos, SMALL_BLOCK_SIZE
);
231 $block = $this->smallBlockChain
[$block];
239 $numBlocks = $this->props
[$this->wrkbook
]['size'] / BIG_BLOCK_SIZE
;
240 if ($this->props
[$this->wrkbook
]['size'] % BIG_BLOCK_SIZE
!= 0) {
244 if ($numBlocks == 0) return '';
246 //echo "numBlocks = $numBlocks\n";
247 //byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE];
248 //print_r($this->wrkbook);
250 $block = $this->props
[$this->wrkbook
]['startBlock'];
253 //echo "block = $block";
254 while ($block != -2) {
255 $pos = ($block +
1) * BIG_BLOCK_SIZE
;
256 $streamData .= substr($this->data
, $pos, BIG_BLOCK_SIZE
);
257 $block = $this->bigBlockChain
[$block];
259 //echo 'stream'.$streamData;