Re: [PEAR-BUGS] [PEAR-BUG] Bug #19284 [Com]: RC2 breaks header in excel files from Spreadsheet_Excel_Writer
[email protected] (lin Jim) Thu, 23 Feb 2012 01:41:02 -0400
| Newsgroups | php.pear.qa |
|---|---|
| Message-ID | <[email protected]> |
iphone On feb 22, 2012, at 18:21, "[email protected]" <[email protected]> wrote: > Edit report at https://pear.php.net/bugs/bug.php?id=19284&edit=1 > > ID: 19284 > Comment by: [email protected] > Reported By: mgfreshour at gmail dot com > Summary: RC2 breaks header in excel files from > Spreadsheet_Excel_Writer > Status: Feedback > Type: Bug > Package: OLE > Operating System: CentOS release 5.6 (Final) > Package Version: 1.0.0RC2 > PHP Version: 5.2.17 > Roadmap Versions: > New Comment: > > The bug is introduced between 7a0455f79a and bb5bd8897c. This is the > only code that changed: > > $ diff OLE.20090716.7a0455f79a/PPS/Root.php > OLE.20120125.bb5bd8897c/PPS/Root.php > 35a36,41 >> * Flag to enable new logic >> * @var bool >> */ >> var $new_func = true; >> >> /** > 203a210,212 >> if($this->new_func) >> return $this->_create_header($iSBDcnt, $iBBcnt, $iPPScnt); >> > 408a418,420 >> if($this->new_func) >> return $this->_create_big_block_chain($iSbdSize, $iBsize, > $iPpsCnt); >> > 484a497,736 >> >> >> >> /** >> * New method to store Bigblock chain >> * >> * @access private >> * @param integer $num_sb_blocks - number of Smallblock depot > blocks >> * @param integer $num_bb_blocks - number of Bigblock depot > blocks >> * @param integer $num_pps_blocks - number of PropertySetStorage > blocks >> */ >> function _create_big_block_chain($num_sb_blocks, $num_bb_blocks, > $num_pps_blocks) >> { >> $FILE = $this->_FILEH_; >> >> $bbd_info = $this->_calculate_big_block_chain($num_sb_blocks, > $num_bb_blocks, $num_pps_blocks); >> >> $data = ""; >> >> if($num_sb_blocks > 0) >> { >> for($i = 0; $i<($num_sb_blocks-1); $i++) >> $data .= pack("V", $i+1); >> $data .= pack("V", -2); >> } >> >> for($i = 0; $i<($num_bb_blocks-1); $i++) >> $data .= pack("V", $i + $num_sb_blocks + 1); >> $data .= pack("V", -2); >> >> for($i = 0; $i<($num_pps_blocks-1); $i++) >> $data .= pack("V", $i + $num_sb_blocks + $num_bb_blocks + 1); >> $data .= pack("V", -2); >> >> for($i = 0; $i < $bbd_info["0xFFFFFFFD_blockchain_entries"]; > $i++) >> $data .= pack("V", 0xFFFFFFFD); >> >> for($i = 0; $i < $bbd_info["0xFFFFFFFC_blockchain_entries"]; > $i++) >> $data .= pack("V", 0xFFFFFFFC); >> >> // Adjust for Block >> $all_entries = $num_sb_blocks + $num_bb_blocks + $num_pps_blocks > + $bbd_info["0xFFFFFFFD_blockchain_entries"] + > $bbd_info["0xFFFFFFFC_blockchain_entries"]; >> if($all_entries % $bbd_info["entries_per_block"]) >> { >> $rest = $bbd_info["entries_per_block"] - ($all_entries % > $bbd_info["entries_per_block"]); >> for($i = 0; $i < $rest; $i++) >> $data .= pack("V", -1); >> } >> >> // Extra BDList >> if($bbd_info["blockchain_list_entries"] > > $bbd_info["header_blockchain_list_entries"]) >> { >> $iN=0; >> $iNb=0; >> for($i = $bbd_info["header_blockchain_list_entries"]; $i < > $bbd_info["blockchain_list_entries"]; $i++, $iN++) >> { >> if($iN >= ($bbd_info["entries_per_block"]-1)) >> { >> $iN = 0; >> $iNb++; >> $data .= pack("V", $num_sb_blocks + $num_bb_blocks + > $num_pps_blocks + $bbd_info["0xFFFFFFFD_blockchain_entries"] + $iNb); >> } >> >> $data .= pack("V", $num_bb_blocks + $num_sb_blocks + > $num_pps_blocks + $i); >> } >> >> $all_entries = $bbd_info["blockchain_list_entries"] - > $bbd_info["header_blockchain_list_entries"]; >> if(($all_entries % ($bbd_info["entries_per_block"] - 1))) >> { >> $rest = ($bbd_info["entries_per_block"] - 1) - > ($all_entries % ($bbd_info["entries_per_block"] - 1)); >> for($i = 0; $i < $rest; $i++) >> $data .= pack("V", -1); >> } >> >> $data .= pack("V", -2); >> } >> >> /* >> $this->dump($data, 0, strlen($data)); >> die; >> */ >> >> fwrite($FILE, $data); >> } >> >> /** >> * New method to store Header >> * >> * @access private >> * @param integer $num_sb_blocks - number of Smallblock depot > blocks >> * @param integer $num_bb_blocks - number of Bigblock depot > blocks >> * @param integer $num_pps_blocks - number of PropertySetStorage > blocks >> */ >> function _create_header($num_sb_blocks, $num_bb_blocks, > $num_pps_blocks) >> { >> $FILE = $this->_FILEH_; >> >> $bbd_info = $this->_calculate_big_block_chain($num_sb_blocks, > $num_bb_blocks, $num_pps_blocks); >> >> // Save Header >> fwrite($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", $bbd_info["blockchain_list_entries"]) >> . pack("V", $num_sb_blocks + $num_bb_blocks) //ROOT > START >> . pack("V", 0) >> . pack("V", 0x1000) >> ); >> >> //Small Block Depot >> if($num_sb_blocks > 0) >> fwrite($FILE, pack("V", 0)); >> else >> fwrite($FILE, pack("V", -2)); >> >> fwrite($FILE, pack("V", 1)); >> >> // Extra BDList Start, Count >> if($bbd_info["blockchain_list_entries"] < > $bbd_info["header_blockchain_list_entries"]) >> { >> fwrite($FILE, >> pack("V", -2). // Extra BDList Start >> pack("V", 0) // Extra BDList Count >> ); >> } >> else >> { >> fwrite($FILE, pack("V", $num_sb_blocks + $num_bb_blocks + > $num_pps_blocks + $bbd_info["0xFFFFFFFD_blockchain_entries"]) . > pack("V", $bbd_info["0xFFFFFFFC_blockchain_entries"])); >> } >> >> // BDList >> for ($i=0; $i < $bbd_info["header_blockchain_list_entries"] and > $i < $bbd_info["blockchain_list_entries"]; $i++) >> { >> fwrite($FILE, pack("V", $num_bb_blocks + $num_sb_blocks + > $num_pps_blocks + $i)); >> } >> >> if($i < $bbd_info["header_blockchain_list_entries"]) >> { >> for($j = 0; $j < > ($bbd_info["header_blockchain_list_entries"]-$i); $j++) >> { >> fwrite($FILE, (pack("V", -1))); >> } >> } >> } >> >> /** >> * New method to calculate Bigblock chain >> * >> * @access private >> * @param integer $num_sb_blocks - number of Smallblock depot > blocks >> * @param integer $num_bb_blocks - number of Bigblock depot > blocks >> * @param integer $num_pps_blocks - number of PropertySetStorage > blocks >> */ >> function _calculate_big_block_chain($num_sb_blocks, > $num_bb_blocks, $num_pps_blocks) >> { >> $bbd_info["entries_per_block"] = $this->_BIG_BLOCK_SIZE / > OLE_LONG_INT_SIZE; >> $bbd_info["header_blockchain_list_entries"] = > ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE_LONG_INT_SIZE; >> $bbd_info["blockchain_entries"] = $num_sb_blocks + > $num_bb_blocks + $num_pps_blocks; >> $bbd_info["0xFFFFFFFD_blockchain_entries"] = > $this->get_number_of_pointer_blocks($bbd_info["blockchain_entries"]); >> $bbd_info["blockchain_list_entries"] = > $this->get_number_of_pointer_blocks($bbd_info["blockchain_entries"] + > $bbd_info["0xFFFFFFFD_blockchain_entries"]); >> >> // do some magic >> $bbd_info["ext_blockchain_list_entries"] = 0; >> $bbd_info["0xFFFFFFFC_blockchain_entries"] = 0; >> if($bbd_info["blockchain_list_entries"] > > $bbd_info["header_blockchain_list_entries"]) >> { >> do >> { >> $bbd_info["blockchain_list_entries"] = > $this->get_number_of_pointer_blocks($bbd_info["blockchain_entries"] + > $bbd_info["0xFFFFFFFD_blockchain_entries"] + > $bbd_info["0xFFFFFFFC_blockchain_entries"]); >> $bbd_info["ext_blockchain_list_entries"] = > $bbd_info["blockchain_list_entries"] - > $bbd_info["header_blockchain_list_entries"]; >> $bbd_info["0xFFFFFFFC_blockchain_entries"] = > $this->get_number_of_pointer_blocks($bbd_info["ext_blockchain_list_entries"]); >> $bbd_info["0xFFFFFFFD_blockchain_entries"] = > $this->get_number_of_pointer_blocks($num_sb_blocks + $num_bb_blocks + > $num_pps_blocks + $bbd_info["0xFFFFFFFD_blockchain_entries"] + > $bbd_info["0xFFFFFFFC_blockchain_entries"]); >> } >> while($bbd_info["blockchain_list_entries"] < > $this->get_number_of_pointer_blocks($bbd_info["blockchain_entries"] + > $bbd_info["0xFFFFFFFD_blockchain_entries"] + > $bbd_info["0xFFFFFFFC_blockchain_entries"])); >> } >> >> return $bbd_info; >> } >> >> /** >> * Calculates number of pointer blocks >> * >> * @access public >> * @param integer $num_pointers - number of pointers >> */ >> function get_number_of_pointer_blocks($num_pointers) >> { >> $pointers_per_block = $this->_BIG_BLOCK_SIZE / > OLE_LONG_INT_SIZE; >> >> return floor($num_pointers / $pointers_per_block) + > (($num_pointers % $pointers_per_block)? 1: 0); >> } >> >> /** >> * Support method for some hexdumping >> * >> * @access public >> * @param string $data - Binary data >> * @param integer $from - Start offset of data to dump >> * @param integer $to - Target offset of data to dump >> */ >> function dump($data, $from, $to) >> { >> $chars = array(); >> $i = 0; >> for($i = $from; $i < $to; $i++) >> { >> if(sizeof($chars) == 16) >> { >> printf("%08X (% 12d) |", $i-16, $i-16); >> foreach($chars as $char) >> printf(" %02X", $char); >> print " |\n"; >> >> $chars = array(); >> } >> >> $chars[] = ord($data[$i]); >> } >> >> if(sizeof($chars)) >> { >> printf("%08X (% 12d) |", $i-sizeof($chars), > $i-sizeof($chars)); >> foreach($chars as $char) >> printf(" %02X", $char); >> print " |\n"; >> >> $chars = array(); >> } >> } > > > > Code to generate the XLS output file: > > <?php > > error_reporting(0); > > require_once('PEAR.php'); > require_once('Spreadsheet/Excel/Writer.php'); > > $workbook = new Spreadsheet_Excel_Writer(); > $workbook->setVersion(8); > > $worksheet = $workbook->addWorksheet('My first worksheet'); > > $worksheet->setLandscape(); > > $format_even_rows = $workbook->addFormat(); > > $workbook->setCustomColor(12, 204, 204, 204); > > $format_even_rows->setFgColor(12); > $format_even_rows->setBottom(1); > $format_even_rows->setLeft(1); > $format_even_rows->setRight(1); > $format_even_rows->setTop(1); > $format_even_rows->setNumFormat('@'); > > $format_even_rows1 = $workbook ->addFormat(); > $format_even_rows1->setFgColor(12); > $format_even_rows1->setBottom(1); > $format_even_rows1->setLeft(1); > $format_even_rows1->setRight(1); > $format_even_rows1->setTop(1); > $format_even_rows1->setNumFormat('#,##0'); > > for($i=0; $i<1000; $i++) > { > $worksheet->write($i, 0, 'purple', $format_even_rows); > $worksheet->write($i, 1, 'monkey', $format_even_rows); > $worksheet->write($i, 2, 'dishwasher', $format_even_rows); > $worksheet->write($i, 3, '999', $format_even_rows); > $worksheet->write($i, 4, '1000', $format_even_rows1); > } > > $worksheet->setColumn(0, 4, 50); > // Let's send the file > $workbook->send('test.xls'); > $workbook->close(); > > ?> > > > > Binary comparison between the 2 XLS files (similar difference in header > as indicated by Morgan above, additional differences later in the file > can be ignored as they change every time output is regenerated): > > $ cmp -l OLE.20090716.7a0455f79a.output.xls > OLE.20120125.bb5bd8897c.output.xls > 61 0 376 > 62 0 377 > 63 0 377 > 64 0 377 > 79974 32 236 > 79975 247 176 > 79976 214 244 > 79982 32 236 > 79983 247 176 > 79984 214 244 > > > Windows XP with Excel 2003 does not have an issue. > > Windows 7 with Excel 2010 reports corrupt file error. > > Our temporary workaround is to freeze OLE at RC1. > > Take care, > Jon > > > Previous Comments: > ------------------------------------------------------------------------ > > [2012-02-22 20:23:12] jonl > > Just realized no one maintains OLE > > This week I'll try to go thru the commits sequentially from RC1 to RC2 > to narrow it down > > ------------------------------------------------------------------------ > > [2012-02-22 18:28:38] jonl > > We are also experiencing this problem via Spreadsheet_Excel_Writer on > Windows 7 with Excel 2010. Windows XP with Excel 2003 works fine. > > We are experiencing in both Slackware-12ish/Apache-2.2.22/PHP-5.3.10 and > Slackware-10.2ish/Apache-1.3.42/PHP-5.3.10. All PEAR modules are > current. > > Let us know what you need -- test cases, beer -- and we will oblige. > > ------------------------------------------------------------------------ > > [2012-02-17 12:06:05] ttischbein > > I have the same problem. But I can open the corrupt xls file with > OpenOffice Calc. Another notice: If I write less rows to the sheet, the > output xls file is ok. > I have a php script to reconstruate the Bug but where I can upload it? > > ------------------------------------------------------------------------ > > [2012-02-10 09:08:04] doconnor > > -Status: Open > +Status: Feedback > > > ------------------------------------------------------------------------ > > [2012-02-10 09:07:57] doconnor > > Also, which of the comments (Jan 25 2012? earlier) do you think > introduced this? > https://github.com/pear/OLE/commits/master > > ------------------------------------------------------------------------ > > The remainder of the comments for this report are too long. To view > the rest of the comments, please view the bug report online at > http://pear.php.net/bugs/bug.php?id=19284 > > -- > Edit this bug report at https://pear.php.net/bugs/bug.php?id=19284&edit=1 > > > -- > PEAR Bugs Mailing List (http://pear.php.net/bugs/) > To unsubscribe, visit: http://www.php.net/unsub.php >