/var/www/hkosl.com/imusiccircle/webadmin/libraies/phpoffice/phpexcel/Classes/PHPExcel/Shared/OLERead.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
<?php
/**
 * PHPExcel
 *
 * Copyright (c) 2006 - 2014 PHPExcel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   PHPExcel
 * @package    PHPExcel_Shared
 * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
 * @version    ##VERSION##, ##DATE##
 */

defined('IDENTIFIER_OLE') ||
    
define('IDENTIFIER_OLE'pack('CCCCCCCC'0xd00xcf0x110xe00xa10xb10x1a0xe1));

class 
PHPExcel_Shared_OLERead {
    private 
$data '';

    
// OLE identifier
    
const IDENTIFIER_OLE IDENTIFIER_OLE;

    
// Size of a sector = 512 bytes
    
const BIG_BLOCK_SIZE                    0x200;

    
// Size of a short sector = 64 bytes
    
const SMALL_BLOCK_SIZE                    0x40;

    
// Size of a directory entry always = 128 bytes
    
const PROPERTY_STORAGE_BLOCK_SIZE        0x80;

    
// Minimum size of a standard stream = 4096 bytes, streams smaller than this are stored as short streams
    
const SMALL_BLOCK_THRESHOLD                0x1000;

    
// header offsets
    
const NUM_BIG_BLOCK_DEPOT_BLOCKS_POS    0x2c;
    const 
ROOT_START_BLOCK_POS                0x30;
    const 
SMALL_BLOCK_DEPOT_BLOCK_POS        0x3c;
    const 
EXTENSION_BLOCK_POS                0x44;
    const 
NUM_EXTENSION_BLOCK_POS            0x48;
    const 
BIG_BLOCK_DEPOT_BLOCKS_POS        0x4c;

    
// property storage offsets (directory offsets)
    
const SIZE_OF_NAME_POS                    0x40;
    const 
TYPE_POS                            0x42;
    const 
START_BLOCK_POS                    0x74;
    const 
SIZE_POS                            0x78;



    public 
$wrkbook                        null;
    public 
$summaryInformation            null;
    public 
$documentSummaryInformation    null;


    
/**
     * Read the file
     *
     * @param $sFileName string Filename
     * @throws PHPExcel_Reader_Exception
     */
    
public function read($sFileName)
    {
        
// Check if file exists and is readable
        
if(!is_readable($sFileName)) {
            throw new 
PHPExcel_Reader_Exception("Could not open " $sFileName " for reading! File does not exist, or it is not readable.");
        }

        
// Get the file identifier
        // Don't bother reading the whole file until we know it's a valid OLE file
        
$this->data file_get_contents($sFileNameFALSENULL08);

        
// Check OLE identifier
        
if ($this->data != self::IDENTIFIER_OLE) {
            throw new 
PHPExcel_Reader_Exception('The filename ' $sFileName ' is not recognised as an OLE file');
        }

        
// Get the file data
        
$this->data file_get_contents($sFileName);

        
// Total number of sectors used for the SAT
        
$this->numBigBlockDepotBlocks self::_GetInt4d($this->dataself::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);

        
// SecID of the first sector of the directory stream
        
$this->rootStartBlock self::_GetInt4d($this->dataself::ROOT_START_BLOCK_POS);

        
// SecID of the first sector of the SSAT (or -2 if not extant)
        
$this->sbdStartBlock self::_GetInt4d($this->dataself::SMALL_BLOCK_DEPOT_BLOCK_POS);

        
// SecID of the first sector of the MSAT (or -2 if no additional sectors are used)
        
$this->extensionBlock self::_GetInt4d($this->dataself::EXTENSION_BLOCK_POS);

        
// Total number of sectors used by MSAT
        
$this->numExtensionBlocks self::_GetInt4d($this->dataself::NUM_EXTENSION_BLOCK_POS);

        
$bigBlockDepotBlocks = array();
        
$pos self::BIG_BLOCK_DEPOT_BLOCKS_POS;

        
$bbdBlocks $this->numBigBlockDepotBlocks;

        if (
$this->numExtensionBlocks != 0) {
            
$bbdBlocks = (self::BIG_BLOCK_SIZE self::BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
        }

        for (
$i 0$i $bbdBlocks; ++$i) {
              
$bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data$pos);
              
$pos += 4;
        }

        for (
$j 0$j $this->numExtensionBlocks; ++$j) {
            
$pos = ($this->extensionBlock 1) * self::BIG_BLOCK_SIZE;
            
$blocksToRead min($this->numBigBlockDepotBlocks $bbdBlocksself::BIG_BLOCK_SIZE 1);

            for (
$i $bbdBlocks$i $bbdBlocks $blocksToRead; ++$i) {
                
$bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data$pos);
                
$pos += 4;
            }

            
$bbdBlocks += $blocksToRead;
            if (
$bbdBlocks $this->numBigBlockDepotBlocks) {
                
$this->extensionBlock self::_GetInt4d($this->data$pos);
            }
        }

        
$pos 0;
        
$this->bigBlockChain '';
        
$bbs self::BIG_BLOCK_SIZE 4;
        for (
$i 0$i $this->numBigBlockDepotBlocks; ++$i) {
            
$pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;

            
$this->bigBlockChain .= substr($this->data$pos4*$bbs);
            
$pos += 4*$bbs;
        }

        
$pos 0;
        
$sbdBlock $this->sbdStartBlock;
        
$this->smallBlockChain '';
        while (
$sbdBlock != -2) {
            
$pos = ($sbdBlock 1) * self::BIG_BLOCK_SIZE;

            
$this->smallBlockChain .= substr($this->data$pos4*$bbs);
            
$pos += 4*$bbs;

            
$sbdBlock self::_GetInt4d($this->bigBlockChain$sbdBlock*4);
        }

        
// read the directory stream
        
$block $this->rootStartBlock;
        
$this->entry $this->_readData($block);

        
$this->_readPropertySets();
    }

    
