Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / lib / pear / OLE / PPS / Root.php
blob33b6017949f021496de8144320fdf8c0b21d9a9d
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4 |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license, |
9 // | that is bundled with this package in the file LICENSE, and is |
10 // | available at through the world-wide-web at |
11 // | http://www.php.net/license/2_02.txt. |
12 // | If you did not receive a copy of the PHP license and are unable to |
13 // | obtain it through the world-wide-web, please send a note to |
14 // | license@php.net so we can mail you a copy immediately. |
15 // +----------------------------------------------------------------------+
16 // | Author: Xavier Noguer <xnoguer@php.net> |
17 // | Based on OLE::Storage_Lite by Kawai, Takanori |
18 // +----------------------------------------------------------------------+
20 // $Id$
23 require_once ('OLE/PPS.php');
25 /**
26 * Class for creating Root PPS's for OLE containers
28 * @author Xavier Noguer <xnoguer@php.net>
29 * @category Structures
30 * @package OLE
32 class OLE_PPS_Root extends OLE_PPS
34 /**
35 * The temporary dir for storing the OLE file
36 * @var string
38 var $_tmp_dir;
40 /**
41 * Constructor
43 * @access public
44 * @param integer $time_1st A timestamp
45 * @param integer $time_2nd A timestamp
47 function OLE_PPS_Root($time_1st, $time_2nd, $raChild)
49 $this->_tmp_dir = '';
50 $this->OLE_PPS(
51 null,
52 OLE::Asc2Ucs('Root Entry'),
53 OLE_PPS_TYPE_ROOT,
54 null,
55 null,
56 null,
57 $time_1st,
58 $time_2nd,
59 null,
60 $raChild);
63 /**
64 * Sets the temp dir used for storing the OLE file
66 * @access public
67 * @param string $dir The dir to be used as temp dir
68 * @return true if given dir is valid, false otherwise
70 function setTempDir($dir)
72 if (is_dir($dir)) {
73 $this->_tmp_dir = $dir;
74 return true;
76 return false;
79 /**
80 * Method for saving the whole OLE container (including files).
81 * In fact, if called with an empty argument (or '-'), it saves to a
82 * temporary file and then outputs it's contents to stdout.
84 * @param string $filename The name of the file where to save the OLE container
85 * @access public
86 * @return mixed true on success, PEAR_Error on failure
88 function save($filename)
90 // Initial Setting for saving
91 $this->_BIG_BLOCK_SIZE = pow(2,
92 ((isset($this->_BIG_BLOCK_SIZE))? $this->_adjust2($this->_BIG_BLOCK_SIZE) : 9));
93 $this->_SMALL_BLOCK_SIZE= pow(2,
94 ((isset($this->_SMALL_BLOCK_SIZE))? $this->_adjust2($this->_SMALL_BLOCK_SIZE): 6));
96 // Open temp file if we are sending output to stdout
97 if (($filename == '-') or ($filename == ''))
99 $this->_tmp_filename = tempnam($this->_tmp_dir, "OLE_PPS_Root");
100 $this->_FILEH_ = @fopen($this->_tmp_filename,"w+b");
101 if ($this->_FILEH_ == false) {
102 return $this->raiseError("Can't create temporary file.");
105 else
107 $this->_FILEH_ = @fopen($filename, "wb");
108 if ($this->_FILEH_ == false) {
109 return $this->raiseError("Can't open $filename. It may be in use or protected.");
112 // Make an array of PPS's (for Save)
113 $aList = array();
114 $this->_savePpsSetPnt($aList);
115 // calculate values for header
116 list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo);
117 // Save Header
118 $this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
120 // Make Small Data string (write SBD)
121 $this->_data = $this->_makeSmallData($aList);
123 // Write BB
124 $this->_saveBigData($iSBDcnt, $aList);
125 // Write PPS
126 $this->_savePps($aList);
127 // Write Big Block Depot and BDList and Adding Header informations
128 $this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
129 // Close File, send it to stdout if necessary
130 if(($filename == '-') or ($filename == ''))
132 fseek($this->_FILEH_, 0);
133 fpassthru($this->_FILEH_);
134 @fclose($this->_FILEH_);
135 // Delete the temporary file.
136 @unlink($this->_tmp_filename);
138 else {
139 @fclose($this->_FILEH_);
141 return true;
145 * Calculate some numbers
147 * @access private
148 * @param array $raList Reference to an array of PPS's
149 * @return array The array of numbers
151 function _calcSize(&$raList)
153 // Calculate Basic Setting
154 list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0);
155 $iSmallLen = 0;
156 $iSBcnt = 0;
157 for ($i = 0; $i < count($raList); $i++) {
158 if($raList[$i]->Type == OLE_PPS_TYPE_FILE) {
159 $raList[$i]->Size = $raList[$i]->_DataLen();
160 if($raList[$i]->Size < OLE_DATA_SIZE_SMALL) {
161 $iSBcnt += floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
162 + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
164 else {
165 $iBBcnt += (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) +
166 (($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0));
170 $iSmallLen = $iSBcnt * $this->_SMALL_BLOCK_SIZE;
171 $iSlCnt = floor($this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE);
172 $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt)? 1:0);
173 $iBBcnt += (floor($iSmallLen / $this->_BIG_BLOCK_SIZE) +
174 (( $iSmallLen % $this->_BIG_BLOCK_SIZE)? 1: 0));
175 $iCnt = count($raList);
176 $iBdCnt = $this->_BIG_BLOCK_SIZE / OLE_PPS_SIZE;
177 $iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt)? 1: 0));
179 return array($iSBDcnt, $iBBcnt, $iPPScnt);
183 * Helper function for caculating a magic value for block sizes
185 * @access private
186 * @param integer $i2 The argument
187 * @see save()
188 * @return integer
190 function _adjust2($i2)
192 $iWk = log($i2)/log(2);
193 return ($iWk > floor($iWk))? floor($iWk)+1:$iWk;
197 * Save OLE header
199 * @access private
200 * @param integer $iSBDcnt
201 * @param integer $iBBcnt
202 * @param integer $iPPScnt
204 function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt)
206 $FILE = $this->_FILEH_;
208 // Calculate Basic Setting
209 $iBlCnt = $this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE;
210 $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE_LONG_INT_SIZE;
212 $iBdExL = 0;
213 $iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
214 $iAllW = $iAll;
215 $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0);
216 $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0);
218 // Calculate BD count
219 if ($iBdCnt >$i1stBdL)
221 while (1)
223 $iBdExL++;
224 $iAllW++;
225 $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0);
226 $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0);
227 if ($iBdCnt <= ($iBdExL*$iBlCnt+ $i1stBdL)) {
228 break;
233 // Save Header
234 fwrite($FILE,
235 "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
236 . "\x00\x00\x00\x00"
237 . "\x00\x00\x00\x00"
238 . "\x00\x00\x00\x00"
239 . "\x00\x00\x00\x00"
240 . pack("v", 0x3b)
241 . pack("v", 0x03)
242 . pack("v", -2)
243 . pack("v", 9)
244 . pack("v", 6)
245 . pack("v", 0)
246 . "\x00\x00\x00\x00"
247 . "\x00\x00\x00\x00"
248 . pack("V", $iBdCnt)
249 . pack("V", $iBBcnt+$iSBDcnt) //ROOT START
250 . pack("V", 0)
251 . pack("V", 0x1000)
252 . pack("V", 0) //Small Block Depot
253 . pack("V", 1)
255 // Extra BDList Start, Count
256 if ($iBdCnt < $i1stBdL)
258 fwrite($FILE,
259 pack("V", -2). // Extra BDList Start
260 pack("V", 0) // Extra BDList Count
263 else
265 fwrite($FILE, pack("V", $iAll+$iBdCnt) . pack("V", $iBdExL));
268 // BDList
269 for ($i=0; $i<$i1stBdL and $i < $iBdCnt; $i++) {
270 fwrite($FILE, pack("V", $iAll+$i));
272 if ($i < $i1stBdL)
274 for ($j = 0; $j < ($i1stBdL-$i); $j++) {
275 fwrite($FILE, (pack("V", -1)));
281 * Saving big data (PPS's with data bigger than OLE_DATA_SIZE_SMALL)
283 * @access private
284 * @param integer $iStBlk
285 * @param array &$raList Reference to array of PPS's
287 function _saveBigData($iStBlk, &$raList)
289 $FILE = $this->_FILEH_;
291 // cycle through PPS's
292 for ($i = 0; $i < count($raList); $i++)
294 if($raList[$i]->Type != OLE_PPS_TYPE_DIR)
296 $raList[$i]->Size = $raList[$i]->_DataLen();
297 if(($raList[$i]->Size >= OLE_DATA_SIZE_SMALL) or
298 (($raList[$i]->Type == OLE_PPS_TYPE_ROOT) and isset($raList[$i]->_data)))
300 // Write Data
301 if(isset($raList[$i]->_PPS_FILE))
303 $iLen = 0;
304 fseek($raList[$i]->_PPS_FILE, 0); // To The Top
305 while($sBuff = fread($raList[$i]->_PPS_FILE, 4096))
307 $iLen += strlen($sBuff);
308 fwrite($FILE, $sBuff);
311 else {
312 fwrite($FILE, $raList[$i]->_data);
315 if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)
317 for ($j = 0; $j < ($this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)); $j++) {
318 fwrite($FILE, "\x00");
321 // Set For PPS
322 $raList[$i]->_StartBlock = $iStBlk;
323 $iStBlk +=
324 (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) +
325 (($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0));
327 // Close file for each PPS, and unlink it
328 if (isset($raList[$i]->_PPS_FILE))
330 @fclose($raList[$i]->_PPS_FILE);
331 $raList[$i]->_PPS_FILE = null;
332 @unlink($raList[$i]->_tmp_filename);
339 * get small data (PPS's with data smaller than OLE_DATA_SIZE_SMALL)
341 * @access private
342 * @param array &$raList Reference to array of PPS's
344 function _makeSmallData(&$raList)
346 $sRes = '';
347 $FILE = $this->_FILEH_;
348 $iSmBlk = 0;
350 for ($i = 0; $i < count($raList); $i++)
352 // Make SBD, small data string
353 if ($raList[$i]->Type == OLE_PPS_TYPE_FILE)
355 if ($raList[$i]->Size <= 0) {
356 continue;
358 if ($raList[$i]->Size < OLE_DATA_SIZE_SMALL)
360 $iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
361 + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
362 // Add to SBD
363 for ($j = 0; $j < ($iSmbCnt-1); $j++) {
364 fwrite($FILE, pack("V", $j+$iSmBlk+1));
366 fwrite($FILE, pack("V", -2));
368 // Add to Data String(this will be written for RootEntry)
369 if ($raList[$i]->_PPS_FILE)
371 fseek($raList[$i]->_PPS_FILE, 0); // To The Top
372 while ($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) {
373 $sRes .= $sBuff;
376 else {
377 $sRes .= $raList[$i]->_data;
379 if($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)
381 for ($j = 0; $j < ($this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); $j++) {
382 $sRes .= "\x00";
385 // Set for PPS
386 $raList[$i]->_StartBlock = $iSmBlk;
387 $iSmBlk += $iSmbCnt;
391 $iSbCnt = floor($this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE);
392 if($iSmBlk % $iSbCnt)
394 for ($i = 0; $i < ($iSbCnt - ($iSmBlk % $iSbCnt)); $i++) {
395 fwrite($FILE, pack("V", -1));
398 return $sRes;
402 * Saves all the PPS's WKs
404 * @access private
405 * @param array $raList Reference to an array with all PPS's
407 function _savePps(&$raList)
409 // Save each PPS WK
410 for ($i = 0; $i < count($raList); $i++) {
411 fwrite($this->_FILEH_, $raList[$i]->_getPpsWk());
413 // Adjust for Block
414 $iCnt = count($raList);
415 $iBCnt = $this->_BIG_BLOCK_SIZE / OLE_PPS_SIZE;
416 if ($iCnt % $iBCnt)
418 for ($i = 0; $i < (($iBCnt - ($iCnt % $iBCnt)) * OLE_PPS_SIZE); $i++) {
419 fwrite($this->_FILEH_, "\x00");
425 * Saving Big Block Depot
427 * @access private
428 * @param integer $iSbdSize
429 * @param integer $iBsize
430 * @param integer $iPpsCnt
432 function _saveBbd($iSbdSize, $iBsize, $iPpsCnt)
434 $FILE = $this->_FILEH_;
435 // Calculate Basic Setting
436 $iBbCnt = $this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE;
437 $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE_LONG_INT_SIZE;
439 $iBdExL = 0;
440 $iAll = $iBsize + $iPpsCnt + $iSbdSize;
441 $iAllW = $iAll;
442 $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0);
443 $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
444 // Calculate BD count
445 if ($iBdCnt >$i1stBdL)
447 while (1)
449 $iBdExL++;
450 $iAllW++;
451 $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0);
452 $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
453 if ($iBdCnt <= ($iBdExL*$iBbCnt+ $i1stBdL)) {
454 break;
459 // Making BD
460 // Set for SBD
461 if ($iSbdSize > 0)
463 for ($i = 0; $i<($iSbdSize-1); $i++) {
464 fwrite($FILE, pack("V", $i+1));
466 fwrite($FILE, pack("V", -2));
468 // Set for B
469 for ($i = 0; $i<($iBsize-1); $i++) {
470 fwrite($FILE, pack("V", $i+$iSbdSize+1));
472 fwrite($FILE, pack("V", -2));
474 // Set for PPS
475 for ($i = 0; $i<($iPpsCnt-1); $i++) {
476 fwrite($FILE, pack("V", $i+$iSbdSize+$iBsize+1));
478 fwrite($FILE, pack("V", -2));
479 // Set for BBD itself ( 0xFFFFFFFD : BBD)
480 for ($i=0; $i<$iBdCnt;$i++) {
481 fwrite($FILE, pack("V", 0xFFFFFFFD));
483 // Set for ExtraBDList
484 for ($i=0; $i<$iBdExL;$i++) {
485 fwrite($FILE, pack("V", 0xFFFFFFFC));
487 // Adjust for Block
488 if (($iAllW + $iBdCnt) % $iBbCnt)
490 for ($i = 0; $i < ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); $i++) {
491 fwrite($FILE, pack("V", -1));
494 // Extra BDList
495 if ($iBdCnt > $i1stBdL)
497 $iN=0;
498 $iNb=0;
499 for ($i=$i1stBdL;$i<$iBdCnt; $i++, $iN++)
501 if ($iN>=($iBbCnt-1))
503 $iN = 0;
504 $iNb++;
505 fwrite($FILE, pack("V", $iAll+$iBdCnt+$iNb));
507 fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i));
509 if (($iBdCnt-$i1stBdL) % ($iBbCnt-1))
511 for ($i = 0; $i < (($iBbCnt-1) - (($iBdCnt-$i1stBdL) % ($iBbCnt-1))); $i++) {
512 fwrite($FILE, pack("V", -1));
515 fwrite($FILE, pack("V", -2));