*/
define('SPREADSHEET_EXCEL_WRITER_NE', "<>");
-/**
-* Class for creating OLE streams for Excel Spreadsheets
-*
-* @author Xavier Noguer <xnoguer@rezebra.com>
-* @package Spreadsheet_WriteExcel
-*/
-class OLEwriter
+define('PpsType_Root', 5);
+define('PpsType_Dir', 1);
+define('PpsType_File', 2);
+define('DataSizeSmall', 0x1000);
+define('LongIntSize', 4);
+define('PpsSize', 0x80);
+
+function Asc2Ucs($sAsc)
{
- /**
- * Filename for the OLE stream
- * @var string
- * @see _initialize()
- */
- var $_OLEfilename;
+ return implode("\x00", (preg_split('//', $sAsc, -1, PREG_SPLIT_NO_EMPTY)))."\x00";
+}
- /**
- * Filehandle for the OLE stream
- * @var resource
- */
- var $_filehandle;
+function Ucs2Asc($sUcs)
+{
+ $chars=explode("\x00", $sUcs);
+ array_pop($chars);
+ return implode("", $chars);
+}
- /**
- * Name of the temporal file in case OLE stream goes to stdout
- * @var string
- */
- var $_tmp_filename;
+function OLEDate2Local($sDateTime)
+{
+}
- /**
- * Variable for preventing closing two times
- * @var integer
- */
- var $_fileclosed;
+#------------------------------------------------------------------------------
+# Localtime->OLE Date
+#------------------------------------------------------------------------------
+function LocalDate2OLE($raDate)
+{
+}
- /**
- * Size of the data to be written to the OLE stream
- * @var integer
- */
- var $_biffsize;
+function _leapYear($iYear)
+{
+ return ((($iYear % 4)==0) && (($iYear % 100) || ($iYear % 400)==0)) ? 1 : 0;
+}
- /**
- * Real data size to be written to the OLE stream
- * @var integer
- */
- var $_booksize;
+function _yearDays($iYear)
+{
+ return _leapYear($iYear) ? 366 : 365;
+}
- /**
- * Number of big blocks in the OLE stream
- * @var integer
- */
- var $_big_blocks;
+function _monthDays($iMon, $iYear)
+{
+ if ($iMon == 1 || $iMon == 3 || $iMon == 5 || $iMon == 7 ||
+ $iMon == 8 || $iMon == 10 || $iMon == 12)
+ return 31;
+ elseif ($iMon == 4 || $iMon == 6 || $iMon == 9 || $iMon == 11)
+ return 30;
+ elseif ($iMon == 2)
+ return _leapYear($iYear) ? 29 : 28;
+}
- /**
- * Number of list blocks in the OLE stream
- * @var integer
- */
- var $_list_blocks;
+/*
+ * This is the OLE::Storage_Lite Perl package ported to PHP
+ * OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org
+ */
- /**
- * Number of big blocks in the OLE stream
- * @var integer
- */
- var $_root_start;
+class ole_pps
+{
+ var $No;
+ var $Name;
+ var $Type;
+ var $PrevPps;
+ var $NextPps;
+ var $DirPps;
+ var $Time1st;
+ var $Time2nd;
+ var $StartBlock;
+ var $Size;
+ var $Data;
+ var $Child;
+ var $_PPS_FILE;
+
+ #------------------------------------------------------------------------------
+ # _new (OLE::Storage_Lite::PPS)
+ # for OLE::Storage_Lite
+ #------------------------------------------------------------------------------
+ function ole_pps($iNo, $sNm, $iType, $iPrev, $iNext, $iDir,
+ $raTime1st, $raTime2nd, $iStart, $iSize,
+ $sData=false, $raChild=false)
+ {
+ #1. Constructor for OLE::Storage_Lite
+
+ $this->No = $iNo;
+ $this->Name = $sNm;
+ $this->Type = $iType;
+ $this->PrevPps = $iPrev;
+ $this->NextPps = $iNext;
+ $this->DirPps = $iDir;
+ $this->Time1st = $raTime1st;
+ $this->Time2nd = $raTime2nd;
+ $this->StartBlock = $iStart;
+ $this->Size = $iSize;
+ $this->Data = $sData;
+ $this->Child = $raChild;
+ $this->_PPS_FILE = NULL;
+ }
+
+ #------------------------------------------------------------------------------
+ # _DataLen (OLE::Storage_Lite::PPS)
+ # Check for update
+ #------------------------------------------------------------------------------
+ function _DataLen()
+ {
+ if ($this->Data===false)
+ return 0;
+
+ if ($this->_PPS_FILE)
+ return filesize($this->_PPS_FILE);
+
+ return strlen($this->Data);
+ }
+
+ #------------------------------------------------------------------------------
+ # _makeSmallData (OLE::Storage_Lite::PPS)
+ #------------------------------------------------------------------------------
+ function _makeSmallData(&$aList, $rhInfo)
+ {
+ //my ($sRes);
+ $FILE = $rhInfo->_FILEH_;
+ $iSmBlk = 0;
+ $sRes = '';
+
+ for ($c=0;$c<sizeof($aList);$c++)
+ {
+ $oPps=&$aList[$c];
- /**
- * Constructor for the OLEwriter class
- *
- * @param string $OLEfilename the name of the file for the OLE stream
- */
- function OLEwriter($OLEfilename)
- {
- $this->_OLEfilename = $OLEfilename;
- $this->_filehandle = '';
- $this->_tmp_filename = '';
- $this->_fileclosed = 0;
- $this->_biff_only = 0;
- //$this->_size_allowed = 0;
- $this->_biffsize = 0;
- $this->_booksize = 0;
- $this->_big_blocks = 0;
- $this->_list_blocks = 0;
- $this->_root_start = 0;
- //$this->_block_count = 4;
- $this->_initialize();
- }
+ #1. Make SBD, small data string
- /**
- * Check for a valid filename and store the filehandle.
- * Filehandle "-" writes to STDOUT
- *
- * @access private
- */
- function _initialize()
- {
- $OLEfile = $this->_OLEfilename;
+ if ($oPps->Type==PpsType_File)
+ {
+ if ($oPps->Size<=0)
+ continue;
- if (($OLEfile == '-') or ($OLEfile == '')) {
- $this->_tmp_filename = tempnam("/tmp", "OLEwriter");
- $fh = fopen($this->_tmp_filename, "wb");
- if ($fh == false) {
- die("Can't create temporary file.");
- }
- } else {
- // Create a new file, open for writing (in binmode)
- $fh = fopen($OLEfile, "wb");
- if ($fh == false) {
- die("Can't open $OLEfile. It may be in use or protected.");
+ if($oPps->Size < $rhInfo->_SMALL_SIZE)
+ {
+ $iSmbCnt = floor($oPps->Size / $rhInfo->_SMALL_BLOCK_SIZE) +
+ (($oPps->Size % $rhInfo->_SMALL_BLOCK_SIZE) ? 1 : 0);
+ #1.1 Add to SBD
+ for ($i = 0; $i<($iSmbCnt-1); $i++)
+ fputs($FILE, pack("V", $i+$iSmBlk+1));
+ fputs($FILE, pack("V", -2));
+
+ #1.2 Add to Data String(this will be written for RootEntry)
+ #Check for update
+ if ($oPps->_PPS_FILE)
+ {
+ //my $sBuff;
+ fseek($oPps->_PPS_FILE, 0, SEEK_SET); #To The Top
+ while ($sBuff=fread($oPps->_PPS_FILE, 4096))
+ $sRes .= $sBuff;
+ }
+ else
+ $sRes .= $oPps->Data;
+ if($oPps->Size % $rhInfo->_SMALL_BLOCK_SIZE)
+ {
+ $sRes .= (str_repeat("\x00",
+ ($rhInfo->_SMALL_BLOCK_SIZE -
+ ($oPps->Size % $rhInfo->_SMALL_BLOCK_SIZE))));
+ }
+ #1.3 Set for PPS
+ $oPps->StartBlock = $iSmBlk;
+ $iSmBlk += $iSmbCnt;
+ }
}
- }
-
- // Store filehandle
- $this->_filehandle = $fh;
- }
-
-
- /**
- * Set the size of the data to be written to the OLE stream.
- * The maximun size comes from this:
- * $big_blocks = (109 depot block x (128 -1 marker word)
- * - (1 x end words)) = 13842
- * $maxsize = $big_blocks * 512 bytes = 7087104
- *
- * @access public
- * @see Spreadsheet_Excel_Writer_Workbook::store_OLE_file()
- * @param integer $biffsize The size of the data to be written to the OLE stream
- * @return integer 1 for success
- */
- function setSize($biffsize)
- {
- $maxsize = 7087104; // TODO: extend max size
- if ($biffsize > $maxsize) {
- die("Maximum file size, $maxsize, exceeded.");
}
-
- $this->_biffsize = $biffsize;
- // Set the min file size to 4k to avoid having to use small blocks
- if ($biffsize > 4096) {
- $this->_booksize = $biffsize;
- } else {
- $this->_booksize = 4096;
- }
- //$this->_size_allowed = 1;
- return(1);
+ $iSbCnt = floor($rhInfo->_BIG_BLOCK_SIZE / LongIntSize);
+ if ($iSmBlk % $iSbCnt)
+ fputs($FILE, str_repeat(pack("V", -1), $iSbCnt - ($iSmBlk % $iSbCnt)));
+ #2. Write SBD with adjusting length for block
+ return $sRes;
+ }
+
+ #------------------------------------------------------------------------------
+ # _savePpsWk (OLE::Storage_Lite::PPS)
+ #------------------------------------------------------------------------------
+ function _savePpsWk($rhInfo)
+ {
+ #1. Write PPS
+ $FILE=$rhInfo->_FILEH_;
+ fputs($FILE,
+ $this->Name.
+ str_repeat("\x00", 64 - strlen($this->Name)). # 64
+ pack("v", strlen($this->Name) + 2). # 66
+ pack("c", $this->Type). # 67
+ pack("c", 0x00). #UK # 68
+ pack("V", $this->PrevPps). #Prev # 72
+ pack("V", $this->NextPps). #Next # 76
+ pack("V", $this->DirPps). #Dir # 80
+ "\x00\x09\x02\x00". # 84
+ "\x00\x00\x00\x00". # 88
+ "\xc0\x00\x00\x00". # 92
+ "\x00\x00\x00\x46". # 96
+ "\x00\x00\x00\x00". # 100
+ "\x00\x00\x00\x00\x00\x00\x00\x00".
+ "\x00\x00\x00\x00\x00\x00\x00\x00".
+ pack("V", ($this->StartBlock!==false) ?
+ $this->StartBlock : 0). # 120
+ pack("V", ($this->Size!==false) ?
+ $this->Size : 0). # 124
+ pack("V", 0) # 128
+ );
}
+}
- /**
- * Calculate various sizes needed for the OLE stream
- *
- * @access private
- */
- function _calculateSizes()
- {
- $datasize = $this->_booksize;
- if ($datasize % 512 == 0) {
- $this->_big_blocks = $datasize/512;
- } else {
- $this->_big_blocks = floor($datasize/512) + 1;
- }
- // There are 127 list blocks and 1 marker blocks for each big block
- // depot + 1 end of chain block
- $this->_list_blocks = floor(($this->_big_blocks)/127) + 1;
- $this->_root_start = $this->_big_blocks;
- }
+/*
+ * This is the OLE::Storage_Lite Perl package ported to PHP
+ * OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org
+ */
- /**
- * Write root entry, big block list and close the filehandle.
- * This routine is used to explicitly close the open filehandle without
- * having to wait for DESTROY.
- *
- * @access public
- * @see Spreadsheet_Excel_Writer_Workbook::store_OLE_file()
- */
- function close()
- {
- //return if not $this->{_size_allowed};
- $this->_writePadding();
- $this->_writePropertyStorage();
- $this->_writeBigBlockDepot();
- // Close the filehandle
- fclose($this->_filehandle);
- if (($this->_OLEfilename == '-') or ($this->_OLEfilename == '')) {
- $fh = fopen($this->_tmp_filename, "rb");
- if ($fh == false) {
- die("Can't read temporary file.");
+class ole_pps_file extends ole_pps
+{
+ function ole_pps_file($sNm, $sData=false, $sFile=false)
+ {
+ $this->No = false;
+ $this->Name = $sNm;
+ $this->Type = PpsType_File;
+ $this->PrevPps = false;
+ $this->NextPps = false;
+ $this->DirPps = false;
+ $this->Time1st = false;
+ $this->Time2nd = false;
+ $this->StartBlock = false;
+ $this->Size = false;
+ $this->Data = ($sFile===false) ? $sData : '';
+ $this->Child = false;
+
+ if ($sFile!==false)
+ {
+ if (is_ressource($sFile))
+ $this->_PPS_FILE=$sFile;
+ elseif ($sFile=="")
+ {
+ $fname=tempnam("php_ole");
+ $this->_PPS_FILE=fopen($fname, "r+b");
+ }
+ else
+ {
+ $fname=$sFile;
+ $this->_PPS_FILE=fopen($fname, "r+b");
}
- fpassthru($fh);
- @unlink($this->_tmp_filename);
- }
- $this->_fileclosed = 1;
- }
-
-
- /**
- * Write BIFF data to OLE file.
- *
- * @param string $data string of bytes to be written
- */
- function write($data)
- {
- fwrite($this->_filehandle, $data, strlen($data));
- }
-
-
- /**
- * Write OLE header block.
- */
- function writeHeader()
- {
- $this->_calculateSizes();
- $root_start = $this->_root_start;
- $num_lists = $this->_list_blocks;
- $id = pack("nnnn", 0xD0CF, 0x11E0, 0xA1B1, 0x1AE1);
- $unknown1 = pack("VVVV", 0x00, 0x00, 0x00, 0x00);
- $unknown2 = pack("vv", 0x3E, 0x03);
- $unknown3 = pack("v", -2);
- $unknown4 = pack("v", 0x09);
- $unknown5 = pack("VVV", 0x06, 0x00, 0x00);
- $num_bbd_blocks = pack("V", $num_lists);
- $root_startblock = pack("V", $root_start);
- $unknown6 = pack("VV", 0x00, 0x1000);
- $sbd_startblock = pack("V", -2);
- $unknown7 = pack("VVV", 0x00, -2 ,0x00);
- $unused = pack("V", -1);
-
- fwrite($this->_filehandle, $id);
- fwrite($this->_filehandle, $unknown1);
- fwrite($this->_filehandle, $unknown2);
- fwrite($this->_filehandle, $unknown3);
- fwrite($this->_filehandle, $unknown4);
- fwrite($this->_filehandle, $unknown5);
- fwrite($this->_filehandle, $num_bbd_blocks);
- fwrite($this->_filehandle, $root_startblock);
- fwrite($this->_filehandle, $unknown6);
- fwrite($this->_filehandle, $sbd_startblock);
- fwrite($this->_filehandle, $unknown7);
-
- for ($i=1; $i <= $num_lists; $i++) {
- $root_start++;
- fwrite($this->_filehandle, pack("V",$root_start));
- }
- for ($i = $num_lists; $i <=108; $i++) {
- fwrite($this->_filehandle, $unused);
- }
- }
-
-
- /**
- * Write big block depot.
- *
- * @access private
- */
- function _writeBigBlockDepot()
- {
- $num_blocks = $this->_big_blocks;
- $num_lists = $this->_list_blocks;
- $total_blocks = $num_lists *128;
- $used_blocks = $num_blocks + $num_lists +2;
-
- $marker = pack("V", -3);
- $end_of_chain = pack("V", -2);
- $unused = pack("V", -1);
-
- for ($i = 1; $i < $num_blocks; $i++) {
- fwrite($this->_filehandle, pack("V",$i));
- }
-
- fwrite($this->_filehandle, $end_of_chain);
- fwrite($this->_filehandle, $end_of_chain);
- for ($i = 0; $i < $num_lists; $i++) {
- fwrite($this->_filehandle, $marker);
- }
- for ($i = $used_blocks; $i <= $total_blocks; $i++) {
- fwrite($this->_filehandle, $unused);
+ if ($sData!==false)
+ fputs($this->_PPS_FILE, $sData);
}
}
- /**
- * Write property storage. TODO: add summary sheets
- *
- * @access private
- */
- function _writePropertyStorage()
+ function append ($sData)
{
- //$rootsize = -2;
- /*************** name type dir start size */
- $this->_writePps("Root Entry", 0x05, 1, -2, 0x00);
- $this->_writePps("Book", 0x02, -1, 0x00, $this->_booksize);
- $this->_writePps('', 0x00, -1, 0x00, 0x0000);
- $this->_writePps('', 0x00, -1, 0x00, 0x0000);
+ if ($this->_PPS_FILE)
+ fputs($this->_PPS_FILE, $sData);
+ else
+ $this->Data.=$sData;
}
+}
-/**
-* Write property sheet in property storage
-*
-* @param string $name name of the property storage.
-* @param integer $type type of the property storage.
-* @param integer $dir dir of the property storage.
-* @param integer $start start of the property storage.
-* @param integer $size size of the property storage.
-* @access private
-*/
- function _writePps($name, $type, $dir, $start, $size)
- {
- $length = 0;
- $rawname = '';
-
- if ($name != '') {
- $name = $name . "\0";
- $name_length = strlen($name);
- for ($i = 0; $i < $name_length; $i++) {
- // Simulate a Unicode string
- $rawname .= pack("H*",dechex(ord($name{$i}))).pack("C",0);
- }
- $length = strlen($name) * 2;
- }
-
- $zero = pack("C", 0);
- $pps_sizeofname = pack("v", $length); // 0x40
- $pps_type = pack("v", $type); // 0x42
- $pps_prev = pack("V", -1); // 0x44
- $pps_next = pack("V", -1); // 0x48
- $pps_dir = pack("V", $dir); // 0x4c
-
- $unknown1 = pack("V", 0);
-
- $pps_ts1s = pack("V", 0); // 0x64
- $pps_ts1d = pack("V", 0); // 0x68
- $pps_ts2s = pack("V", 0); // 0x6c
- $pps_ts2d = pack("V", 0); // 0x70
- $pps_sb = pack("V", $start); // 0x74
- $pps_size = pack("V", $size); // 0x78
-
-
- fwrite($this->_filehandle, $rawname);
- for ($i = 0; $i < (64 -$length); $i++) {
- fwrite($this->_filehandle, $zero);
- }
- fwrite($this->_filehandle, $pps_sizeofname);
- fwrite($this->_filehandle, $pps_type);
- fwrite($this->_filehandle, $pps_prev);
- fwrite($this->_filehandle, $pps_next);
- fwrite($this->_filehandle, $pps_dir);
- for ($i = 0; $i < 5; $i++) {
- fwrite($this->_filehandle, $unknown1);
- }
- fwrite($this->_filehandle, $pps_ts1s);
- fwrite($this->_filehandle, $pps_ts1d);
- fwrite($this->_filehandle, $pps_ts2d);
- fwrite($this->_filehandle, $pps_ts2d);
- fwrite($this->_filehandle, $pps_sb);
- fwrite($this->_filehandle, $pps_size);
- fwrite($this->_filehandle, $unknown1);
- }
+/*
+ * This is the OLE::Storage_Lite Perl package ported to PHP
+ * OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org
+ */
- /**
- * Pad the end of the file
- *
- * @access private
- */
- function _writePadding()
- {
- $biffsize = $this->_biffsize;
- if ($biffsize < 4096) {
- $min_size = 4096;
- } else {
- $min_size = 512;
- }
- if ($biffsize % $min_size != 0) {
- $padding = $min_size - ($biffsize % $min_size);
- for ($i = 0; $i < $padding; $i++) {
- fwrite($this->_filehandle, "\0");
- }
- }
- }
+class ole_pps_root extends ole_pps
+{
+ function ole_pps_root($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));
+ }
+ }
}
/**
*/
function _storeOLEFile()
{
- $OLE = new OLEwriter($this->_filename);
- // Write Worksheet data if data <~ 7MB
- if ($OLE->setSize($this->_biffsize))
- {
- $OLE->writeHeader();
- $OLE->write($this->_data);
- foreach($this->_worksheets as $sheet)
- {
- while ($tmp = $sheet->getData()) {
- $OLE->write($tmp);
- }
+ if($this->_BIFF_version == 0x0600) {
+ $OLE = new ole_pps_file(Asc2Ucs('Workbook'));
+ } else {
+ $OLE = new ole_pps_file(Asc2Ucs('Book'));
+ }
+
+ $OLE->append($this->_data);
+
+ $total_worksheets = count($this->_worksheets);
+ for ($i = 0; $i < $total_worksheets; $i++) {
+ while ($tmp = $this->_worksheets[$i]->getData()) {
+ $OLE->append($tmp);
}
}
- $OLE->close();
- return true;
+
+ $root = new ole_pps_root(false, false, array($OLE));
+
+ $root->save($this->_filename);
}
/**