#23 : Implement Word97 aka MsDoc Reader (PHPCS-PHPMD Fixes)

This commit is contained in:
Progi1984 2014-08-16 12:33:37 +02:00
parent e561d54661
commit 4ade9c3c6e
5 changed files with 223 additions and 186 deletions

View File

@ -2,6 +2,9 @@
/** /**
* Footer file * Footer file
*/ */
if (CLI) {
return;
}
?> ?>
</div> </div>
<script src="bootstrap/js/jquery.min.js"></script> <script src="bootstrap/js/jquery.min.js"></script>

View File

@ -48,20 +48,46 @@ abstract class IOFactory
return self::createObject('Reader', $name); return self::createObject('Reader', $name);
} }
$fqName = "PhpOffice\\PhpWord\\Reader\\{$name}"; /**
return new $fqName(); * Create new object
*
* @param string $type
* @param string $name
* @param \PhpOffice\PhpWord\PhpWord $phpWord
* @return \PhpOffice\PhpWord\Writer\WriterInterface|\PhpOffice\PhpWord\Reader\ReaderInterface
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
private static function createObject($type, $name, $phpWord = null)
{
$class = "PhpOffice\\PhpWord\\{$type}\\{$name}";
if (class_exists($class) && self::isConcreteClass($class)) {
return new $class($phpWord);
} else {
throw new Exception("\"{$name}\" is not a valid {$type}.");
}
} }
/** /**
* Loads PhpWord from file * Loads PhpWord from file
* *
* @param string $filename The name of the file * @param string $filename The name of the file
* @param string $readerName * @param string $readerName
* @return PhpWord * @return \PhpOffice\PhpWord\PhpWord $phpWord
*/ */
public static function load($filename, $readerName = 'Word2007') public static function load($filename, $readerName = 'Word2007')
{ {
/** @var \PhpOffice\PhpWord\Reader\ReaderInterface $reader */
$reader = self::createReader($readerName); $reader = self::createReader($readerName);
return $reader->load($filename); return $reader->load($filename);
} }
/**
* Check if it's a concrete class (not abstract nor interface)
*
* @param string $class
* @return bool
*/
private static function isConcreteClass($class)
{
$reflection = new \ReflectionClass($class);
return !$reflection->isAbstract() && !$reflection->isInterface();
}
} }

View File

