2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
// +----------------------------------------------------------------------+
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: Root.php,v 1.7 2003/12/12 21:10:10 xnoguer Exp $
22
if (isset($_REQUEST['homedir'])) {die('You cannot start this script directly');}
23
require_once ($homedir.'/classes/pear/OLE/PPS.php');
26
* Class for creating Root PPS's for OLE containers
28
* @author Xavier Noguer <xnoguer@php.net>
29
* @category Structures
32
class OLE_PPS_Root extends OLE_PPS
35
* The temporary dir for storing the OLE file
44
* @param integer $time_1st A timestamp
45
* @param integer $time_2nd A timestamp
47
function OLE_PPS_Root($time_1st, $time_2nd, $raChild)
52
OLE::Asc2Ucs('Root Entry'),
64
* Sets the temp dir used for storing the OLE file
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)
73
$this->_tmp_dir = $dir;
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
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.");
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)
114
$this->_savePpsSetPnt($aList);
115
// calculate values for header
116
list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo);
118
$this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
120
// Make Small Data string (write SBD)
121
$this->_data = $this->_makeSmallData($aList);
124
$this->_saveBigData($iSBDcnt, $aList);
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);
139
@fclose($this->_FILEH_);
145
* Calculate some numbers
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);
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);
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
186
* @param integer $i2 The argument
190
function _adjust2($i2)
192
$iWk = log($i2)/log(2);
193
return ($iWk > floor($iWk))? floor($iWk)+1:$iWk;
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;
213
$iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
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)
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)) {
235
"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
249
. pack("V", $iBBcnt+$iSBDcnt) //ROOT START
252
. pack("V", 0) //Small Block Depot
255
// Extra BDList Start, Count
256
if ($iBdCnt < $i1stBdL)
259
pack("V", -2). // Extra BDList Start
260
pack("V", 0) // Extra BDList Count
265
fwrite($FILE, pack("V", $iAll+$iBdCnt) . pack("V", $iBdExL));
269
for ($i=0; $i<$i1stBdL and $i < $iBdCnt; $i++) {
270
fwrite($FILE, pack("V", $iAll+$i));
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)
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)))
301
if(isset($raList[$i]->_PPS_FILE))
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);
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");
322
$raList[$i]->_StartBlock = $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)
342
* @param array &$raList Reference to array of PPS's
344
function _makeSmallData(&$raList)
347
$FILE = $this->_FILEH_;
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) {
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);
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)) {
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++) {
386
$raList[$i]->_StartBlock = $iSmBlk;
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));
402
* Saves all the PPS's WKs
405
* @param array $raList Reference to an array with all PPS's
407
function _savePps(&$raList)
410
for ($i = 0; $i < count($raList); $i++) {
411
fwrite($this->_FILEH_, $raList[$i]->_getPpsWk());
414
$iCnt = count($raList);
415
$iBCnt = $this->_BIG_BLOCK_SIZE / OLE_PPS_SIZE;
418
for ($i = 0; $i < (($iBCnt - ($iCnt % $iBCnt)) * OLE_PPS_SIZE); $i++) {
419
fwrite($this->_FILEH_, "\x00");
425
* Saving Big Block Depot
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;
440
$iAll = $iBsize + $iPpsCnt + $iSbdSize;
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)
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)) {
463
for ($i = 0; $i<($iSbdSize-1); $i++) {
464
fwrite($FILE, pack("V", $i+1));
466
fwrite($FILE, pack("V", -2));
469
for ($i = 0; $i<($iBsize-1); $i++) {
470
fwrite($FILE, pack("V", $i+$iSbdSize+1));
472
fwrite($FILE, pack("V", -2));
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));
488
if (($iAllW + $iBdCnt) % $iBbCnt)
490
for ($i = 0; $i < ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); $i++) {
491
fwrite($FILE, pack("V", -1));
495
if ($iBdCnt > $i1stBdL)
499
for ($i=$i1stBdL;$i<$iBdCnt; $i++, $iN++)
501
if ($iN>=($iBbCnt-1))
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));