ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Root.php
Go to the documentation of this file.
1<?php
2
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// | license@php.net so we can mail you a copy immediately. |
18// +----------------------------------------------------------------------+
19// | Author: Xavier Noguer <xnoguer@php.net> |
20// | Based on OLE::Storage_Lite by Kawai, Takanori |
21// +----------------------------------------------------------------------+
22//
25
31class Root extends PPS
32{
36 private $fileHandle;
37
42
47
53 public function __construct($time_1st, $time_2nd, $raChild)
54 {
55 parent::__construct(null, OLE::ascToUcs('Root Entry'), OLE::OLE_PPS_TYPE_ROOT, null, null, null, $time_1st, $time_2nd, null, $raChild);
56 }
57
69 public function save($fileHandle)
70 {
71 $this->fileHandle = $fileHandle;
72
73 // Initial Setting for saving
74 $this->bigBlockSize = 2 ** (
75 (isset($this->bigBlockSize)) ? self::adjust2($this->bigBlockSize) : 9
76 );
77 $this->smallBlockSize = 2 ** (
78 (isset($this->smallBlockSize)) ? self::adjust2($this->smallBlockSize) : 6
79 );
80
81 // Make an array of PPS's (for Save)
82 $aList = [];
83 PPS::savePpsSetPnt($aList, [$this]);
84 // calculate values for header
85 [$iSBDcnt, $iBBcnt, $iPPScnt] = $this->calcSize($aList); //, $rhInfo);
86 // Save Header
87 $this->saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
88
89 // Make Small Data string (write SBD)
90 $this->_data = $this->makeSmallData($aList);
91
92 // Write BB
93 $this->saveBigData($iSBDcnt, $aList);
94 // Write PPS
95 $this->savePps($aList);
96 // Write Big Block Depot and BDList and Adding Header informations
97 $this->saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
98
99 return true;
100 }
101
109 private function calcSize(&$raList)
110 {
111 // Calculate Basic Setting
112 [$iSBDcnt, $iBBcnt, $iPPScnt] = [0, 0, 0];
113 $iSmallLen = 0;
114 $iSBcnt = 0;
115 $iCount = count($raList);
116 for ($i = 0; $i < $iCount; ++$i) {
117 if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) {
118 $raList[$i]->Size = $raList[$i]->getDataLen();
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 $iSmallLen = $iSBcnt * $this->smallBlockSize;
129 $iSlCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE);
130 $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt) ? 1 : 0);
131 $iBBcnt += (floor($iSmallLen / $this->bigBlockSize) +
132 (($iSmallLen % $this->bigBlockSize) ? 1 : 0));
133 $iCnt = count($raList);
134 $iBdCnt = $this->bigBlockSize / OLE::OLE_PPS_SIZE;
135 $iPPScnt = (floor($iCnt / $iBdCnt) + (($iCnt % $iBdCnt) ? 1 : 0));
136
137 return [$iSBDcnt, $iBBcnt, $iPPScnt];
138 }
139
149 private static function adjust2($i2)
150 {
151 $iWk = log($i2) / log(2);
152
153 return ($iWk > floor($iWk)) ? floor($iWk) + 1 : $iWk;
154 }
155
163 private function saveHeader($iSBDcnt, $iBBcnt, $iPPScnt): void
164 {
165 $FILE = $this->fileHandle;
166
167 // Calculate Basic Setting
168 $iBlCnt = $this->bigBlockSize / OLE::OLE_LONG_INT_SIZE;
169 $i1stBdL = ($this->bigBlockSize - 0x4C) / OLE::OLE_LONG_INT_SIZE;
170
171 $iBdExL = 0;
172 $iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
173 $iAllW = $iAll;
174 $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
175 $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0);
176
177 // Calculate BD count
178 if ($iBdCnt > $i1stBdL) {
179 while (1) {
180 ++$iBdExL;
181 ++$iAllW;
182 $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
183 $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW + $iBdCntW) % $iBlCnt) ? 1 : 0);
184 if ($iBdCnt <= ($iBdExL * $iBlCnt + $i1stBdL)) {
185 break;
186 }
187 }
188 }
189
190 // Save Header
191 fwrite(
192 $FILE,
193 "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
194 . "\x00\x00\x00\x00"
195 . "\x00\x00\x00\x00"
196 . "\x00\x00\x00\x00"
197 . "\x00\x00\x00\x00"
198 . pack('v', 0x3b)
199 . pack('v', 0x03)
200 . pack('v', -2)
201 . pack('v', 9)
202 . pack('v', 6)
203 . pack('v', 0)
204 . "\x00\x00\x00\x00"
205 . "\x00\x00\x00\x00"
206 . pack('V', $iBdCnt)
207 . pack('V', $iBBcnt + $iSBDcnt) //ROOT START
208 . pack('V', 0)
209 . pack('V', 0x1000)
210 . pack('V', $iSBDcnt ? 0 : -2) //Small Block Depot
211 . pack('V', $iSBDcnt)
212 );
213 // Extra BDList Start, Count
214 if ($iBdCnt < $i1stBdL) {
215 fwrite(
216 $FILE,
217 pack('V', -2) // Extra BDList Start
218 . pack('V', 0)// Extra BDList Count
219 );
220 } else {
221 fwrite($FILE, pack('V', $iAll + $iBdCnt) . pack('V', $iBdExL));
222 }
223
224 // BDList
225 for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) {
226 fwrite($FILE, pack('V', $iAll + $i));
227 }
228 if ($i < $i1stBdL) {
229 $jB = $i1stBdL - $i;
230 for ($j = 0; $j < $jB; ++$j) {
231 fwrite($FILE, (pack('V', -1)));
232 }
233 }
234 }
235
242 private function saveBigData($iStBlk, &$raList): void
243 {
244 $FILE = $this->fileHandle;
245
246 // cycle through PPS's
247 $iCount = count($raList);
248 for ($i = 0; $i < $iCount; ++$i) {
249 if ($raList[$i]->Type != OLE::OLE_PPS_TYPE_DIR) {
250 $raList[$i]->Size = $raList[$i]->getDataLen();
251 if (($raList[$i]->Size >= OLE::OLE_DATA_SIZE_SMALL) || (($raList[$i]->Type == OLE::OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data))) {
252 fwrite($FILE, $raList[$i]->_data);
253
254 if ($raList[$i]->Size % $this->bigBlockSize) {
255 fwrite($FILE, str_repeat("\x00", $this->bigBlockSize - ($raList[$i]->Size % $this->bigBlockSize)));
256 }
257 // Set For PPS
258 $raList[$i]->startBlock = $iStBlk;
259 $iStBlk +=
260 (floor($raList[$i]->Size / $this->bigBlockSize) +
261 (($raList[$i]->Size % $this->bigBlockSize) ? 1 : 0));
262 }
263 }
264 }
265 }
266
274 private function makeSmallData(&$raList)
275 {
276 $sRes = '';
277 $FILE = $this->fileHandle;
278 $iSmBlk = 0;
279
280 $iCount = count($raList);
281 for ($i = 0; $i < $iCount; ++$i) {
282 // Make SBD, small data string
283 if ($raList[$i]->Type == OLE::OLE_PPS_TYPE_FILE) {
284 if ($raList[$i]->Size <= 0) {
285 continue;
286 }
287 if ($raList[$i]->Size < OLE::OLE_DATA_SIZE_SMALL) {
288 $iSmbCnt = floor($raList[$i]->Size / $this->smallBlockSize)
289 + (($raList[$i]->Size % $this->smallBlockSize) ? 1 : 0);
290 // Add to SBD
291 $jB = $iSmbCnt - 1;
292 for ($j = 0; $j < $jB; ++$j) {
293 fwrite($FILE, pack('V', $j + $iSmBlk + 1));
294 }
295 fwrite($FILE, pack('V', -2));
296
297 // Add to Data String(this will be written for RootEntry)
298 $sRes .= $raList[$i]->_data;
299 if ($raList[$i]->Size % $this->smallBlockSize) {
300 $sRes .= str_repeat("\x00", $this->smallBlockSize - ($raList[$i]->Size % $this->smallBlockSize));
301 }
302 // Set for PPS
303 $raList[$i]->startBlock = $iSmBlk;
304 $iSmBlk += $iSmbCnt;
305 }
306 }
307 }
308 $iSbCnt = floor($this->bigBlockSize / OLE::OLE_LONG_INT_SIZE);
309 if ($iSmBlk % $iSbCnt) {
310 $iB = $iSbCnt - ($iSmBlk % $iSbCnt);
311 for ($i = 0; $i < $iB; ++$i) {
312 fwrite($FILE, pack('V', -1));
313 }
314 }
315
316 return $sRes;
317 }
318
324 private function savePps(&$raList): void
325 {
326 // Save each PPS WK
327 $iC = count($raList);
328 for ($i = 0; $i < $iC; ++$i) {
329 fwrite($this->fileHandle, $raList[$i]->getPpsWk());
330 }
331 // Adjust for Block
332 $iCnt = count($raList);
333 $iBCnt = $this->bigBlockSize / OLE::OLE_PPS_SIZE;
334 if ($iCnt % $iBCnt) {
335 fwrite($this->fileHandle, str_repeat("\x00", ($iBCnt - ($iCnt % $iBCnt)) * OLE::OLE_PPS_SIZE));
336 }
337 }
338
346 private function saveBbd($iSbdSize, $iBsize, $iPpsCnt): void
347 {
348 $FILE = $this->fileHandle;
349 // Calculate Basic Setting
350 $iBbCnt = $this->bigBlockSize / OLE::OLE_LONG_INT_SIZE;
351 $i1stBdL = ($this->bigBlockSize - 0x4C) / OLE::OLE_LONG_INT_SIZE;
352
353 $iBdExL = 0;
354 $iAll = $iBsize + $iPpsCnt + $iSbdSize;
355 $iAllW = $iAll;
356 $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
357 $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0);
358 // Calculate BD count
359 if ($iBdCnt > $i1stBdL) {
360 while (1) {
361 ++$iBdExL;
362 ++$iAllW;
363 $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
364 $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW + $iBdCntW) % $iBbCnt) ? 1 : 0);
365 if ($iBdCnt <= ($iBdExL * $iBbCnt + $i1stBdL)) {
366 break;
367 }
368 }
369 }
370
371 // Making BD
372 // Set for SBD
373 if ($iSbdSize > 0) {
374 for ($i = 0; $i < ($iSbdSize - 1); ++$i) {
375 fwrite($FILE, pack('V', $i + 1));
376 }
377 fwrite($FILE, pack('V', -2));
378 }
379 // Set for B
380 for ($i = 0; $i < ($iBsize - 1); ++$i) {
381 fwrite($FILE, pack('V', $i + $iSbdSize + 1));
382 }
383 fwrite($FILE, pack('V', -2));
384
385 // Set for PPS
386 for ($i = 0; $i < ($iPpsCnt - 1); ++$i) {
387 fwrite($FILE, pack('V', $i + $iSbdSize + $iBsize + 1));
388 }
389 fwrite($FILE, pack('V', -2));
390 // Set for BBD itself ( 0xFFFFFFFD : BBD)
391 for ($i = 0; $i < $iBdCnt; ++$i) {
392 fwrite($FILE, pack('V', 0xFFFFFFFD));
393 }
394 // Set for ExtraBDList
395 for ($i = 0; $i < $iBdExL; ++$i) {
396 fwrite($FILE, pack('V', 0xFFFFFFFC));
397 }
398 // Adjust for Block
399 if (($iAllW + $iBdCnt) % $iBbCnt) {
400 $iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt));
401 for ($i = 0; $i < $iBlock; ++$i) {
402 fwrite($FILE, pack('V', -1));
403 }
404 }
405 // Extra BDList
406 if ($iBdCnt > $i1stBdL) {
407 $iN = 0;
408 $iNb = 0;
409 for ($i = $i1stBdL; $i < $iBdCnt; $i++, ++$iN) {
410 if ($iN >= ($iBbCnt - 1)) {
411 $iN = 0;
412 ++$iNb;
413 fwrite($FILE, pack('V', $iAll + $iBdCnt + $iNb));
414 }
415 fwrite($FILE, pack('V', $iBsize + $iSbdSize + $iPpsCnt + $i));
416 }
417 if (($iBdCnt - $i1stBdL) % ($iBbCnt - 1)) {
418 $iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1));
419 for ($i = 0; $i < $iB; ++$i) {
420 fwrite($FILE, pack('V', -1));
421 }
422 }
423 fwrite($FILE, pack('V', -2));
424 }
425 }
426}
An exception for terminatinating execution or to throw for unit testing.
Class for creating Root PPS's for OLE containers.
Definition: Root.php:32
static adjust2($i2)
Helper function for caculating a magic value for block sizes.
Definition: Root.php:149
saveBigData($iStBlk, &$raList)
Saving big data (PPS's with data bigger than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMAL...
Definition: Root.php:242
savePps(&$raList)
Saves all the PPS's WKs.
Definition: Root.php:324
saveBbd($iSbdSize, $iBsize, $iPpsCnt)
Saving Big Block Depot.
Definition: Root.php:346
saveHeader($iSBDcnt, $iBBcnt, $iPPScnt)
Save OLE header.
Definition: Root.php:163
makeSmallData(&$raList)
get small data (PPS's with data smaller than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMAL...
Definition: Root.php:274
calcSize(&$raList)
Calculate some numbers.
Definition: Root.php:109
save($fileHandle)
Method for saving the whole OLE container (including files).
Definition: Root.php:69
__construct($time_1st, $time_2nd, $raChild)
Definition: Root.php:53
Class for creating PPS's for OLE containers.
Definition: PPS.php:31
static savePpsSetPnt(&$raList, $to_save, $depth=0)
Updates index and pointers to previous, next and children PPS's for this PPS.
Definition: PPS.php:210
getPpsWk()
Returns a string with the PPS's WK (What is a WK?).
Definition: PPS.php:175
static ascToUcs($ascii)
Utility function to transform ASCII text to Unicode.
Definition: OLE.php:478
$i
Definition: disco.tpl.php:19