sFile=$sFile; } #------------------------------------------------------------------------------ # getPpsTree: OLE::Storage_Lite #------------------------------------------------------------------------------ function getPpsTree($bData=false) { #0.Init $rhInfo = _initParse($this->_FILE); if (!$rhInfo) { return false; } #1. Get Data list($oPps) = _getPpsTree(0, $rhInfo, $bData); // close(IN); return $oPps; } #------------------------------------------------------------------------------ # getSearch: OLE::Storage_Lite #------------------------------------------------------------------------------ function getPpsSearch($raName, $bData=false, $iCase=false) { #0.Init $rhInfo = _initParse($this->_FILE); if (!$rhInfo) { return false; } #1. Get Data $aList = _getPpsSearch(0, $rhInfo, $raName, $bData, $iCase); // close(IN); return $aList; } #------------------------------------------------------------------------------ # getNthPps: OLE::Storage_Lite #------------------------------------------------------------------------------ function getNthPps($iNo, $bData=false) { #0.Init $rhInfo = _initParse($this->_FILE); if (!$rhInfo) { return false; } #1. Get Data $oPps = _getNthPps($iNo, $rhInfo, $bData); // close IN; return $oPps; } #------------------------------------------------------------------------------ # _initParse: OLE::Storage_Lite #------------------------------------------------------------------------------ function _initParse($sFile) { //$oIo; #1. $sFile is a resource (hopefully a file resource) if (is_resource($sFile)) { $oIo=$sFile; } #2. $sFile is a filename string else { $oIo=fopen($sFile, "rb"); } return _getHeaderInfo($oIo); } #------------------------------------------------------------------------------ # _getPpsTree: OLE::Storage_Lite #------------------------------------------------------------------------------ function _getPpsTree($iNo, $rhInfo, $bData, &$raDone) { // last par optional! if($raDone!==false) { if(in_array($iNo, $raDone)) { return array(); } } else { $raDone=array(); } array_push($raDone, $iNo); $iRootBlock = $rhInfo->_ROOT_START; #1. Get Information about itself $oPps = _getNthPps($iNo, $rhInfo, $bData); #2. Child if($oPps->DirPps != 0xFFFFFFFF) { $aChildL = _getPpsTree($oPps->DirPps, $rhInfo, $bData, $raDone); $oPps->Child =& $aChildL; } else { $oPps->Child = false; } #3. Previous,Next PPSs $aList = array(); if ($oPps->PrevPps != 0xFFFFFFFF) { array_push($aList, _getPpsTree($oPps->PrevPps, $rhInfo, $bData, $raDone)); } array_push($aList, $oPps); if ($oPps->NextPps != 0xFFFFFFFF) { array_push($aList, _getPpsTree($oPps->NextPps, $rhInfo, $bData, $raDone)); } return $aList; } #------------------------------------------------------------------------------ # _getPpsSearch: OLE::Storage_Lite #------------------------------------------------------------------------------ function _getPpsSearch($iNo, $rhInfo, $raName, $bData, $iCase, &$raDone) { // last par optional! $iRootBlock = $rhInfo->_ROOT_START; //my @aRes; #1. Check it self if($raDone!==false) { if(in_array($iNo, $raDone)) { return array(); } } else { $raDone=array(); } array_push($raDone, $iNo); $oPps = _getNthPps($iNo, $rhInfo, false); $found=false; foreach ($raName as $cmp) { if (($iCase && strcasecmp($oPps->Name, $cmp)==0) || strcmp($oPps->Name, $cmp)==0) { $found=true; break; } } if ($found) { if ($bData) { $oPps = _getNthPps($iNo, $rhInfo, $bData); } $aRes = array($oPps); } else { $aRes = array(); } #2. Check Child, Previous, Next PPSs if ($oPps->DirPps != 0xFFFFFFFF) { array_push($aRes, _getPpsSearch($oPps->DirPps, $rhInfo, $raName, $bData, $iCase, $raDone)); } if ($oPps->PrevPps != 0xFFFFFFFF) { array_push($aRes, _getPpsSearch($oPps->PrevPps, $rhInfo, $raName, $bData, $iCase, $raDone)); } if ($oPps->NextPps != 0xFFFFFFFF) { array_push($aRes, _getPpsSearch($oPps->NextPps, $rhInfo, $raName, $bData, $iCase, $raDone)); } return $aRes; } #=================================================================== # Get Header Info (BASE Informain about that file) #=================================================================== function _getHeaderInfo($FILE) { //my($iWk); $rhInfo = new object(); $rhInfo->_FILEH_ = $FILE; //my $sWk; #0. Check ID fseek($rhInfo->_FILEH_, 0, SEEK_SET); $sWk=fread($rhInfo->_FILEH_, 8); if ($sWk!="\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1") { return false; } #BIG BLOCK SIZE $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x1E, 2, "v"); if ($iWk===false) { return false; } $rhInfo->_BIG_BLOCK_SIZE = pow(2, $iWk); #SMALL BLOCK SIZE $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x20, 2, "v"); if ($iWk===false) { return false; } $rhInfo->_SMALL_BLOCK_SIZE = pow(2, $iWk); #BDB Count $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x2C, 4, "V"); if ($iWk===false) { return false; } $rhInfo->_BDB_COUNT = $iWk; #START BLOCK $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x30, 4, "V"); if ($iWk===false) { return false; } $rhInfo->_ROOT_START = $iWk; #MIN SIZE OF BB # $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x38, 4, "V"); # if ($iWk===false) { # return false; # } # $rhInfo->_MIN_SIZE_BB = $iWk; #SMALL BD START $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x3C, 4, "V"); if ($iWk===false) { return false; } $rhInfo->_SBD_START = $iWk; #SMALL BD COUNT $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x40, 4, "V"); if ($iWk===false) { return false; } $rhInfo->_SBD_COUNT = $iWk; #EXTRA BBD START $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x44, 4, "V"); if ($iWk===false) { return false; } $rhInfo->_EXTRA_BBD_START = $iWk; #EXTRA BD COUNT $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x48, 4, "V"); if ($iWk===false) { return false; } $rhInfo->_EXTRA_BBD_COUNT = $iWk; #GET BBD INFO $rhInfo->_BBD_INFO= _getBbdInfo($rhInfo); #GET ROOT PPS $oRoot = _getNthPps(0, $rhInfo, false); $rhInfo->_SB_START = $oRoot->StartBlock; $rhInfo->_SB_SIZE = $oRoot->Size; return $rhInfo; } #------------------------------------------------------------------------------ # _getInfoFromFile #------------------------------------------------------------------------------ function _getInfoFromFile($FILE, $iPos, $iLen, $sFmt) { //my($sWk); if (!$FILE) { return false; } if (fseek($FILE, $iPos, SEEK_SET)!==0) { return false; } $sWk=fread($FILE, $iLen); $data=unpack($sFmt."ret", $sWk); return $data["ret"]; } #------------------------------------------------------------------------------ # _getBbdInfo #------------------------------------------------------------------------------ function _getBbdInfo($rhInfo) { $aBdList = array(); $iBdbCnt = $rhInfo->_BDB_COUNT; //my $iGetCnt; //my $sWk; $i1stCnt = floor(($rhInfo->_BIG_BLOCK_SIZE - 0x4C) / LongIntSize); $iBdlCnt = floor($rhInfo->_BIG_BLOCK_SIZE / LongIntSize) - 1; #1. 1st BDlist fseek ($rhInfo->_FILEH_, 0x4C, SEEK_SET); $iGetCnt = ($iBdbCnt < $i1stCnt) ? $iBdbCnt : $i1stCnt; $sWk=fread($rhInfo->_FILEH_, LongIntSize*$iGetCnt); $data=unpack("V".$iGetCnt."int", $sWk); for ($c=0;$c<$iGetCnt;$c++) { array_push ($aBdList, $data["int$c"]); } $iBdbCnt -= $iGetCnt; #2. Extra BDList $iBlock = $rhInfo->_EXTRA_BBD_START; while(($iBdbCnt> 0) && _isNormalBlock($iBlock)){ _setFilePos($iBlock, 0, $rhInfo); $iGetCnt= ($iBdbCnt < $iBdlCnt) ? $iBdbCnt : $iBdlCnt; $sWk=fread($rhInfo->_FILEH_, LongIntSize*$iGetCnt); $data=unpack("V".$iGetCnt."int", $sWk); for ($c=0;$c<$iGetCnt;$c++) { array_push ($aBdList, $data["int$c"]); } $iBdbCnt -= $iGetCnt; $sWk=fread($rhInfo->_FILEH_, LongIntSize); $data=unpack("Vint", $sWk); $iBlock = $data["int"]; } #3.Get BDs $aWk=array(); $hBd=array(); $iBlkNo = 0; //my $iBdL; //my $i; $iBdCnt = floor($rhInfo->_BIG_BLOCK_SIZE / LongIntSize); foreach ($aBdList as $iBdl) { // foreach $iBdL (@aBdList) { _setFilePos($iBdL, 0, $rhInfo); $sWk=fread($rhInfo->_FILEH_, $rhInfo->_BIG_BLOCK_SIZE); $aWk = unpack("V".$iBdCnt."int", $sWk); for ($i=0;$i<$iBdCnt;$i++, $iBlkNo++) { if($aWk["int".$i] != ($iBlkNo+1)) { $hBd["$iBlkNo"] = $aWk["int".$i]; } } } return $hBd; } #------------------------------------------------------------------------------ # getNthPps (OLE::Storage_Lite) #------------------------------------------------------------------------------ function _getNthPps($iPos, $rhInfo, $bData) { $iPpsStart = $rhInfo->_ROOT_START; //my($iPpsBlock, $iPpsPos); //my $sWk; //my $iBlock; $iBaseCnt = $rhInfo->_BIG_BLOCK_SIZE / PpsSize; $iPpsBlock = floor($iPos / $iBaseCnt); $iPpsPos = $iPos % $iBaseCnt; $iBlock = _getNthBlockNo($iPpsStart, $iPpsBlock, $rhInfo); if ($iBlock===false) { return false; } _setFilePos($iBlock, PpsSize*$iPpsPos, $rhInfo); $sWk=fread($rhInfo->_FILEH_, PpsSize); // return undef unless($sWk); //TODO: substr() binary safe? $data=unpack("vint", substr($sWk, 0x40, 2)); $iNmSize = $data["int"]; $iNmSize = ($iNmSize > 2) ? $iNmSize - 2 : $iNmSize; $sNm= substr($sWk, 0, $iNmSize); $data=unpack("Cint", substr($sWk, 0x42, 2)); $iType = $data["int"]; $data=unpack("V3int", substr($sWk, 0x44, LongIntSize*3)); $lPpsPrev = $data["int1"]; $lPpsNext = $data["int2"]; $lDirPps = $data["int3"]; // TODO: Original lines terminated by commas: ?! /* my @raTime1st = (($iType == PpsType_Root) or ($iType == PpsType_Dir))? OLEDate2Local(substr($sWk, 0x64, 8)) : undef , my @raTime2nd = (($iType == PpsType_Root) or ($iType == PpsType_Dir))? OLEDate2Local(substr($sWk, 0x6C, 8)) : undef, */ $raTime1st = (($iType == PpsType_Root) or ($iType == PpsType_Dir)) ? OLEDate2Local(substr($sWk, 0x64, 8)) : false; $raTime2nd = (($iType == PpsType_Root) or ($iType == PpsType_Dir)) ? OLEDate2Local(substr($sWk, 0x6C, 8)) : false; $data=unpack("V2int", substr($sWk, 0x74, 8)); $iStart=$data["int1"]; $iSize=$data["int2"]; if ($bData) { $sData = _getData($iType, $iStart, $iSize, $rhInfo); /* TODO!!! return OLE::Storage_Lite::PPS->new( $iPos, $sNm, $iType, $lPpsPrev, $lPpsNext, $lDirPps, \@raTime1st, \@raTime2nd, $iStart, $iSize, $sData, undef); */ } else { /* TODO!!! return OLE::Storage_Lite::PPS->new( $iPos, $sNm, $iType, $lPpsPrev, $lPpsNext, $lDirPps, \@raTime1st, \@raTime2nd, $iStart, $iSize, undef, undef); */ } } #------------------------------------------------------------------------------ # _setFilePos (OLE::Storage_Lite) #------------------------------------------------------------------------------ function _setFilePos($iBlock, $iPos, $rhInfo) { fseek($rhInfo->_FILEH_, ($iBlock+1)*$rhInfo->_BIG_BLOCK_SIZE+$iPos, SEEK_SET); } #------------------------------------------------------------------------------ # _getNthBlockNo (OLE::Storage_Lite) #------------------------------------------------------------------------------ function _getNthBlockNo($iStBlock, $iNth, $rhInfo) { //my $iSv; $iNext = $iStBlock; for ($i=0; $i<$iNth; $i++) { $iSv = $iNext; $iNext = _getNextBlockNo($iSv, $rhInfo); if (!_isNormalBlock($iNext)) { return; } } return $iNext; } #------------------------------------------------------------------------------ # _getData (OLE::Storage_Lite) #------------------------------------------------------------------------------ function _getData($iType, $iBlock, $iSize, $rhInfo) { if ($iType == PpsType_File) { if($iSize < DataSizeSmall) { return _getSmallData($iBlock, $iSize, $rhInfo); } else { return _getBigData($iBlock, $iSize, $rhInfo); } } elseif($iType == PpsType_Root) { #Root return _getBigData($iBlock, $iSize, $rhInfo); } elseif($iType == PpsType_Dir) { # Directory return false; } } #------------------------------------------------------------------------------ # _getBigData (OLE::Storage_Lite) #------------------------------------------------------------------------------ function _getBigData($iBlock, $iSize, $rhInfo) { //my($iRest, $sWk, $sRes); if (!_isNormalBlock($iBlock)) { return ''; } $iRest = $iSize; //my($i, $iGetSize, $iNext); $sRes = ''; /* TODO my @aKeys= sort({$a<=>$b} keys(%{$rhInfo->{_BBD_INFO}})); while ($iRest > 0) { my @aRes = grep($_ >= $iBlock, @aKeys); my $iNKey = $aRes[0]; $i = $iNKey - $iBlock; $iNext = $rhInfo->{_BBD_INFO}{$iNKey}; _setFilePos($iBlock, 0, $rhInfo); my $iGetSize = ($rhInfo->{_BIG_BLOCK_SIZE} * ($i+1)); $iGetSize = $iRest if($iRest < $iGetSize); $rhInfo->{_FILEH_}->read( $sWk, $iGetSize); $sRes .= $sWk; $iRest -= $iGetSize; $iBlock= $iNext; } */ return $sRes; } #------------------------------------------------------------------------------ # _getNextBlockNo (OLE::Storage_Lite) #------------------------------------------------------------------------------ function _getNextBlockNo($iBlockNo, $rhInfo) { $iRes = $rhInfo->_BBD_INFO[$iBlockNo]; return ($iRes!==false) ? $iRes : $iBlockNo+1; } #------------------------------------------------------------------------------ # _isNormalBlock (OLE::Storage_Lite) # 0xFFFFFFFC : BDList, 0xFFFFFFFD : BBD, # 0xFFFFFFFE: End of Chain 0xFFFFFFFF : unused #------------------------------------------------------------------------------ function _isNormalBlock($iBlock) { return ($iBlock < 0xFFFFFFFC) ? 1 : false; } #------------------------------------------------------------------------------ # _getSmallData (OLE::Storage_Lite) #------------------------------------------------------------------------------ function _getSmallData($iSmBlock, $iSize, $rhInfo) { //my($sRes, $sWk); $iRest = $iSize; $sRes = ''; while ($iRest > 0) { _setFilePosSmall($iSmBlock, $rhInfo); $sWk=fread($rhInfo->_FILEH_, ($iRest >= $rhInfo->_SMALL_BLOCK_SIZE) ? $rhInfo->_SMALL_BLOCK_SIZE : $iRest); $sRes .= $sWk; $iRest -= $rhInfo->_SMALL_BLOCK_SIZE; $iSmBlock= _getNextSmallBlockNo($iSmBlock, $rhInfo); } return $sRes; } #------------------------------------------------------------------------------ # _setFilePosSmall(OLE::Storage_Lite) #------------------------------------------------------------------------------ function _setFilePosSmall($iSmBlock, $rhInfo) { $iSmStart = $rhInfo->_SB_START; $iBaseCnt = $rhInfo->_BIG_BLOCK_SIZE / $rhInfo->_SMALL_BLOCK_SIZE; $iNth = floor($iSmBlock/$iBaseCnt); $iPos = $iSmBlock % $iBaseCnt; $iBlk = _getNthBlockNo($iSmStart, $iNth, $rhInfo); _setFilePos($iBlk, $iPos * $rhInfo->_SMALL_BLOCK_SIZE, $rhInfo); } #------------------------------------------------------------------------------ # _getNextSmallBlockNo (OLE::Storage_Lite) #------------------------------------------------------------------------------ function _getNextSmallBlockNo($iSmBlock, $rhInfo) { //my($sWk); $iBaseCnt = $rhInfo->_BIG_BLOCK_SIZE / LongIntSize; $iNth = floor($iSmBlock/$iBaseCnt); $iPos = $iSmBlock % $iBaseCnt; $iBlk = _getNthBlockNo($rhInfo->_SBD_START, $iNth, $rhInfo); _setFilePos($iBlk, $iPos * LongIntSize, $rhInfo); $sWk=fread($rhInfo->_FILEH_, LongIntSize); $data=unpack("Vint", $sWk); return $data["int"]; } } ?>