/**
     * Extract binary stream data
     *
     * @return string
     */
    
public function getStream($stream)
    {
        if (
$stream === NULL) {
            return 
null;
        }

        
$streamData '';

        if (
$this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) {
            
$rootdata $this->_readData($this->props[$this->rootentry]['startBlock']);

            
$block $this->props[$stream]['startBlock'];

            while (
$block != -2) {
                  
$pos $block self::SMALL_BLOCK_SIZE;
                
$streamData .= substr($rootdata$posself::SMALL_BLOCK_SIZE);

                
$block self::_GetInt4d($this->smallBlockChain$block*4);
            }

            return 
$streamData;
        } else {
            
$numBlocks $this->props[$stream]['size'] / self::BIG_BLOCK_SIZE;
            if (
$this->props[$stream]['size'] % self::BIG_BLOCK_SIZE != 0) {
                ++
$numBlocks;
            }

            if (
$numBlocks == 0) return '';

            
$block $this->props[$stream]['startBlock'];

            while (
$block != -2) {
                
$pos = ($block 1) * self::BIG_BLOCK_SIZE;
                
$streamData .= substr($this->data$posself::BIG_BLOCK_SIZE);
                
$block self::_GetInt4d($this->bigBlockChain$block*4);
            }

            return 
$streamData;
        }
    }

    
/**
     * Read a standard stream (by joining sectors using information from SAT)
     *
     * @param int $bl Sector ID where the stream starts
     * @return string Data for standard stream
     */
    
private function _readData($bl)
    {
        
$block $bl;
        
$data '';

        while (
$block != -2)  {
            
$pos = ($block 1) * self::BIG_BLOCK_SIZE;
            
$data .= substr($this->data$posself::BIG_BLOCK_SIZE);
            
$block self::_GetInt4d($this->bigBlockChain$block*4);
        }
        return 
$data;
     }

    
/**
     * Read entries in the directory stream.
     */
    
private function _readPropertySets() {
        
$offset 0;

        
// loop through entires, each entry is 128 bytes
        
$entryLen strlen($this->entry);
        while (
$offset $entryLen) {
            
// entry data (128 bytes)
            
$d substr($this->entry$offsetself::PROPERTY_STORAGE_BLOCK_SIZE);

            
// size in bytes of name
            
$nameSize ord($d[self::SIZE_OF_NAME_POS]) | (ord($d[self::SIZE_OF_NAME_POS+1]) << 8);

            
// type of entry
            
$type ord($d[self::TYPE_POS]);

            
// sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook)
            // sectorID of first sector of the short-stream container stream, if this entry is root entry
            
$startBlock self::_GetInt4d($dself::START_BLOCK_POS);

            
$size self::_GetInt4d($dself::SIZE_POS);

            
$name str_replace("\x00"""substr($d,0,$nameSize));


            
$this->props[] = array (
                
'name' => $name,
                
'type' => $type,
                
'startBlock' => $startBlock,
                
'size' => $size);

            
// tmp helper to simplify checks
            
$upName strtoupper($name);

            
// Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook)
            
if (($upName === 'WORKBOOK') || ($upName === 'BOOK')) {
                
$this->wrkbook count($this->props) - 1;
            }
            else if ( 
$upName === 'ROOT ENTRY' || $upName === 'R') {
                
// Root entry
                
$this->rootentry count($this->props) - 1;
            }

            
// Summary information
            
if ($name == chr(5) . 'SummaryInformation') {
//                echo 'Summary Information<br />';
                
$this->summaryInformation count($this->props) - 1;
            }

            
// Additional Document Summary information
            
if ($name == chr(5) . 'DocumentSummaryInformation') {
//                echo 'Document Summary Information<br />';
                
$this->documentSummaryInformation count($this->props) - 1;
            }

            
$offset += self::PROPERTY_STORAGE_BLOCK_SIZE;
        }

    }

    
/**
     * Read 4 bytes of data at specified position
     *
     * @param string $data
     * @param int $pos
     * @return int
     */
    
private static function _GetInt4d($data$pos)
    {
        
// FIX: represent numbers correctly on 64-bit system
        // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
        // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
        
$_or_24 ord($data[$pos 3]);
        if (
$_or_24 >= 128) {
            
// negative number
            
$_ord_24 = -abs((256 $_or_24) << 24);
        } else {
            
$_ord_24 = ($_or_24 127) << 24;
        }
        return 
ord($data[$pos]) | (ord($data[$pos 1]) << 8) | (ord($data[$pos 2]) << 16) | $_ord_24;
    }

}