+class ole_pps_root extends ole_pps
+{
+ function __construct($raTime1st=false, $raTime2nd=false, $raChild=false)
+ {
+ $this->No = false;
+ $this->Name = Asc2Ucs('Root Entry');
+ $this->Type = PpsType_Root;
+ $this->PrevPps = false;
+ $this->NextPps = false;
+ $this->DirPps = false;
+ $this->Time1st = $raTime1st;
+ $this->Time2nd = $raTime2nd;
+ $this->StartBlock = false;
+ $this->Size = false;
+ $this->Data = false;
+ $this->Child = $raChild;
+ }
+
+ #------------------------------------------------------------------------------
+ # save (OLE::Storage_Lite::PPS::Root)
+ #------------------------------------------------------------------------------
+ function save($sFile, $bNoAs=false, $rhInfo=false)
+ {
+ #0.Initial Setting for saving
+
+ if (!$rhInfo)
+ $rhInfo=new stdClass();
+
+ $rhInfo->_BIG_BLOCK_SIZE = $rhInfo->_SMALL_BLOCK_SIZE = 0;
+ $rhInfo->_BIG_BLOCK_SIZE=pow(2, (($rhInfo->_BIG_BLOCK_SIZE) ?
+ _adjust2($rhInfo->_BIG_BLOCK_SIZE) : 9));
+ $rhInfo->_SMALL_BLOCK_SIZE=pow(2, (($rhInfo->_SMALL_BLOCK_SIZE) ?
+ _adjust2($rhInfo->_SMALL_BLOCK_SIZE) : 6));
+ $rhInfo->_SMALL_SIZE = 0x1000;
+ $rhInfo->_PPS_SIZE = 0x80;
+
+ #1.Open File
+ #1.1 $sFile is Ref of scalar
+ if(is_resource($sFile))
+ {
+ $oIo=$sFile;
+ $rhInfo->_FILEH_ = $oIo;
+ }
+ #1.2 $sFile is a simple filename string
+ else
+ {
+ $oIo=fopen("$sFile", "wb");
+ $rhInfo->_FILEH_ = $oIo;
+ }
+
+ $iBlk = 0;
+ #1. Make an array of PPS (for Save)
+ $aList=array();
+ $list=array(&$this);
+ if($bNoAs)
+ $this->_savePpsSetPnt2($list, $aList, $rhInfo);
+ else
+ $this->_savePpsSetPnt($list, $aList, $rhInfo);
+ list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList, $rhInfo);
+ #2.Save Header
+ $this->_saveHeader($rhInfo, $iSBDcnt, $iBBcnt, $iPPScnt);
+
+ #3.Make Small Data string (write SBD)
+ $sSmWk = $this->_makeSmallData($aList, $rhInfo);
+ $this->Data = $sSmWk; #Small Datas become RootEntry Data
+
+ #4. Write BB
+ $iBBlk = $iSBDcnt;
+ $this->_saveBigData($iBBlk, $aList, $rhInfo);
+ #5. Write PPS
+ $this->_savePps($aList, $rhInfo);
+ #6. Write BD and BDList and Adding Header informations
+ $this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt, $rhInfo);
+ #7.Close File
+ fclose($rhInfo->_FILEH_);
+ }
+
+ #------------------------------------------------------------------------------
+ # _calcSize (OLE::Storage_Lite::PPS)
+ #------------------------------------------------------------------------------
+ function _calcSize(&$raList, $rhInfo)
+ {
+ #0. Calculate Basic Setting
+ $iSBDcnt=0;
+ $iBBcnt=0;
+ $iPPScnt = 0;
+ $iSmallLen = 0;
+ $iSBcnt = 0;
+
+ for ($c=0;$c<sizeof($raList);$c++)
+ {
+ $oPps=&$raList[$c];
+
+ if($oPps->Type==PpsType_File)
+ {
+ $oPps->Size = $oPps->_DataLen(); #Mod
+ if($oPps->Size < $rhInfo->_SMALL_SIZE)
+ {
+ $iSBcnt += floor($oPps->Size / $rhInfo->_SMALL_BLOCK_SIZE) +
+ (($oPps->Size % $rhInfo->_SMALL_BLOCK_SIZE) ? 1 : 0);
+ }
+ else
+ {
+ $iBBcnt +=
+ (floor($oPps->Size/ $rhInfo->_BIG_BLOCK_SIZE) +
+ (($oPps->Size % $rhInfo->_BIG_BLOCK_SIZE)? 1: 0));
+ }
+ }
+ }
+ $iSmallLen = $iSBcnt * $rhInfo->_SMALL_BLOCK_SIZE;
+ $iSlCnt = floor($rhInfo->_BIG_BLOCK_SIZE / LongIntSize);
+ $iSBDcnt = floor($iSBcnt / $iSlCnt)+ (($iSBcnt % $iSlCnt) ? 1 : 0);
+ $iBBcnt += (floor($iSmallLen/ $rhInfo->_BIG_BLOCK_SIZE) +
+ (( $iSmallLen% $rhInfo->_BIG_BLOCK_SIZE) ? 1 : 0));
+ $iCnt = sizeof($raList);
+ $iBdCnt = $rhInfo->_BIG_BLOCK_SIZE/PpsSize;
+ $iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt) ? 1 : 0));
+
+ return array($iSBDcnt, $iBBcnt, $iPPScnt);
+ }
+
+ #------------------------------------------------------------------------------
+ # _adjust2 (OLE::Storage_Lite::PPS::Root)
+ #------------------------------------------------------------------------------
+ function _adjust2($i2)
+ {
+ $iWk = log($i2)/log(2);
+ return ($iWk > int($iWk)) ? floor($iWk)+1 : $iWk;
+ }
+
+ #------------------------------------------------------------------------------
+ # _saveHeader (OLE::Storage_Lite::PPS::Root)
+ #------------------------------------------------------------------------------
+ function _saveHeader($rhInfo, $iSBDcnt, $iBBcnt, $iPPScnt)
+ {
+ $FILE = $rhInfo->_FILEH_;
+
+ #0. Calculate Basic Setting
+ $iBlCnt = $rhInfo->_BIG_BLOCK_SIZE / LongIntSize;
+ $i1stBdL = ($rhInfo->_BIG_BLOCK_SIZE - 0x4C) / LongIntSize;
+
+ $iBdExL = 0;
+ $iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
+ $iAllW = $iAll;
+ $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
+ $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt) ? 1 : 0);
+ //my $i;
+
+ #0.1 Calculate BD count
+ if ($iBdCnt > $i1stBdL)
+ {
+ // TODO: is do-while correct here?
+ do
+ {
+ $iBdExL++;
+ $iAllW++;
+ $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
+ $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt) ? 1 : 0);
+ }
+ while($iBdCnt > ($iBdExL*$iBlCnt+ $i1stBdL));
+ }
+
+ #1.Save Header
+ fputs($FILE,
+ "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1".
+ "\x00\x00\x00\x00".
+ "\x00\x00\x00\x00".
+ "\x00\x00\x00\x00".
+ "\x00\x00\x00\x00".
+ pack("v", 0x3b).
+ pack("v", 0x03).
+ pack("v", -2).
+ pack("v", 9).
+ pack("v", 6).
+ pack("v", 0).
+ "\x00\x00\x00\x00".
+ "\x00\x00\x00\x00".
+ pack("V", $iBdCnt).
+ pack("V", $iBBcnt+$iSBDcnt). #ROOT START
+ pack("V", 0).
+ pack("V", 0x1000).
+ pack("V", 0). #Small Block Depot
+ pack("V", 1)
+ );
+ #2. Extra BDList Start, Count
+ if($iBdCnt < $i1stBdL)
+ {
+ fputs($FILE,
+ pack("V", -2). #Extra BDList Start
+ pack("V", 0) #Extra BDList Count
+ );
+ }
+ else
+ {
+ fputs($FILE,
+ pack("V", $iAll+$iBdCnt).
+ pack("V", $iBdExL)
+ );
+ }
+
+ #3. BDList
+ for ($i=0;($i<$i1stBdL) && ($i < $iBdCnt); $i++)
+ fputs($FILE, pack("V", $iAll+$i));
+ if ($i<$i1stBdL)
+ {
+ // TODO: Check, if str_repeat is binary safe
+ fputs($FILE, str_repeat((pack("V", -1)), ($i1stBdL-$i)));
+ }
+ }
+
+ #------------------------------------------------------------------------------
+ # _saveBigData (OLE::Storage_Lite::PPS)
+ #------------------------------------------------------------------------------
+ function _saveBigData(&$iStBlk, &$raList, $rhInfo)
+ {
+
+ //return;//!!!
+
+ $iRes = 0;
+ $FILE = $rhInfo->_FILEH_;
+
+ #1.Write Big (ge 0x1000) Data into Block
+ for ($c=0;$c<sizeof($raList);$c++)
+ {
+ $oPps=&$raList[$c];
+ if($oPps->Type!=PpsType_Dir)
+ {
+ #print "PPS: $oPps DEF:", defined($oPps->{Data}), "\n";
+ $oPps->Size = $oPps->_DataLen(); #Mod
+ if(($oPps->Size >= $rhInfo->_SMALL_SIZE) ||
+ (($oPps->Type == PpsType_Root) && $oPps->Data!==false))
+ {
+ #1.1 Write Data
+ #Check for update
+ if($oPps->_PPS_FILE)
+ {
+ //my $sBuff;
+ $iLen = 0;
+ fseek($oPps->_PPS_FILE, 0, SEEK_SET); #To The Top
+ while ($sBuff=fread($oPps->_PPS_FILE, 4096))
+ {
+ $iLen += length($sBuff);
+ fputs($FILE, $sBuff); #Check for update
+ }
+ }
+ else
+ fputs($FILE, $oPps->Data);
+ if ($oPps->Size % $rhInfo->_BIG_BLOCK_SIZE)
+ {
+ // TODO: Check, if str_repeat() is binary safe
+ fputs($FILE, str_repeat("\x00",
+ ($rhInfo->_BIG_BLOCK_SIZE -
+ ($oPps->Size % $rhInfo->_BIG_BLOCK_SIZE)))
+ );
+ }
+ #1.2 Set For PPS
+ $oPps->StartBlock = $iStBlk;
+ $iStBlk +=
+ (floor($oPps->Size/ $rhInfo->_BIG_BLOCK_SIZE) +
+ (($oPps->Size % $rhInfo->_BIG_BLOCK_SIZE) ? 1 : 0));
+ }
+ }
+ }
+ }
+
+ #------------------------------------------------------------------------------
+ # _savePps (OLE::Storage_Lite::PPS::Root)
+ #------------------------------------------------------------------------------
+ function _savePps(&$raList, $rhInfo)
+ {
+ #0. Initial
+ $FILE = $rhInfo->_FILEH_;
+ #2. Save PPS
+ for ($c=0;$c<sizeof($raList);$c++)
+ {
+ $oItem=&$raList[$c];
+ $oItem->_savePpsWk($rhInfo);
+ }
+ #3. Adjust for Block
+ $iCnt = sizeof($raList);
+ $iBCnt = $rhInfo->_BIG_BLOCK_SIZE / $rhInfo->_PPS_SIZE;
+ if($iCnt % $iBCnt)
+ fputs($FILE, str_repeat("\x00", (($iBCnt - ($iCnt % $iBCnt)) * $rhInfo->_PPS_SIZE)));
+ return (floor($iCnt / $iBCnt) + (($iCnt % $iBCnt) ? 1 : 0));
+ }
+
+ #------------------------------------------------------------------------------
+ # _savePpsSetPnt2 (OLE::Storage_Lite::PPS::Root)
+ # For Test
+ #------------------------------------------------------------------------------
+ function _savePpsSetPnt2(&$aThis, &$raList, $rhInfo)
+ {
+ #1. make Array as Children-Relations
+ #1.1 if No Children
+ if (!is_array($aThis) || sizeof($aThis)==0)
+ return 0xFFFFFFFF;
+ elseif (sizeof($aThis)==1)
+ {
+ #1.2 Just Only one
+ array_push($raList, $aThis[0]);
+ $aThis[0]->No = sizeof($raList)-1;
+ $aThis[0]->PrevPps = 0xFFFFFFFF;
+ $aThis[0]->NextPps = 0xFFFFFFFF;
+ $aThis[0]->DirPps = $this->_savePpsSetPnt2($aThis[0]->Child, $raList, $rhInfo);
+ return $aThis[0]->No;
+ }
+ else
+ {
+ #1.3 Array
+ $iCnt = sizeof($aThis);
+ #1.3.1 Define Center
+ $iPos = 0; #int($iCnt/ 2); #$iCnt
+
+ $aWk = $aThis;
+ $aPrev = (sizeof($aThis) > 2) ? array_splice($aWk, 1, 1) : array(); #$iPos);
+ $aNext = array_splice($aWk, 1); #, $iCnt - $iPos -1);
+ $aThis[$iPos]->PrevPps = $this->_savePpsSetPnt2($aPrev, $raList, $rhInfo);
+ array_push($raList, $aThis[$iPos]);
+ $aThis[$iPos]->No = sizeof($raList)-1;
+
+ #1.3.2 Devide a array into Previous,Next
+ $aThis[$iPos]->NextPps = $this->_savePpsSetPnt2($aNext, $raList, $rhInfo);
+ $aThis[$iPos]->DirPps = $this->_savePpsSetPnt2($aThis[$iPos]->Child, $raList, $rhInfo);
+ return $aThis[$iPos]->No;
+ }
+ }
+
+ #------------------------------------------------------------------------------
+ # _savePpsSetPnt2 (OLE::Storage_Lite::PPS::Root)
+ # For Test
+ #------------------------------------------------------------------------------
+ function _savePpsSetPnt2s(&$aThis, &$raList, $rhInfo)
+ {
+ #1. make Array as Children-Relations
+ #1.1 if No Children
+ if (!is_array($aThis) || sizeof($aThis)==0)
+ return 0xFFFFFFFF;
+ elseif (sizeof($aThis)==1)
+ {
+ #1.2 Just Only one
+ array_push($raList, $aThis[0]);
+ $aThis[0]->No = sizeof($raList)-1;
+ $aThis[0]->PrevPps = 0xFFFFFFFF;
+ $aThis[0]->NextPps = 0xFFFFFFFF;
+ $aThis[0]->DirPps = $this->_savePpsSetPnt2($aThis[0]->Child, $raList, $rhInfo);
+ return $aThis[0]->No;
+ }
+ else
+ {
+ #1.3 Array
+ $iCnt = sizeof($aThis);
+ #1.3.1 Define Center
+ $iPos = 0; #int($iCnt/ 2); #$iCnt
+ array_push($raList, $aThis[$iPos]);
+ $aThis[$iPos]->No = sizeof($raList)-1;
+ $aWk = $aThis;
+ #1.3.2 Devide a array into Previous,Next
+ $aPrev = array_splice($aWk, 0, $iPos);
+ $aNext = array_splice($aWk, 1, $iCnt - $iPos - 1);
+ $aThis[$iPos]->PrevPps = $this->_savePpsSetPnt2($aPrev, $raList, $rhInfo);
+ $aThis[$iPos]->NextPps = $this->_savePpsSetPnt2($aNext, $raList, $rhInfo);
+ $aThis[$iPos]->DirPps = $this->_savePpsSetPnt2($aThis[$iPos]->Child, $raList, $rhInfo);
+ return $aThis[$iPos]->No;
+ }
+ }
+
+ #------------------------------------------------------------------------------
+ # _savePpsSetPnt (OLE::Storage_Lite::PPS::Root)
+ #------------------------------------------------------------------------------
+ function _savePpsSetPnt(&$aThis, &$raList, $rhInfo)
+ {
+
+ //print "yyy type: ".gettype($aThis)."<br>\n";
+ //print "yyy name: ".$aThis[0]->Name."<br>\n";
+
+ #1. make Array as Children-Relations
+ #1.1 if No Children
+ if (!is_array($aThis) || sizeof($aThis)==0)
+ {
+ return 0xFFFFFFFF;
+ }
+ elseif (sizeof($aThis)==1)
+ {
+ #1.2 Just Only one
+ array_push($raList, $aThis[0]);
+ $aThis[0]->No = sizeof($raList)-1;
+ $aThis[0]->PrevPps = 0xFFFFFFFF;
+ $aThis[0]->NextPps = 0xFFFFFFFF;
+ $aThis[0]->DirPps = $this->_savePpsSetPnt($aThis[0]->Child, $raList, $rhInfo);
+ return $aThis[0]->No;
+ }
+ else
+ {
+ #1.3 Array
+ $iCnt = sizeof($aThis);
+ #1.3.1 Define Center
+ $iPos = floor($iCnt/2); #$iCnt
+ array_push($raList, $aThis[$iPos]);
+ $aThis[$iPos]->No = sizeof($raList)-1;
+ $aWk = $aThis;
+ #1.3.2 Devide a array into Previous,Next
+ $aPrev = splice($aWk, 0, $iPos);
+ $aNext = splice($aWk, 1, $iCnt - $iPos - 1);
+ $aThis[$iPos]->PrevPps = $this->_savePpsSetPnt($aPrev, $raList, $rhInfo);
+ $aThis[$iPos]->NextPps = $this->_savePpsSetPnt($aNext, $raList, $rhInfo);
+ $aThis[$iPos]->DirPps = $this->_savePpsSetPnt($aThis[$iPos]->Child, $raList, $rhInfo);
+ return $aThis[$iPos]->No;
+ }
+ }
+
+ #------------------------------------------------------------------------------
+ # _savePpsSetPnt (OLE::Storage_Lite::PPS::Root)
+ #------------------------------------------------------------------------------
+ function _savePpsSetPnt1(&$aThis, &$raList, $rhInfo)
+ {
+ #1. make Array as Children-Relations
+ #1.1 if No Children
+ if (!is_array($aThis) || sizeof($aThis)==0)
+ {
+ return 0xFFFFFFFF;
+ }
+ elseif (sizeof($aThis)==1)
+ {
+ #1.2 Just Only one
+ array_push($raList, $aThis[0]);
+ $aThis[0]->No = sizeof($raList)-1;
+ $aThis[0]->PrevPps = 0xFFFFFFFF;
+ $aThis[0]->NextPps = 0xFFFFFFFF;
+ $aThis[0]->DirPps = $this->_savePpsSetPnt($aThis[0]->Child, $raList, $rhInfo);
+ return $aThis[0]->No;
+ }
+ else
+ {
+ #1.3 Array
+ $iCnt = sizeof($aThis);
+ #1.3.1 Define Center
+ $iPos = floor($iCnt / 2); #$iCnt
+ array_push($raList, $aThis[$iPos]);
+ $aThis[$iPos]->No = sizeof($raList)-1;
+ $aWk = $aThis;
+ #1.3.2 Devide a array into Previous,Next
+ $aPrev = splice($aWk, 0, $iPos);
+ $aNext = splice($aWk, 1, $iCnt - $iPos - 1);
+ $aThis[$iPos]->PrevPps = $this->_savePpsSetPnt($aPrev, $raList, $rhInfo);
+ $aThis[$iPos]->NextPps = $this->_savePpsSetPnt($aNext, $raList, $rhInfo);
+ $aThis[$iPos]->DirPps = $this->_savePpsSetPnt($aThis[$iPos]->Child, $raList, $rhInfo);
+ return $aThis[$iPos]->No;
+ }
+ }
+
+ #------------------------------------------------------------------------------
+ # _saveBbd (OLE::Storage_Lite)
+ #------------------------------------------------------------------------------
+ function _saveBbd($iSbdSize, $iBsize, $iPpsCnt, $rhInfo)
+ {
+ $FILE = $rhInfo->_FILEH_;
+ #0. Calculate Basic Setting
+ $iBbCnt = $rhInfo->_BIG_BLOCK_SIZE / LongIntSize;
+ $i1stBdL = ($rhInfo->_BIG_BLOCK_SIZE - 0x4C) / LongIntSize;
+
+ $iBdExL = 0;
+ $iAll = $iBsize + $iPpsCnt + $iSbdSize;
+ $iAllW = $iAll;
+ $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
+ $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
+ //my $i;
+ #0.1 Calculate BD count
+ if ($iBdCnt >$i1stBdL)
+ {
+ // TODO: do-while correct here?
+ do
+ {
+ $iBdExL++;
+ $iAllW++;
+ $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
+ $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt) ? 1 : 0);
+ }
+ while ($iBdCnt > ($iBdExL*$iBbCnt+$i1stBdL));
+ }
+
+ #1. Making BD
+ #1.1 Set for SBD
+ if($iSbdSize > 0)
+ {
+ for ($i = 0; $i<($iSbdSize-1); $i++)
+ fputs($FILE, pack("V", $i+1));
+ fputs($FILE, pack("V", -2));
+ }
+ #1.2 Set for B
+ for ($i = 0; $i<($iBsize-1); $i++)
+ fputs($FILE, pack("V", $i+$iSbdSize+1));
+ fputs($FILE, pack("V", -2));
+
+ #1.3 Set for PPS
+ for ($i = 0; $i<($iPpsCnt-1); $i++)
+ fputs($FILE, pack("V", $i+$iSbdSize+$iBsize+1));
+ fputs($FILE, pack("V", -2));
+ #1.4 Set for BBD itself ( 0xFFFFFFFD : BBD)
+ for ($i=0; $i<$iBdCnt;$i++)
+ fputs($FILE, pack("V", 0xFFFFFFFD));
+ #1.5 Set for ExtraBDList
+ for ($i=0; $i<$iBdExL;$i++)
+ fputs($FILE, pack("V", 0xFFFFFFFC));
+ #1.6 Adjust for Block
+ if(($iAllW + $iBdCnt) % $iBbCnt)
+ fputs($FILE, str_repeat(pack("V", -1), ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt))));
+
+ #2.Extra BDList
+ if($iBdCnt > $i1stBdL)
+ {
+ $iN=0;
+ $iNb=0;
+ for ($i=$i1stBdL;$i<$iBdCnt; $i++, $iN++)
+ {
+ if($iN>=($iBbCnt-1))
+ {
+ $iN = 0;
+ $iNb++;
+ fputs($FILE, pack("V", $iAll+$iBdCnt+$iNb));
+ }
+ fputs($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i));
+ }
+ if(($iBdCnt-$i1stBdL) % ($iBbCnt-1))
+ fputs($FILE, str_repeat(pack("V", -1), (($iBbCnt-1) - (($iBdCnt-$i1stBdL) % ($iBbCnt-1)))));
+ fputs($FILE, pack("V", -2));
+ }
+ }