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 
31 class Root extends PPS
32 {
36  private $fileHandle;
37 
41  private $smallBlockSize;
42 
46  private $bigBlockSize;
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 }
calcSize(&$raList)
Calculate some numbers.
Definition: Root.php:109
static ascToUcs($ascii)
Utility function to transform ASCII text to Unicode.
Definition: OLE.php:478
static adjust2($i2)
Helper function for caculating a magic value for block sizes.
Definition: Root.php:149
static savePpsSetPnt(&$raList, $to_save, $depth=0)
Updates index and pointers to previous, next and children PPS&#39;s for this PPS.
Definition: PPS.php:210
Class for creating PPS&#39;s for OLE containers.
Definition: PPS.php:30
saveBigData($iStBlk, &$raList)
Saving big data (PPS&#39;s with data bigger than ::OLE_DATA_SIZE_SMALL).
Definition: Root.php:242
saveBbd($iSbdSize, $iBsize, $iPpsCnt)
Saving Big Block Depot.
Definition: Root.php:346
save($fileHandle)
Method for saving the whole OLE container (including files).
Definition: Root.php:69
makeSmallData(&$raList)
get small data (PPS&#39;s with data smaller than ::OLE_DATA_SIZE_SMALL).
Definition: Root.php:274
__construct($time_1st, $time_2nd, $raChild)
Definition: Root.php:53
$i
Definition: disco.tpl.php:19
savePps(&$raList)
Saves all the PPS&#39;s WKs.
Definition: Root.php:324
Class for creating Root PPS&#39;s for OLE containers.
Definition: Root.php:31
getPpsWk()
Returns a string with the PPS&#39;s WK (What is a WK?).
Definition: PPS.php:175
saveHeader($iSBDcnt, $iBBcnt, $iPPScnt)
Save OLE header.
Definition: Root.php:163