From c5ea92442dadba5535c8d72bcf8aaa348af8ef84 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Tue, 7 Dec 2010 17:34:47 +0000 Subject: [PATCH] Performance improvements for the Excel5 Reader and Writer git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@64968 2327b42d-5241-43d6-9e2a-de5ac946f064 --- Classes/PHPExcel/Calculation.php | 8 ++-- Classes/PHPExcel/Reader/Excel5.php | 30 ++++++------ Classes/PHPExcel/Shared/OLE.php | 48 +++++++++---------- Classes/PHPExcel/Shared/OLE/PPS.php | 8 ++-- Classes/PHPExcel/Shared/OLE/PPS/Root.php | 47 +++++++++--------- Classes/PHPExcel/Shared/OLERead.php | 61 +++++++++++------------- changelog.txt | 1 + 7 files changed, 99 insertions(+), 104 deletions(-) diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index 86a2f1e7..ae84b2b3 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -2630,11 +2630,11 @@ class PHPExcel_Calculation { // echo 'Element is a Percentage operator
'; $stack->push('Unary Operator','%'); // Put a percentage on the stack ++$index; - } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (rather than plus) can be discarded? + } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded? // echo 'Element is a Positive number, not Plus operator
'; ++$index; // Drop the redundant plus symbol - } elseif (($opCharacter == '~') && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde, because it's legal - return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression + } elseif ((($opCharacter == '~') || ($opCharacter == '|')) && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde or pipe, because they are legal + return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression } elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? // echo 'Element with value '.$opCharacter.' is an Operator
'; @@ -3278,7 +3278,7 @@ class PHPExcel_Calculation { // echo 'Token is a PHPExcel constant: '.$excelConstant.'
'; $stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]); $this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.$this->_showTypeDetails(self::$_ExcelConstants[$excelConstant])); - } elseif ((is_numeric($token)) || (is_bool($token)) || (is_null($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { + } elseif ((is_numeric($token)) || (is_null($token)) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { // echo 'Token is a number, boolean, string, null or an Excel error
'; $stack->push('Value',$token); // if the token is a named range, push the named range name onto the stack diff --git a/Classes/PHPExcel/Reader/Excel5.php b/Classes/PHPExcel/Reader/Excel5.php index a2b9b5d1..97c2cd89 100644 --- a/Classes/PHPExcel/Reader/Excel5.php +++ b/Classes/PHPExcel/Reader/Excel5.php @@ -570,7 +570,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader if (!$this->_readDataOnly) { foreach ($this->_objFonts as $objFont) { if (isset($objFont->colorIndex)) { - $color = self::_readColor($objFont->colorIndex,$this->_palette); + $color = self::_readColor($objFont->colorIndex,$this->_palette,$this->_version); $objFont->getColor()->setRGB($color['rgb']); } } @@ -580,12 +580,12 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $fill = $objStyle->getFill(); if (isset($fill->startcolorIndex)) { - $startColor = self::_readColor($fill->startcolorIndex,$this->_palette); + $startColor = self::_readColor($fill->startcolorIndex,$this->_palette,$this->_version); $fill->getStartColor()->setRGB($startColor['rgb']); } if (isset($fill->endcolorIndex)) { - $endColor = self::_readColor($fill->endcolorIndex,$this->_palette); + $endColor = self::_readColor($fill->endcolorIndex,$this->_palette,$this->_version); $fill->getEndColor()->setRGB($endColor['rgb']); } @@ -597,27 +597,27 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $diagonal = $objStyle->getBorders()->getDiagonal(); if (isset($top->colorIndex)) { - $borderTopColor = self::_readColor($top->colorIndex,$this->_palette); + $borderTopColor = self::_readColor($top->colorIndex,$this->_palette,$this->_version); $top->getColor()->setRGB($borderTopColor['rgb']); } if (isset($right->colorIndex)) { - $borderRightColor = self::_readColor($right->colorIndex,$this->_palette); + $borderRightColor = self::_readColor($right->colorIndex,$this->_palette,$this->_version); $right->getColor()->setRGB($borderRightColor['rgb']); } if (isset($bottom->colorIndex)) { - $borderBottomColor = self::_readColor($bottom->colorIndex,$this->_palette); + $borderBottomColor = self::_readColor($bottom->colorIndex,$this->_palette,$this->_version); $bottom->getColor()->setRGB($borderBottomColor['rgb']); } if (isset($left->colorIndex)) { - $borderLeftColor = self::_readColor($left->colorIndex,$this->_palette); + $borderLeftColor = self::_readColor($left->colorIndex,$this->_palette,$this->_version); $left->getColor()->setRGB($borderLeftColor['rgb']); } if (isset($diagonal->colorIndex)) { - $borderDiagonalColor = self::_readColor($diagonal->colorIndex,$this->_palette); + $borderDiagonalColor = self::_readColor($diagonal->colorIndex,$this->_palette,$this->_version); $diagonal->getColor()->setRGB($borderDiagonalColor['rgb']); } } @@ -4229,7 +4229,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 0x14: // offset: 16; size: 2; color index for sheet tab $colorIndex = self::_GetInt2d($recordData, 16); - $color = self::_readColor($colorIndex,$this->_palette); + $color = self::_readColor($colorIndex,$this->_palette,$this->_version); $this->_phpSheet->getTabColor()->setRGB($color['rgb']); break; @@ -4665,7 +4665,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 'tAdd': // addition case 'tConcat': // addition case 'tDiv': // division - case 'tEQ': // equaltiy + case 'tEQ': // equality case 'tGE': // greater than or equal case 'tGT': // greater than case 'tIsect': // intersection @@ -5373,7 +5373,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readBIFF8CellAddress($cellAddressStructure) { // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) - $row = self::_GetInt2d($cellAddressStructure, 0) + 1; + $row = self::_GetInt2d($cellAddressStructure, 0) + 1; // offset: 2; size: 2; index to column or column offset + relative flags @@ -6124,11 +6124,9 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader */ private static function _GetInt4d($data, $pos) { - //return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | - // (ord($data[$pos + 2]) << 16) | (ord($data[$pos + 3]) << 24); - // FIX: represent numbers correctly on 64-bit system // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 + // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems $_or_24 = ord($data[$pos + 3]); if ($_or_24 >= 128) { // negative number @@ -6146,7 +6144,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * @param array $palette Color palette * @return array RGB color value, example: array('rgb' => 'FF0000') */ - private static function _readColor($color,$palette) + private static function _readColor($color,$palette,$version) { if ($color <= 0x07 || $color >= 0x40) { // special built-in color @@ -6156,7 +6154,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader return $palette[$color - 8]; } else { // default color table - if ($this->_version == self::XLS_BIFF8) { + if ($version == self::XLS_BIFF8) { return self::_mapColor($color); } else { // BIFF5 diff --git a/Classes/PHPExcel/Shared/OLE.php b/Classes/PHPExcel/Shared/OLE.php index a7cc9c3d..a5c8dd1d 100644 --- a/Classes/PHPExcel/Shared/OLE.php +++ b/Classes/PHPExcel/Shared/OLE.php @@ -111,36 +111,36 @@ class PHPExcel_Shared_OLE throw new Exception("Only Little-Endian encoding is supported."); } // Size of blocks and short blocks in bytes - $this->bigBlockSize = pow(2, $this->_readInt2($fh)); - $this->smallBlockSize = pow(2, $this->_readInt2($fh)); + $this->bigBlockSize = pow(2, self::_readInt2($fh)); + $this->smallBlockSize = pow(2, self::_readInt2($fh)); // Skip UID, revision number and version number fseek($fh, 44); // Number of blocks in Big Block Allocation Table - $bbatBlockCount = $this->_readInt4($fh); + $bbatBlockCount = self::_readInt4($fh); // Root chain 1st block - $directoryFirstBlockId = $this->_readInt4($fh); + $directoryFirstBlockId = self::_readInt4($fh); // Skip unused bytes fseek($fh, 56); // Streams shorter than this are stored using small blocks - $this->bigBlockThreshold = $this->_readInt4($fh); + $this->bigBlockThreshold = self::_readInt4($fh); // Block id of first sector in Short Block Allocation Table - $sbatFirstBlockId = $this->_readInt4($fh); + $sbatFirstBlockId = self::_readInt4($fh); // Number of blocks in Short Block Allocation Table - $sbbatBlockCount = $this->_readInt4($fh); + $sbbatBlockCount = self::_readInt4($fh); // Block id of first sector in Master Block Allocation Table - $mbatFirstBlockId = $this->_readInt4($fh); + $mbatFirstBlockId = self::_readInt4($fh); // Number of blocks in Master Block Allocation Table - $mbbatBlockCount = $this->_readInt4($fh); + $mbbatBlockCount = self::_readInt4($fh); $this->bbat = array(); // Remaining 4 * 109 bytes of current block is beginning of Master // Block Allocation Table $mbatBlocks = array(); for ($i = 0; $i < 109; ++$i) { - $mbatBlocks[] = $this->_readInt4($fh); + $mbatBlocks[] = self::_readInt4($fh); } // Read rest of Master Block Allocation Table (if any is left) @@ -148,10 +148,10 @@ class PHPExcel_Shared_OLE for ($i = 0; $i < $mbbatBlockCount; ++$i) { fseek($fh, $pos); for ($j = 0; $j < $this->bigBlockSize / 4 - 1; ++$j) { - $mbatBlocks[] = $this->_readInt4($fh); + $mbatBlocks[] = self::_readInt4($fh); } // Last block id in each block points to next block - $pos = $this->_getBlockOffset($this->_readInt4($fh)); + $pos = $this->_getBlockOffset(self::_readInt4($fh)); } // Read Big Block Allocation Table according to chain specified by @@ -160,7 +160,7 @@ class PHPExcel_Shared_OLE $pos = $this->_getBlockOffset($mbatBlocks[$i]); fseek($fh, $pos); for ($j = 0 ; $j < $this->bigBlockSize / 4; ++$j) { - $this->bbat[] = $this->_readInt4($fh); + $this->bbat[] = self::_readInt4($fh); } } @@ -169,7 +169,7 @@ class PHPExcel_Shared_OLE $shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4; $sbatFh = $this->getStream($sbatFirstBlockId); for ($blockId = 0; $blockId < $shortBlockCount; ++$blockId) { - $this->sbat[$blockId] = $this->_readInt4($sbatFh); + $this->sbat[$blockId] = self::_readInt4($sbatFh); } fclose($sbatFh); @@ -225,7 +225,7 @@ class PHPExcel_Shared_OLE * @return int * @access public */ - public function _readInt1($fh) + private static function _readInt1($fh) { list(, $tmp) = unpack("c", fread($fh, 1)); return $tmp; @@ -237,7 +237,7 @@ class PHPExcel_Shared_OLE * @return int * @access public */ - public function _readInt2($fh) + private static function _readInt2($fh) { list(, $tmp) = unpack("v", fread($fh, 2)); return $tmp; @@ -249,7 +249,7 @@ class PHPExcel_Shared_OLE * @return int * @access public */ - public function _readInt4($fh) + private static function _readInt4($fh) { list(, $tmp) = unpack("V", fread($fh, 4)); return $tmp; @@ -269,11 +269,11 @@ class PHPExcel_Shared_OLE for ($pos = 0; ; $pos += 128) { fseek($fh, $pos, SEEK_SET); $nameUtf16 = fread($fh, 64); - $nameLength = $this->_readInt2($fh); + $nameLength = self::_readInt2($fh); $nameUtf16 = substr($nameUtf16, 0, $nameLength - 2); // Simple conversion from UTF-16LE to ISO-8859-1 $name = str_replace("\x00", "", $nameUtf16); - $type = $this->_readInt1($fh); + $type = self::_readInt1($fh); switch ($type) { case self::OLE_PPS_TYPE_ROOT: $pps = new PHPExcel_Shared_OLE_PPS_Root(null, null, array()); @@ -292,14 +292,14 @@ class PHPExcel_Shared_OLE fseek($fh, 1, SEEK_CUR); $pps->Type = $type; $pps->Name = $name; - $pps->PrevPps = $this->_readInt4($fh); - $pps->NextPps = $this->_readInt4($fh); - $pps->DirPps = $this->_readInt4($fh); + $pps->PrevPps = self::_readInt4($fh); + $pps->NextPps = self::_readInt4($fh); + $pps->DirPps = self::_readInt4($fh); fseek($fh, 20, SEEK_CUR); $pps->Time1st = self::OLE2LocalDate(fread($fh, 8)); $pps->Time2nd = self::OLE2LocalDate(fread($fh, 8)); - $pps->_StartBlock = $this->_readInt4($fh); - $pps->Size = $this->_readInt4($fh); + $pps->_StartBlock = self::_readInt4($fh); + $pps->Size = self::_readInt4($fh); $pps->No = count($this->_list); $this->_list[] = $pps; diff --git a/Classes/PHPExcel/Shared/OLE/PPS.php b/Classes/PHPExcel/Shared/OLE/PPS.php index aa1a4265..e3d4673a 100644 --- a/Classes/PHPExcel/Shared/OLE/PPS.php +++ b/Classes/PHPExcel/Shared/OLE/PPS.php @@ -169,10 +169,8 @@ class PHPExcel_Shared_OLE_PPS */ public function _getPpsWk() { - $ret = $this->Name; - for ($i = 0; $i < (64 - strlen($this->Name)); ++$i) { - $ret .= "\x00"; - } + $ret = str_pad($this->Name,64,"\x00"); + $ret .= pack("v", strlen($this->Name) + 2) // 66 . pack("c", $this->Type) // 67 . pack("c", 0x00) //UK // 68 @@ -215,4 +213,4 @@ class PHPExcel_Shared_OLE_PPS } return $this->No; } - } +} diff --git a/Classes/PHPExcel/Shared/OLE/PPS/Root.php b/Classes/PHPExcel/Shared/OLE/PPS/Root.php index 412f9928..a3c4ab6d 100644 --- a/Classes/PHPExcel/Shared/OLE/PPS/Root.php +++ b/Classes/PHPExcel/Shared/OLE/PPS/Root.php @@ -63,9 +63,9 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS { // Initial Setting for saving $this->_BIG_BLOCK_SIZE = pow(2, - ((isset($this->_BIG_BLOCK_SIZE))? $this->_adjust2($this->_BIG_BLOCK_SIZE) : 9)); + ((isset($this->_BIG_BLOCK_SIZE))? self::_adjust2($this->_BIG_BLOCK_SIZE) : 9)); $this->_SMALL_BLOCK_SIZE= pow(2, - ((isset($this->_SMALL_BLOCK_SIZE))? $this->_adjust2($this->_SMALL_BLOCK_SIZE): 6)); + ((isset($this->_SMALL_BLOCK_SIZE))? self::_adjust2($this->_SMALL_BLOCK_SIZE): 6)); if (is_resource($filename)) { $this->_FILEH_ = $filename; @@ -119,7 +119,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0); $iSmallLen = 0; $iSBcnt = 0; - for ($i = 0; $i < count($raList); ++$i) { + $iCount = count($raList); + for ($i = 0; $i < $iCount; ++$i) { if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { $raList[$i]->Size = $raList[$i]->_DataLen(); if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) { @@ -151,7 +152,7 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS * @see save() * @return integer */ - public function _adjust2($i2) + private static function _adjust2($i2) { $iWk = log($i2)/log(2); return ($iWk > floor($iWk))? floor($iWk)+1:$iWk; @@ -229,7 +230,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS fwrite($FILE, pack("V", $iAll+$i)); } if ($i < $i1stBdL) { - for ($j = 0; $j < ($i1stBdL-$i); ++$j) { + $jB = $i1stBdL - $i; + for ($j = 0; $j < $jB; ++$j) { fwrite($FILE, (pack("V", -1))); } } @@ -247,7 +249,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS $FILE = $this->_FILEH_; // cycle through PPS's - for ($i = 0; $i < count($raList); ++$i) { + $iCount = count($raList); + for ($i = 0; $i < $iCount; ++$i) { if ($raList[$i]->Type != PHPExcel_Shared_OLE::OLE_PPS_TYPE_DIR) { $raList[$i]->Size = $raList[$i]->_DataLen(); if (($raList[$i]->Size >= PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) || @@ -266,9 +269,7 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS //} if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) { - for ($j = 0; $j < ($this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)); ++$j) { - fwrite($FILE, "\x00"); - } + fwrite($FILE, str_repeat("\x00", $this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE))); } // Set For PPS $raList[$i]->_StartBlock = $iStBlk; @@ -298,7 +299,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS $FILE = $this->_FILEH_; $iSmBlk = 0; - for ($i = 0; $i < count($raList); ++$i) { + $iCount = count($raList); + for ($i = 0; $i < $iCount; ++$i) { // Make SBD, small data string if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { if ($raList[$i]->Size <= 0) { @@ -308,7 +310,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS $iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE) + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0); // Add to SBD - for ($j = 0; $j < ($iSmbCnt-1); ++$j) { + $jB = $iSmbCnt - 1; + for ($j = 0; $j < $jB; ++$j) { fwrite($FILE, pack("V", $j+$iSmBlk+1)); } fwrite($FILE, pack("V", -2)); @@ -323,9 +326,7 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS $sRes .= $raList[$i]->_data; //} if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) { - for ($j = 0; $j < ($this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); ++$j) { - $sRes .= "\x00"; - } + $sRes .= str_repeat("\x00",$this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); } // Set for PPS $raList[$i]->_StartBlock = $iSmBlk; @@ -335,7 +336,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS } $iSbCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE); if ($iSmBlk % $iSbCnt) { - for ($i = 0; $i < ($iSbCnt - ($iSmBlk % $iSbCnt)); ++$i) { + $iB = $iSbCnt - ($iSmBlk % $iSbCnt); + for ($i = 0; $i < $iB; ++$i) { fwrite($FILE, pack("V", -1)); } } @@ -351,16 +353,15 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS public function _savePps(&$raList) { // Save each PPS WK - for ($i = 0; $i < count($raList); ++$i) { + $iC = count($raList); + for ($i = 0; $i < $iC; ++$i) { fwrite($this->_FILEH_, $raList[$i]->_getPpsWk()); } // Adjust for Block $iCnt = count($raList); $iBCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE; if ($iCnt % $iBCnt) { - for ($i = 0; $i < (($iBCnt - ($iCnt % $iBCnt)) * PHPExcel_Shared_OLE::OLE_PPS_SIZE); ++$i) { - fwrite($this->_FILEH_, "\x00"); - } + fwrite($this->_FILEH_, str_repeat("\x00",($iBCnt - ($iCnt % $iBCnt)) * PHPExcel_Shared_OLE::OLE_PPS_SIZE)); } } @@ -426,7 +427,8 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS } // Adjust for Block if (($iAllW + $iBdCnt) % $iBbCnt) { - for ($i = 0; $i < ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); ++$i) { + $iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); + for ($i = 0; $i < $iBlock; ++$i) { fwrite($FILE, pack("V", -1)); } } @@ -443,11 +445,12 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i)); } if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) { - for ($i = 0; $i < (($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1))); ++$i) { + $iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1)); + for ($i = 0; $i < $iB; ++$i) { fwrite($FILE, pack("V", -1)); } } fwrite($FILE, pack("V", -2)); } } - } +} diff --git a/Classes/PHPExcel/Shared/OLERead.php b/Classes/PHPExcel/Shared/OLERead.php index 5c2aa75b..1ef746fb 100644 --- a/Classes/PHPExcel/Shared/OLERead.php +++ b/Classes/PHPExcel/Shared/OLERead.php @@ -81,19 +81,19 @@ class PHPExcel_Shared_OLERead { } // Total number of sectors used for the SAT - $this->numBigBlockDepotBlocks = $this->_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); + $this->numBigBlockDepotBlocks = self::_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); // SecID of the first sector of the directory stream - $this->rootStartBlock = $this->_GetInt4d($this->data, self::ROOT_START_BLOCK_POS); + $this->rootStartBlock = self::_GetInt4d($this->data, self::ROOT_START_BLOCK_POS); // SecID of the first sector of the SSAT (or -2 if not extant) - $this->sbdStartBlock = $this->_GetInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS); + $this->sbdStartBlock = self::_GetInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS); // SecID of the first sector of the MSAT (or -2 if no additional sectors are used) - $this->extensionBlock = $this->_GetInt4d($this->data, self::EXTENSION_BLOCK_POS); + $this->extensionBlock = self::_GetInt4d($this->data, self::EXTENSION_BLOCK_POS); // Total number of sectors used by MSAT - $this->numExtensionBlocks = $this->_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS); + $this->numExtensionBlocks = self::_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS); $bigBlockDepotBlocks = array(); $pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS; @@ -105,7 +105,7 @@ class PHPExcel_Shared_OLERead { } for ($i = 0; $i < $bbdBlocks; ++$i) { - $bigBlockDepotBlocks[$i] = $this->_GetInt4d($this->data, $pos); + $bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos); $pos += 4; } @@ -114,13 +114,13 @@ class PHPExcel_Shared_OLERead { $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1); for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) { - $bigBlockDepotBlocks[$i] = $this->_GetInt4d($this->data, $pos); + $bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos); $pos += 4; } $bbdBlocks += $blocksToRead; if ($bbdBlocks < $this->numBigBlockDepotBlocks) { - $this->extensionBlock = $this->_GetInt4d($this->data, $pos); + $this->extensionBlock = self::_GetInt4d($this->data, $pos); } } @@ -128,11 +128,12 @@ class PHPExcel_Shared_OLERead { $index = 0; $this->bigBlockChain = array(); + $bbs = self::BIG_BLOCK_SIZE / 4; for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) { $pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE; - for ($j = 0 ; $j < self::BIG_BLOCK_SIZE / 4; ++$j) { - $this->bigBlockChain[$index] = $this->_GetInt4d($this->data, $pos); + for ($j = 0 ; $j < $bbs; ++$j) { + $this->bigBlockChain[$index] = self::_GetInt4d($this->data, $pos); $pos += 4 ; ++$index; } @@ -146,8 +147,8 @@ class PHPExcel_Shared_OLERead { while ($sbdBlock != -2) { $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; - for ($j = 0; $j < self::BIG_BLOCK_SIZE / 4; ++$j) { - $this->smallBlockChain[$index] = $this->_GetInt4d($this->data, $pos); + for ($j = 0; $j < $bbs; ++$j) { + $this->smallBlockChain[$index] = self::_GetInt4d($this->data, $pos); $pos += 4; ++$index; } @@ -187,7 +188,6 @@ class PHPExcel_Shared_OLERead { return $streamData; - } else { $numBlocks = $this->props[$this->wrkbook]['size'] / self::BIG_BLOCK_SIZE; if ($this->props[$this->wrkbook]['size'] % self::BIG_BLOCK_SIZE != 0) { @@ -196,7 +196,6 @@ class PHPExcel_Shared_OLERead { if ($numBlocks == 0) return ''; - $streamData = ''; $block = $this->props[$this->wrkbook]['startBlock']; @@ -239,7 +238,6 @@ class PHPExcel_Shared_OLERead { return $streamData; - } else { $numBlocks = $this->props[$this->summaryInformation]['size'] / self::BIG_BLOCK_SIZE; if ($this->props[$this->summaryInformation]['size'] % self::BIG_BLOCK_SIZE != 0) { @@ -248,7 +246,6 @@ class PHPExcel_Shared_OLERead { if ($numBlocks == 0) return ''; - $streamData = ''; $block = $this->props[$this->summaryInformation]['startBlock']; @@ -291,7 +288,6 @@ class PHPExcel_Shared_OLERead { return $streamData; - } else { $numBlocks = $this->props[$this->documentSummaryInformation]['size'] / self::BIG_BLOCK_SIZE; if ($this->props[$this->documentSummaryInformation]['size'] % self::BIG_BLOCK_SIZE != 0) { @@ -300,7 +296,6 @@ class PHPExcel_Shared_OLERead { if ($numBlocks == 0) return ''; - $streamData = ''; $block = $this->props[$this->documentSummaryInformation]['startBlock']; @@ -330,7 +325,7 @@ class PHPExcel_Shared_OLERead { while ($block != -2) { $pos = ($block + 1) * self::BIG_BLOCK_SIZE; - $data = $data . substr($this->data, $pos, self::BIG_BLOCK_SIZE); + $data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); $block = $this->bigBlockChain[$block]; } return $data; @@ -356,16 +351,11 @@ class PHPExcel_Shared_OLERead { // sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook) // sectorID of first sector of the short-stream container stream, if this entry is root entry - $startBlock = $this->_GetInt4d($d, self::START_BLOCK_POS); + $startBlock = self::_GetInt4d($d, self::START_BLOCK_POS); - $size = $this->_GetInt4d($d, self::SIZE_POS); + $size = self::_GetInt4d($d, self::SIZE_POS); - $name = ''; - for ($i = 0; $i < $nameSize ; ++$i) { - $name .= $d[$i]; - } - - $name = str_replace("\x00", "", $name); + $name = str_replace("\x00", "", substr($d,0,$nameSize)); $this->props[] = array ( 'name' => $name, @@ -407,14 +397,19 @@ class PHPExcel_Shared_OLERead { * @param int $pos * @return int */ - private function _GetInt4d($data, $pos) + private static function _GetInt4d($data, $pos) { + // FIX: represent numbers correctly on 64-bit system + // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems - $_or_24 = ord($data[$pos+3]); - if ($_or_24>=128) $_ord_24 = -abs((256-$_or_24) << 24); - else $_ord_24 = ($_or_24&127) << 24; - - return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $_ord_24; + $_or_24 = ord($data[$pos + 3]); + if ($_or_24 >= 128) { + // negative number + $_ord_24 = -abs((256 - $_or_24) << 24); + } else { + $_ord_24 = ($_or_24 & 127) << 24; + } + return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $_ord_24; } } diff --git a/changelog.txt b/changelog.txt index e98b65b9..7102e967 100644 --- a/changelog.txt +++ b/changelog.txt @@ -58,6 +58,7 @@ Fixed in SVN: - Bugfix: (MBaker) Work item 14679 - Formula evaluation fails with Japanese sheet refs - Bugfix: (MBaker) Work item 13559 - PHPExcel_Writer_PDF does not handle cell borders correctly - Bugfix: (MBaker) Work item 14831 - Style : applyFromArray() for 'allborders' not working +- Bugfix: (MBaker) Work item 14837 - Using $this when not in object context in Excel5 Reader - General: (MBaker) Applied patch 6609 - Removes a unnecessary loop through each cell when applying conditional formatting to a range. - General: (MBaker) Applied patch 7169 - Removed spurious PHP end tags (?>) - General: (MBaker) Improved performance (speed) and reduced memory overheads, particularly for the Writers, but across the whole library.