@ -144,11 +144,13 @@ class MsDoc extends AbstractReader implements ReaderInterface
$this->_DocumentSummaryInformation = $ole->getStream($ole->documentSummaryInformation); $this->_DocumentSummaryInformation = $ole->getStream($ole->documentSummaryInformation);
} }
private function getNumInLcb($lcb, $iSize){ private function getNumInLcb($lcb, $iSize)
{
return ($lcb - 4) / (4 + $iSize); return ($lcb - 4) / (4 + $iSize);
} }
private function getArrayCP($data, $posMem, $iNum){ private function getArrayCP($data, $posMem, $iNum)
{
$arrayCP = array(); $arrayCP = array();
for ($inc = 0; $inc < $iNum; $inc++) { for ($inc = 0; $inc < $iNum; $inc++) {
$arrayCP[$inc] = self::getInt4d($data, $posMem); $arrayCP[$inc] = self::getInt4d($data, $posMem);
@ -1111,7 +1113,8 @@ class MsDoc extends AbstractReader implements ReaderInterface
* Section and information about them * Section and information about them
* @link : http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx * @link : http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx
*/ */
private function readRecordPlcfSed(){ private function readRecordPlcfSed()
{
$posMem = $this->arrayFib['fcPlcfSed']; $posMem = $this->arrayFib['fcPlcfSed'];
// PlcfSed // PlcfSed
// PlcfSed : aCP // PlcfSed : aCP
@ -1139,7 +1142,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
$posMem += 4; $posMem += 4;
} }
foreach($aSed as $keySed => $offsetSed){ foreach ($aSed as $offsetSed) {
// Sepx : http://msdn.microsoft.com/en-us/library/dd921348%28v=office.12%29.aspx // Sepx : http://msdn.microsoft.com/en-us/library/dd921348%28v=office.12%29.aspx
$cb = self::getInt2d($this->dataWorkDocument, $offsetSed); $cb = self::getInt2d($this->dataWorkDocument, $offsetSed);
$offsetSed += 2; $offsetSed += 2;
@ -1214,14 +1217,15 @@ class MsDoc extends AbstractReader implements ReaderInterface
* Paragraph and information about them * Paragraph and information about them
* @link http://msdn.microsoft.com/en-us/library/dd908569%28v=office.12%29.aspx * @link http://msdn.microsoft.com/en-us/library/dd908569%28v=office.12%29.aspx
*/ */
private function readRecordPlcfBtePapx(){ private function readRecordPlcfBtePapx()
{
$posMem = $this->arrayFib['fcPlcfBtePapx']; $posMem = $this->arrayFib['fcPlcfBtePapx'];
$num = $this->getNumInLcb($this->arrayFib['lcbPlcfBtePapx'], 4); $num = $this->getNumInLcb($this->arrayFib['lcbPlcfBtePapx'], 4);
$posMem += 4 * ($num + 1); $posMem += 4 * ($num + 1);
$plcfBtePapx_aPnBtePapx = $this->getArrayCP($this->data1Table, $posMem, $num); $arrAPnBtePapx = $this->getArrayCP($this->data1Table, $posMem, $num);
$posMem += 4 * $num; $posMem += 4 * $num;
foreach($plcfBtePapx_aPnBtePapx as $aPnBtePapx){ foreach ($arrAPnBtePapx as $aPnBtePapx) {
$offsetBase = $aPnBtePapx * 512; $offsetBase = $aPnBtePapx * 512;
$offset = $offsetBase; $offset = $offsetBase;
@ -1242,7 +1246,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
$offset += 12; $offset += 12;
} }
foreach ($arrayRGFC as $key => $rgFc) { foreach (array_keys($arrayRGFC) as $key) {
if (!isset($arrayRGFC[$key + 1])) { if (!isset($arrayRGFC[$key + 1])) {
break; break;
} }
@ -1354,7 +1358,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
} }
break; break;
case 0x7: case 0x7:
$operand = self::_GetInt3d($this->dataWorkDocument, $offset); $operand = self::getInt3d($this->dataWorkDocument, $offset);
$offset += 3; $offset += 3;
$cb -= 3; $cb -= 3;
print_r('$operand : 0x'.dechex($operand).PHP_EOL); print_r('$operand : 0x'.dechex($operand).PHP_EOL);
@ -1425,12 +1429,13 @@ class MsDoc extends AbstractReader implements ReaderInterface
* Character formatting properties to text in a document * Character formatting properties to text in a document
* @link http://msdn.microsoft.com/en-us/library/dd907108%28v=office.12%29.aspx * @link http://msdn.microsoft.com/en-us/library/dd907108%28v=office.12%29.aspx
*/ */
private function readRecordPlcfBteChpx(){ private function readRecordPlcfBteChpx()
{
$posMem = $this->arrayFib['fcPlcfBteChpx']; $posMem = $this->arrayFib['fcPlcfBteChpx'];
$num = $this->getNumInLcb($this->arrayFib['lcbPlcfBteChpx'], 4); $num = $this->getNumInLcb($this->arrayFib['lcbPlcfBteChpx'], 4);
$PlcBteChpx_aPnBteChpx = array(); $aPnBteChpx = array();
for ($inc = 0; $inc <= $num; $inc++) { for ($inc = 0; $inc <= $num; $inc++) {
$PlcBteChpx_aPnBteChpx[$inc] = self::getInt4d($this->data1Table, $posMem); $aPnBteChpx[$inc] = self::getInt4d($this->data1Table, $posMem);
$posMem += 4; $posMem += 4;
} }
$PnFkpChpx = self::getInt4d($this->data1Table, $posMem); $PnFkpChpx = self::getInt4d($this->data1Table, $posMem);
@ -1537,7 +1542,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
} }
break; break;
case 0x7: case 0x7:
$operand = self::_GetInt3d($data, $pos); $operand = self::getInt3d($data, $pos);
$length = 3; $length = 3;
break; break;
default: default:
@ -1556,7 +1561,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
* @return \stdClass * @return \stdClass
* @link http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx * @link http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx
*/ */
private function readPrl($data, $pos, $cb) private function readPrl($data, $pos, $cbNum)
{ {
$posStart = $pos; $posStart = $pos;
$oStylePrl = new \stdClass(); $oStylePrl = new \stdClass();
@ -1573,11 +1578,11 @@ class MsDoc extends AbstractReader implements ReaderInterface
$sprm = self::getInt2d($data, $pos); $sprm = self::getInt2d($data, $pos);
$oSprm = $this->readSprm($sprm); $oSprm = $this->readSprm($sprm);
$pos += 2; $pos += 2;
$cb -= 2; $cbNum -= 2;
$arrayReturn = $this->readSprmSpra($data, $pos, $oSprm); $arrayReturn = $this->readSprmSpra($data, $pos, $oSprm);
$pos += $arrayReturn['length']; $pos += $arrayReturn['length'];
$cb -= $arrayReturn['length']; $cbNum -= $arrayReturn['length'];
$operand = $arrayReturn['operand']; $operand = $arrayReturn['operand'];
switch(dechex($oSprm->sgc)) { switch(dechex($oSprm->sgc)) {
@ -1829,7 +1834,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
case 0x66: case 0x66:
// $operand = self::getInt2d($data, $pos); // $operand = self::getInt2d($data, $pos);
$pos += 2; $pos += 2;
$cb -= 2; $cbNum -= 2;
// $ipat = ($operand >> 0) && bindec('111111'); // $ipat = ($operand >> 0) && bindec('111111');
// $icoBack = ($operand >> 6) && bindec('11111'); // $icoBack = ($operand >> 6) && bindec('11111');
// $icoFore = ($operand >> 11) && bindec('11111'); // $icoFore = ($operand >> 11) && bindec('11111');
@ -1845,7 +1850,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
$pos += 1; $pos += 1;
$pos += 1; $pos += 1;
$oStylePrl->styleFont['color'] = $red.$green.$blue; $oStylePrl->styleFont['color'] = $red.$green.$blue;
$cb -= 4; $cbNum -= 4;
break; break;
default: default:
// print_r('@todo Character : 0x'.dechex($oSprm->isPmd)); // print_r('@todo Character : 0x'.dechex($oSprm->isPmd));
@ -1919,7 +1924,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
case 0x05: case 0x05:
break; break;
} }
} while($cb > 0); } while ($cbNum > 0);
if (!is_null($sprmCPicLocation)) { if (!is_null($sprmCPicLocation)) {
if (!is_null($sprmCFData) && $sprmCFData == 0x01) { if (!is_null($sprmCFData) && $sprmCFData == 0x01) {
@ -2013,7 +2018,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
// PICF : cbHeader // PICF : cbHeader
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : mfpf : mm // PICF : mfpf : mm
$mfpf_mm = self::getInt2d($this->dataData, $sprmCPicLocation); $mfpfMm = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : mfpf : xExt // PICF : mfpf : xExt
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
@ -2030,28 +2035,28 @@ class MsDoc extends AbstractReader implements ReaderInterface
// PICF : innerHeader : padding2 // PICF : innerHeader : padding2
$sprmCPicLocation += 4; $sprmCPicLocation += 4;
// PICF : picmid : dxaGoal // PICF : picmid : dxaGoal
$picmid_dxaGoal = self::getInt2d($this->dataData, $sprmCPicLocation); $picmidDxaGoal = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : picmid : dyaGoal // PICF : picmid : dyaGoal
$picmid_dyaGoal = self::getInt2d($this->dataData, $sprmCPicLocation); $picmidDyaGoal = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : picmid : mx // PICF : picmid : mx
$picmid_mx = self::getInt2d($this->dataData, $sprmCPicLocation); $picmidMx = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : picmid : my // PICF : picmid : my
$picmid_my = self::getInt2d($this->dataData, $sprmCPicLocation); $picmidMy = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : picmid : dxaReserved1 // PICF : picmid : dxaReserved1
$picmid_dxaCropLeft = self::getInt2d($this->dataData, $sprmCPicLocation); $picmidDxaCropLeft = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : picmid : dyaReserved1 // PICF : picmid : dyaReserved1
$picmid_dxaCropTop = self::getInt2d($this->dataData, $sprmCPicLocation); $picmidDxaCropTop = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : picmid : dxaReserved2 // PICF : picmid : dxaReserved2
$picmid_dxaCropRight = self::getInt2d($this->dataData, $sprmCPicLocation); $picmidDxaCropRight = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : picmid : dyaReserved2 // PICF : picmid : dyaReserved2
$picmid_dxaCropBottom = self::getInt2d($this->dataData, $sprmCPicLocation); $picmidDxaCropBottom = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
// PICF : picmid : fReserved // PICF : picmid : fReserved
$sprmCPicLocation += 1; $sprmCPicLocation += 1;
@ -2072,7 +2077,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
// PICF : cProps // PICF : cProps
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
if ($mfpf_mm == 0x0066) { if ($mfpfMm == 0x0066) {
// cchPicName // cchPicName
$cchPicName = self::getInt1d($this->dataData, $sprmCPicLocation); $cchPicName = self::getInt1d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 1; $sprmCPicLocation += 1;
@ -2156,16 +2161,16 @@ class MsDoc extends AbstractReader implements ReaderInterface
$oStylePrl->image['data'] = substr($this->dataData, $sprmCPicLocation, $embeddedBlipRH['recLen']); $oStylePrl->image['data'] = substr($this->dataData, $sprmCPicLocation, $embeddedBlipRH['recLen']);
$oStylePrl->image['format'] = 'jpg'; $oStylePrl->image['format'] = 'jpg';
// Image Size // Image Size
$iCropWidth = $picmid_dxaGoal - ($picmid_dxaCropLeft + $picmid_dxaCropRight); $iCropWidth = $picmidDxaGoal - ($picmidDxaCropLeft + $picmidDxaCropRight);
$iCropHeight = $picmid_dyaGoal - ($picmid_dxaCropTop + $picmid_dxaCropBottom); $iCropHeight = $picmidDyaGoal - ($picmidDxaCropTop + $picmidDxaCropBottom);
if (!$iCropWidth) { if (!$iCropWidth) {
$iCropWidth = 1; $iCropWidth = 1;
} }
if (!$iCropHeight) { if (!$iCropHeight) {
$iCropHeight = 1; $iCropHeight = 1;
} }
$oStylePrl->image['width'] = Drawing::twipsToPixels($iCropWidth * $picmid_mx / 1000); $oStylePrl->image['width'] = Drawing::twipsToPixels($iCropWidth * $picmidMx / 1000);
$oStylePrl->image['height'] = Drawing::twipsToPixels($iCropHeight * $picmid_my / 1000); $oStylePrl->image['height'] = Drawing::twipsToPixels($iCropHeight * $picmidMy / 1000);
$sprmCPicLocation += $embeddedBlipRH['recLen']; $sprmCPicLocation += $embeddedBlipRH['recLen'];
break; break;
@ -2211,7 +2216,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
$sHYPERLINK = ''; $sHYPERLINK = '';
foreach ($this->arrayParagraphs as $itmParagraph) { foreach ($this->arrayParagraphs as $itmParagraph) {
$textPara = $itmParagraph; $textPara = $itmParagraph;
foreach ($this->arrayCharacters as $keyCharacters => $oCharacters) { foreach ($this->arrayCharacters as $oCharacters) {
$subText = substr($textPara, $oCharacters->pos_start, $oCharacters->pos_len); $subText = substr($textPara, $oCharacters->pos_start, $oCharacters->pos_len);
$subText = str_replace(chr(13), PHP_EOL, $subText); $subText = str_replace(chr(13), PHP_EOL, $subText);
$arrayText = explode(PHP_EOL, $subText); $arrayText = explode(PHP_EOL, $subText);
@ -2307,7 +2312,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
* @param int $pos * @param int $pos
* @return int * @return int
*/ */
public static function _GetInt3d($data, $pos) public static function getInt3d($data, $pos)
{ {
return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16); return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16);
} }
@ -2324,13 +2329,13 @@ class MsDoc extends AbstractReader implements ReaderInterface
// FIX: represent numbers correctly on 64-bit system // FIX: represent numbers correctly on 64-bit system
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 // 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 // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
$_or_24 = ord($data[$pos + 3]); $or24 = ord($data[$pos + 3]);
if ($_or_24 >= 128) { if ($or24 >= 128) {
// negative number // negative number
$_ord_24 = -abs((256 - $_or_24) << 24); $ord24 = -abs((256 - $or24) << 24);
} else { } else {
$_ord_24 = ($_or_24 & 127) << 24; $ord24 = ($or24 & 127) << 24;
} }
return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $_ord_24; return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $ord24;
} }
} }

View File

@ -31,7 +31,7 @@ class Drawing
* @param integer $pValue Value in EMU * @param integer $pValue Value in EMU
* @return integer Value in pixels * @return integer Value in pixels
*/ */
public static function EMUToPixels($pValue = 0) public static function emuToPixels($pValue = 0)
{ {
if ($pValue != 0) { if ($pValue != 0) {
return round($pValue / 9525); return round($pValue / 9525);
@ -201,17 +201,17 @@ class Drawing
} }
if (strlen($pValue) == 6) { if (strlen($pValue) == 6) {
list($color_R, $color_G, $color_B) = array($pValue[0] . $pValue[1], $pValue[2] . $pValue[3], $pValue[4] . $pValue[5]); list($colorR, $colorG, $colorB) = array($pValue[0] . $pValue[1], $pValue[2] . $pValue[3], $pValue[4] . $pValue[5]);
} elseif (strlen($pValue) == 3) { } elseif (strlen($pValue) == 3) {
list($color_R, $color_G, $color_B) = array($pValue[0] . $pValue[0], $pValue[1] . $pValue[1], $pValue[2] . $pValue[2]); list($colorR, $colorG, $colorB) = array($pValue[0] . $pValue[0], $pValue[1] . $pValue[1], $pValue[2] . $pValue[2]);
} else { } else {
return false; return false;
} }
$color_R = hexdec($color_R); $colorR = hexdec($colorR);
$color_G = hexdec($color_G); $colorG = hexdec($colorG);
$color_B = hexdec($color_B); $colorB = hexdec($colorB);
return array($color_R, $color_G, $color_B); return array($colorR, $colorG, $colorB);
} }
} }

View File

@ -15,7 +15,8 @@ use PhpOffice\PhpWord\Exception\Exception;
defined('IDENTIFIER_OLE') || defined('IDENTIFIER_OLE') ||
define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1)); define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1));
class OLERead { class OLERead
{
private $data = ''; private $data = '';
// OLE identifier // OLE identifier
@ -54,7 +55,7 @@ class OLERead {
public $wrkData = null; public $wrkData = null;
public $wrkObjectPool = null; public $wrkObjectPool = null;
public $summaryInformation = null; public $summaryInformation = null;
public $documentSummaryInformation = null; public $docSummaryInformation = null;
/** /**
@ -72,7 +73,7 @@ class OLERead {
// Get the file identifier // Get the file identifier
// Don't bother reading the whole file until we know it's a valid OLE file // Don't bother reading the whole file until we know it's a valid OLE file
$this->data = file_get_contents($sFileName, FALSE, NULL, 0, 8); $this->data = file_get_contents($sFileName, false, null, 0, 8);
// Check OLE identifier // Check OLE identifier
if ($this->data != self::IDENTIFIER_OLE) { if ($this->data != self::IDENTIFIER_OLE) {
@ -83,19 +84,19 @@ class OLERead {
$this->data = file_get_contents($sFileName); $this->data = file_get_contents($sFileName);
// Total number of sectors used for the SAT // Total number of sectors used for the SAT
$this->numBigBlockDepotBlocks = self::_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 // SecID of the first sector of the directory stream
$this->rootStartBlock = self::_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) // SecID of the first sector of the SSAT (or -2 if not extant)
$this->sbdStartBlock = self::_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) // SecID of the first sector of the MSAT (or -2 if no additional sectors are used)
$this->extensionBlock = self::_GetInt4d($this->data, self::EXTENSION_BLOCK_POS); $this->extensionBlock = self::getInt4d($this->data, self::EXTENSION_BLOCK_POS);
// Total number of sectors used by MSAT // Total number of sectors used by MSAT
$this->numExtensionBlocks = self::_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS); $this->numExtensionBlocks = self::getInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS);
$bigBlockDepotBlocks = array(); $bigBlockDepotBlocks = array();
$pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS; $pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS;
@ -107,7 +108,7 @@ class OLERead {
} }
for ($i = 0; $i < $bbdBlocks; ++$i) { for ($i = 0; $i < $bbdBlocks; ++$i) {
$bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos); $bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos);
$pos += 4; $pos += 4;
} }
@ -116,13 +117,13 @@ class OLERead {
$blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1); $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1);
for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) { for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) {
$bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos); $bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos);
$pos += 4; $pos += 4;
} }
$bbdBlocks += $blocksToRead; $bbdBlocks += $blocksToRead;
if ($bbdBlocks < $this->numBigBlockDepotBlocks) { if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
$this->extensionBlock = self::_GetInt4d($this->data, $pos); $this->extensionBlock = self::getInt4d($this->data, $pos);
} }
} }
@ -145,14 +146,14 @@ class OLERead {
$this->smallBlockChain .= substr($this->data, $pos, 4*$bbs); $this->smallBlockChain .= substr($this->data, $pos, 4*$bbs);
$pos += 4*$bbs; $pos += 4*$bbs;
$sbdBlock = self::_GetInt4d($this->bigBlockChain, $sbdBlock*4); $sbdBlock = self::getInt4d($this->bigBlockChain, $sbdBlock*4);
} }
// read the directory stream // read the directory stream
$block = $this->rootStartBlock; $block = $this->rootStartBlock;
$this->entry = $this->_readData($block); $this->entry = $this->readData($block);
$this->_readPropertySets(); $this->readPropertySets();
} }
/** /**
@ -162,14 +163,14 @@ class OLERead {
*/ */
public function getStream($stream) public function getStream($stream)
{ {
if ($stream === NULL) { if ($stream === null) {
return null; return null;
} }
$streamData = ''; $streamData = '';
if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) { if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) {
$rootdata = $this->_readData($this->props[$this->rootentry]['startBlock']); $rootdata = $this->readData($this->props[$this->rootentry]['startBlock']);
$block = $this->props[$stream]['startBlock']; $block = $this->props[$stream]['startBlock'];
@ -177,7 +178,7 @@ class OLERead {
$pos = $block * self::SMALL_BLOCK_SIZE; $pos = $block * self::SMALL_BLOCK_SIZE;
$streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE); $streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE);
$block = self::_GetInt4d($this->smallBlockChain, $block*4); $block = self::getInt4d($this->smallBlockChain, $block*4);
} }
return $streamData; return $streamData;
@ -187,14 +188,16 @@ class OLERead {
++$numBlocks; ++$numBlocks;
} }
if ($numBlocks == 0) return ''; if ($numBlocks == 0) {
return '';
}
$block = $this->props[$stream]['startBlock']; $block = $this->props[$stream]['startBlock'];
while ($block != -2) { while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE; $pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); $streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = self::_GetInt4d($this->bigBlockChain, $block*4); $block = self::getInt4d($this->bigBlockChain, $block*4);
} }
return $streamData; return $streamData;
@ -204,18 +207,18 @@ class OLERead {
/** /**
* Read a standard stream (by joining sectors using information from SAT) * Read a standard stream (by joining sectors using information from SAT)
* *
* @param int $bl Sector ID where the stream starts * @param int $blSectorId Sector ID where the stream starts
* @return string Data for standard stream * @return string Data for standard stream
*/ */
private function _readData($bl) private function readData($blSectorId)
{ {
$block = $bl; $block = $blSectorId;
$data = ''; $data = '';
while ($block != -2) { while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE; $pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); $data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = self::_GetInt4d($this->bigBlockChain, $block*4); $block = self::getInt4d($this->bigBlockChain, $block*4);
} }
return $data; return $data;
} }
@ -223,28 +226,29 @@ class OLERead {
/** /**
* Read entries in the directory stream. * Read entries in the directory stream.
*/ */
private function _readPropertySets() { private function readPropertySets()
{
$offset = 0; $offset = 0;
// loop through entires, each entry is 128 bytes // loop through entires, each entry is 128 bytes
$entryLen = strlen($this->entry); $entryLen = strlen($this->entry);
while ($offset < $entryLen) { while ($offset < $entryLen) {
// entry data (128 bytes) // entry data (128 bytes)
$d = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE); $data = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE);
// size in bytes of name // size in bytes of name
$nameSize = ord($d[self::SIZE_OF_NAME_POS]) | (ord($d[self::SIZE_OF_NAME_POS+1]) << 8); $nameSize = ord($data[self::SIZE_OF_NAME_POS]) | (ord($data[self::SIZE_OF_NAME_POS+1]) << 8);
// type of entry // type of entry
$type = ord($d[self::TYPE_POS]); $type = ord($data[self::TYPE_POS]);
// sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook) // 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 // sectorID of first sector of the short-stream container stream, if this entry is root entry
$startBlock = self::_GetInt4d($d, self::START_BLOCK_POS); $startBlock = self::getInt4d($data, self::START_BLOCK_POS);
$size = self::_GetInt4d($d, self::SIZE_POS); $size = self::getInt4d($data, self::SIZE_POS);
$name = str_replace("\x00", "", substr($d,0,$nameSize)); $name = str_replace("\x00", "", substr($data, 0, $nameSize));
$this->props[] = array ( $this->props[] = array (
@ -260,11 +264,11 @@ class OLERead {
// print_r($upName.PHP_EOL); // print_r($upName.PHP_EOL);
if (($upName === 'WORDDOCUMENT')) { if (($upName === 'WORDDOCUMENT')) {
$this->wrkdocument = count($this->props) - 1; $this->wrkdocument = count($this->props) - 1;
} elseif (($upName === '1TABLE')) { } elseif ($upName === '1TABLE') {
$this->wrk1Table = count($this->props) - 1; $this->wrk1Table = count($this->props) - 1;
} elseif (($upName === 'DATA')) { } elseif ($upName === 'DATA') {
$this->wrkData = count($this->props) - 1; $this->wrkData = count($this->props) - 1;
} elseif (($upName === 'OBJECTPOOL')) { } elseif ($upName === 'OBJECTPOOL') {
$this->wrkObjectPoolelseif = count($this->props) - 1; $this->wrkObjectPoolelseif = count($this->props) - 1;
} elseif ($upName === 'ROOT ENTRY' || $upName === 'R') { } elseif ($upName === 'ROOT ENTRY' || $upName === 'R') {
$this->rootentry = count($this->props) - 1; $this->rootentry = count($this->props) - 1;
@ -277,7 +281,7 @@ class OLERead {
// Additional Document Summary information // Additional Document Summary information
if ($name == chr(5) . 'DocumentSummaryInformation') { if ($name == chr(5) . 'DocumentSummaryInformation') {
$this->documentSummaryInformation = count($this->props) - 1; $this->docSummaryInformation = count($this->props) - 1;
} }
$offset += self::PROPERTY_STORAGE_BLOCK_SIZE; $offset += self::PROPERTY_STORAGE_BLOCK_SIZE;
@ -292,19 +296,18 @@ class OLERead {
* @param int $pos * @param int $pos
* @return int * @return int
*/ */
private static function _GetInt4d($data, $pos) private static function getInt4d($data, $pos)
{ {
// FIX: represent numbers correctly on 64-bit system // FIX: represent numbers correctly on 64-bit system
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 // 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 // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
$_or_24 = ord($data[$pos + 3]); $or24 = ord($data[$pos + 3]);
if ($_or_24 >= 128) { if ($or24 >= 128) {
// negative number // negative number
$_ord_24 = -abs((256 - $_or_24) << 24); $ord24 = -abs((256 - $or24) << 24);
} else { } else {
$_ord_24 = ($_or_24 & 127) << 24; $ord24 = ($or24 & 127) << 24;
} }
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $_ord_24; return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $ord24;
} }
} }