PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Shared / OLE / PPS / Root.php

Root.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Shared/OLE/PPS/Root.php

417 lines 12.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Shared\OLE\PPS;
4
5 // vim: set expandtab tabstop=4 shiftwidth=4:
6 // +----------------------------------------------------------------------+
7 // | PHP Version 4 |
8 // +----------------------------------------------------------------------+
9 // | Copyright (c) 1997-2002 The PHP Group |
10 // +----------------------------------------------------------------------+
11 // | This source file is subject to version 2.02 of the PHP license, |
12 // | that is bundled with this package in the file LICENSE, and is |
13 // | available at through the world-wide-web at |
14 // | http://www.php.net/license/2_02.txt. |
15 // | If you did not receive a copy of the PHP license and are unable to |
16 // | obtain it through the world-wide-web, please send a note to |
17 // | [email protected] so we can mail you a copy immediately. |
18 // +----------------------------------------------------------------------+
19 // | Author: Xavier Noguer <[email protected]> |
20 // | Based on OLE::Storage_Lite by Kawai, Takanori |
21 // +----------------------------------------------------------------------+
22 //
23 use TablePress\PhpOffice\PhpSpreadsheet\Exception;
24 use TablePress\PhpOffice\PhpSpreadsheet\Shared\OLE;
25 use TablePress\PhpOffice\PhpSpreadsheet\Shared\OLE\PPS;
26
27 /**
28 * Class for creating Root PPS's for OLE containers.
29 *
30 * @author Xavier Noguer <[email protected]>
31 */
32 class Root extends PPS
33 {
34 private const BIG_BLOCK_SIZE = 512;
35
36 private const SMALL_BLOCK_SIZE = 64;
37
38 private const MAX_VERSION_3_STREAM_SIZE = 0x80000000;
39
40 private const MAX_REGULAR_SECTOR_COUNT = 0xFFFFFFFB;
41
42 /**
43 * @var resource
44 */
45 private $fileHandle;
46
47 private int $smallBlockSize = self::SMALL_BLOCK_SIZE;
48
49 private int $bigBlockSize = self::BIG_BLOCK_SIZE;
50
51 /**
52 * @param null|float|int $time_1st A timestamp
53 * @param null|float|int $time_2nd A timestamp
54 * @param File[] $raChild
55 */
56 public function __construct($time_1st, $time_2nd, array $raChild)
57 {
58 parent::__construct(null, OLE::ascToUcs('Root Entry'), OLE::OLE_PPS_TYPE_ROOT, null, null, null, $time_1st, $time_2nd, null, $raChild);
59 }
60
61 /**
62 * Method for saving the whole OLE container (including files).
63 * In fact, if called with an empty argument (or '-'), it saves to a
64 * temporary file and then outputs it's contents to stdout.
65 * If a resource pointer to a stream created by fopen() is passed
66 * it will be used, but you have to close such stream by yourself.
67 *
68 * @param resource $fileHandle the name of the file or stream where to save the OLE container
69 *
70 * @return bool true on success
71 */
72 public function save($fileHandle): bool
73 {
74 $this->fileHandle = $fileHandle;
75
76 // This writer implements the version-3 CFB profile only.
77 $this->bigBlockSize = self::BIG_BLOCK_SIZE;
78 $this->smallBlockSize = self::SMALL_BLOCK_SIZE;
79
80 // Make an array of PPS's (for Save)
81 $aList = [];
82 PPS::savePpsSetPnt($aList, [$this]);
83 // calculate values for header
84 [$iSBDcnt, $iBBcnt, $iPPScnt] = $this->calcSize($aList); //, $rhInfo);
85 // Save Header
86 $this->saveHeader((int) $iSBDcnt, (int) $iBBcnt, (int) $iPPScnt);
87
88 // Make Small Data string (write SBD)
89 $this->_data = $this->makeSmallData($aList);
90 $this->assertVersion3StreamSize(strlen($this->_data));
91
92 // Write BB
93 $this->saveBigData((int) $iSBDcnt, $aList);
94 // Write PPS
95 $this->savePps($aList);
96 // Write Big Block Depot and BDList and Adding Header informations
97 $this->saveBbd((int) $iSBDcnt, (int) $iBBcnt, (int) $iPPScnt);
98
99 return true;
100 }
101
102 /**
103 * Calculate some numbers.
104 *
105 * @param PPS[] $raList Reference to an array of PPS's
106 *
107 * @return float[] The array of numbers
108 */
109 private function calcSize(array &$raList): array
110 {
111 // Calculate Basic Setting
112 [$iSBDcnt, $iBBcnt, $iPPScnt] = [0, 0, 0];
113 $iSBcnt = 0;
114 $iCount = count($raList);
115 for ($i = 0; $i < $iCount; ++$i) {
116 if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) {
117 $raList[$i]->Size = $raList[$i]->getDataLen();
118 $this->assertVersion3StreamSize($raList[$i]->Size);
119 if ($raList[$i]->Size < OLE::OLE_DATA_SIZE_SMALL) {
120 $iSBcnt += floor($raList[$i]->Size / $this->smallBlockSize)
121 + (($raList[$i]->Size % $this->smallBlockSize) ? 1 : 0);
122 } else {
123 $iBBcnt += (floor($raList[$i]->Size / $this->bigBlockSize)
124 + (($raList[$i]->Size % $this->bigBlockSize) ? 1 : 0));
125 }
126 }
127 }
128 $this->assertVersion3MiniStreamSize((int) $iSBcnt);
129 $iSmallLen = $iSBcnt * $this->smallBlockSize;
130 $iSlCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE);
131 $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt) ? 1 : 0);
132 $iBBcnt += (floor($iSmallLen / $this->bigBlockSize)
133 + (($iSmallLen % $this->bigBlockSize) ? 1 : 0));
134 $iCnt = count($raList);
135 $iBdCnt = $this->bigBlockSize / OLE::OLE_PPS_SIZE;
136 $iPPScnt = (floor($iCnt / $iBdCnt) + (($iCnt % $iBdCnt) ? 1 : 0));
137
138 return [$iSBDcnt, $iBBcnt, $iPPScnt];
139 }
140
141 private function assertVersion3StreamSize(int $size): void
142 {
143 if ($size > self::MAX_VERSION_3_STREAM_SIZE) {
144 throw new Exception('OLE version-3 streams cannot exceed 2 GiB.');
145 }
146 }
147
148 private function assertVersion3MiniStreamSize(int $smallBlockCount): void
149 {
150 $this->assertVersion3StreamSize($smallBlockCount * self::SMALL_BLOCK_SIZE);
151 }
152
153 /**
154 * Save OLE header.
155 */
156 private function saveHeader(int $iSBDcnt, int $iBBcnt, int $iPPScnt): void
157 {
158 $FILE = $this->fileHandle;
159
160 // Calculate Basic Setting
161 $iBlCnt = $this->bigBlockSize / OLE::OLE_LONG_INT_SIZE;
162 $i1stBdL = ($this->bigBlockSize - 0x4C) / OLE::OLE_LONG_INT_SIZE;
163
164 $iBdExL = 0;
165 $iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
166 $iAllW = $iAll;
167 $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
168 $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0);
169
170 // Calculate BD count
171 if ($iBdCnt > $i1stBdL) {
172 while (1) {
173 ++$iBdExL;
174 ++$iAllW;
175 $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
176 $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0);
177 if ($iBdCnt <= ($iBdExL * ($iBlCnt - 1) + $i1stBdL)) {
178 break;
179 }
180 }
181 }
182
183 if ($iAllW + $iBdCnt > self::MAX_REGULAR_SECTOR_COUNT) {
184 throw new Exception('OLE version-3 output exceeds the maximum sector count.');
185 }
186
187 // Save Header
188 fwrite(
189 $FILE,
190 "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
191 . "\x00\x00\x00\x00"
192 . "\x00\x00\x00\x00"
193 . "\x00\x00\x00\x00"
194 . "\x00\x00\x00\x00"
195 . pack('v', 0x3E)
196 . pack('v', 0x03)
197 . pack('v', -2)
198 . pack('v', 9)
199 . pack('v', 6)
200 . pack('v', 0)
201 . "\x00\x00\x00\x00"
202 . "\x00\x00\x00\x00"
203 . pack('V', $iBdCnt)
204 . pack('V', $iBBcnt + $iSBDcnt) //ROOT START
205 . pack('V', 0)
206 . pack('V', 0x1000)
207 . pack('V', $iSBDcnt ? 0 : -2) //Small Block Depot
208 . pack('V', $iSBDcnt)
209 );
210 // Extra BDList Start, Count
211 if ($iBdCnt <= $i1stBdL) {
212 fwrite(
213 $FILE,
214 pack('V', -2) // Extra BDList Start
215 . pack('V', 0)// Extra BDList Count
216 );
217 } else {
218 fwrite($FILE, pack('V', $iAll + $iBdCnt) . pack('V', $iBdExL));
219 }
220
221 // BDList
222 for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) {
223 fwrite($FILE, pack('V', $iAll + $i));
224 }
225 if ($i < $i1stBdL) {
226 $jB = $i1stBdL - $i;
227 for ($j = 0; $j < $jB; ++$j) {
228 fwrite($FILE, (pack('V', -1)));
229 }
230 }
231 }
232
233 /**
234 * Saving big data (PPS's with data bigger than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL).
235 *
236 * @param PPS[] $raList Reference to array of PPS's
237 */
238 private function saveBigData(int $iStBlk, array &$raList): void
239 {
240 $FILE = $this->fileHandle;
241
242 // cycle through PPS's
243 $iCount = count($raList);
244 for ($i = 0; $i < $iCount; ++$i) {
245 if ($raList[$i]->Type != OLE::OLE_PPS_TYPE_DIR) {
246 $raList[$i]->Size = $raList[$i]->getDataLen();
247 if (($raList[$i]->Size >= OLE::OLE_DATA_SIZE_SMALL) || (($raList[$i]->Type == OLE::OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data))) {
248 fwrite($FILE, $raList[$i]->_data);
249
250 if ($raList[$i]->Size % $this->bigBlockSize) {
251 fwrite($FILE, str_repeat("\x00", $this->bigBlockSize - ($raList[$i]->Size % $this->bigBlockSize)));
252 }
253 // Set For PPS
254 $raList[$i]->startBlock = $iStBlk;
255 $iStBlk
256 += ((int) floor($raList[$i]->Size / $this->bigBlockSize)
257 + (($raList[$i]->Size % $this->bigBlockSize) ? 1 : 0));
258 }
259 }
260 }
261 }
262
263 /**
264 * get small data (PPS's with data smaller than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL).
265 *
266 * @param PPS[] $raList Reference to array of PPS's
267 */
268 private function makeSmallData(array &$raList): string
269 {
270 $sRes = '';
271 $FILE = $this->fileHandle;
272 $iSmBlk = 0;
273
274 $iCount = count($raList);
275 for ($i = 0; $i < $iCount; ++$i) {
276 // Make SBD, small data string
277 if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) {
278 if ($raList[$i]->Size <= 0) {
279 continue;
280 }
281 if ($raList[$i]->Size < OLE::OLE_DATA_SIZE_SMALL) {
282 $iSmbCnt = (int) floor($raList[$i]->Size / $this->smallBlockSize)
283 + (($raList[$i]->Size % $this->smallBlockSize) ? 1 : 0);
284 // Add to SBD
285 $jB = $iSmbCnt - 1;
286 for ($j = 0; $j < $jB; ++$j) {
287 fwrite($FILE, pack('V', $j + $iSmBlk + 1));
288 }
289 fwrite($FILE, pack('V', -2));
290
291 // Add to Data String(this will be written for RootEntry)
292 $sRes .= $raList[$i]->_data;
293 if ($raList[$i]->Size % $this->smallBlockSize) {
294 $sRes .= str_repeat("\x00", $this->smallBlockSize - ($raList[$i]->Size % $this->smallBlockSize));
295 }
296 // Set for PPS
297 $raList[$i]->startBlock = $iSmBlk;
298 $iSmBlk += $iSmbCnt;
299 }
300 }
301 }
302 $iSbCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE);
303 if ($iSmBlk % $iSbCnt) {
304 $iB = $iSbCnt - ($iSmBlk % $iSbCnt);
305 for ($i = 0; $i < $iB; ++$i) {
306 fwrite($FILE, pack('V', -1));
307 }
308 }
309
310 return $sRes;
311 }
312
313 /**
314 * Saves all the PPS's WKs.
315 *
316 * @param PPS[] $raList Reference to an array with all PPS's
317 */
318 private function savePps(array &$raList): void
319 {
320 // Save each PPS WK
321 $iC = count($raList);
322 for ($i = 0; $i < $iC; ++$i) {
323 fwrite($this->fileHandle, $raList[$i]->getPpsWk());
324 }
325 // Adjust for Block
326 $iCnt = count($raList);
327 $iBCnt = $this->bigBlockSize / OLE::OLE_PPS_SIZE;
328 if ($iCnt % $iBCnt) {
329 fwrite($this->fileHandle, str_repeat("\x00", ($iBCnt - ($iCnt % $iBCnt)) * OLE::OLE_PPS_SIZE));
330 }
331 }
332
333 /**
334 * Saving Big Block Depot.
335 */
336 private function saveBbd(int $iSbdSize, int $iBsize, int $iPpsCnt): void
337 {
338 $FILE = $this->fileHandle;
339 // Calculate Basic Setting
340 $iBbCnt = $this->bigBlockSize / OLE::OLE_LONG_INT_SIZE;
341 $i1stBdL = ($this->bigBlockSize - 0x4C) / OLE::OLE_LONG_INT_SIZE;
342
343 $iBdExL = 0;
344 $iAll = $iBsize + $iPpsCnt + $iSbdSize;
345 $iAllW = $iAll;
346 $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
347 $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0);
348 // Calculate BD count
349 if ($iBdCnt > $i1stBdL) {
350 while (1) {
351 ++$iBdExL;
352 ++$iAllW;
353 $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
354 $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0);
355 if ($iBdCnt <= ($iBdExL * ($iBbCnt - 1) + $i1stBdL)) {
356 break;
357 }
358 }
359 }
360
361 // Making BD
362 // Set for SBD
363 if ($iSbdSize > 0) {
364 for ($i = 0; $i < ($iSbdSize - 1); ++$i) {
365 fwrite($FILE, pack('V', $i + 1));
366 }
367 fwrite($FILE, pack('V', -2));
368 }
369 // Set for B
370 for ($i = 0; $i < ($iBsize - 1); ++$i) {
371 fwrite($FILE, pack('V', $i + $iSbdSize + 1));
372 }
373 fwrite($FILE, pack('V', -2));
374
375 // Set for PPS
376 for ($i = 0; $i < ($iPpsCnt - 1); ++$i) {
377 fwrite($FILE, pack('V', $i + $iSbdSize + $iBsize + 1));
378 }
379 fwrite($FILE, pack('V', -2));
380 // Set for BBD itself ( 0xFFFFFFFD : BBD)
381 for ($i = 0; $i < $iBdCnt; ++$i) {
382 fwrite($FILE, pack('V', 0xFFFFFFFD));
383 }
384 // Set for ExtraBDList
385 for ($i = 0; $i < $iBdExL; ++$i) {
386 fwrite($FILE, pack('V', 0xFFFFFFFC));
387 }
388 // Adjust for Block
389 if (($iAllW + $iBdCnt) % $iBbCnt) {
390 $iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt));
391 for ($i = 0; $i < $iBlock; ++$i) {
392 fwrite($FILE, pack('V', -1));
393 }
394 }
395 // Extra BDList
396 if ($iBdCnt > $i1stBdL) {
397 $iN = 0;
398 $iNb = 0;
399 for ($i = $i1stBdL; $i < $iBdCnt; $i++, ++$iN) {
400 if ($iN >= ($iBbCnt - 1)) {
401 $iN = 0;
402 ++$iNb;
403 fwrite($FILE, pack('V', $iAll + $iBdCnt + $iNb));
404 }
405 fwrite($FILE, pack('V', $iBsize + $iSbdSize + $iPpsCnt + $i));
406 }
407 if (($iBdCnt - $i1stBdL) % ($iBbCnt - 1)) {
408 $iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1));
409 for ($i = 0; $i < $iB; ++$i) {
410 fwrite($FILE, pack('V', -1));
411 }
412 }
413 fwrite($FILE, pack('V', -2));
414 }
415 }
416 }
417