📄 ole.php
字号:
<?php/* vim: set expandtab tabstop=4 shiftwidth=4: */// +----------------------------------------------------------------------+// | PHP Version 4 |// +----------------------------------------------------------------------+// | Copyright (c) 1997-2002 The PHP Group |// +----------------------------------------------------------------------+// | This source file is subject to version 2.02 of the PHP license, |// | that is bundled with this package in the file LICENSE, and is |// | available at through the world-wide-web at |// | http://www.php.net/license/2_02.txt. |// | If you did not receive a copy of the PHP license and are unable to |// | obtain it through the world-wide-web, please send a note to |// | license@php.net so we can mail you a copy immediately. |// +----------------------------------------------------------------------+// | Author: Xavier Noguer <xnoguer@php.net> |// | Based on OLE::Storage_Lite by Kawai, Takanori |// +----------------------------------------------------------------------+//// $Id: OLE.php,v 1.15 2007/12/18 20:59:11 schmidt Exp $/*** Constants for OLE package*/define('OLE_PPS_TYPE_ROOT', 5);define('OLE_PPS_TYPE_DIR', 1);define('OLE_PPS_TYPE_FILE', 2);define('OLE_DATA_SIZE_SMALL', 0x1000);define('OLE_LONG_INT_SIZE', 4);define('OLE_PPS_SIZE', 0x80);require_once 'PEAR.php';/*** Array for storing OLE instances that are accessed from* OLE_ChainedBlockStream::stream_open().* @var array*/$GLOBALS['_OLE_INSTANCES'] = array();/*** OLE package base class.** @category Structures* @package OLE* @author Xavier Noguer <xnoguer@php.net>* @author Christian Schmidt <schmidt@php.net>*/class OLE extends PEAR{ /** * The file handle for reading an OLE container * @var resource */ var $_file_handle; /** * Array of PPS's found on the OLE container * @var array */ var $_list; /** * Root directory of OLE container * @var OLE_PPS_Root */ var $root; /** * Big Block Allocation Table * @var array (blockId => nextBlockId) */ var $bbat; /** * Short Block Allocation Table * @var array (blockId => nextBlockId) */ var $sbat; /** * Size of big blocks. This is usually 512. * @var int number of octets per block. */ var $bigBlockSize; /** * Size of small blocks. This is usually 64. * @var int number of octets per block */ var $smallBlockSize; /** * Creates a new OLE object * @access public */ function OLE() { $this->_list = array(); } /** * Destructor (using PEAR) * Just closes the file handle on the OLE file. * * @access private */ function _OLE() { fclose($this->_file_handle); } /** * Reads an OLE container from the contents of the file given. * * @access public * @param string $file * @return mixed true on success, PEAR_Error on failure */ function read($file) { $fh = @fopen($file, "r"); if (!$fh) { return $this->raiseError("Can't open file $file"); } $this->_file_handle = $fh; $signature = fread($fh, 8); if ("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) { return $this->raiseError("File doesn't seem to be an OLE container."); } fseek($fh, 28); if (fread($fh, 2) != "\xFE\xFF") { // This shouldn't be a problem in practice return $this->raiseError("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)); // Skip UID, revision number and version number fseek($fh, 44); // Number of blocks in Big Block Allocation Table $bbatBlockCount = $this->_readInt4($fh); // Root chain 1st block $directoryFirstBlockId = $this->_readInt4($fh); // Skip unused bytes fseek($fh, 56); // Streams shorter than this are stored using small blocks $this->bigBlockThreshold = $this->_readInt4($fh); // Block id of first sector in Short Block Allocation Table $sbatFirstBlockId = $this->_readInt4($fh); // Number of blocks in Short Block Allocation Table $sbbatBlockCount = $this->_readInt4($fh); // Block id of first sector in Master Block Allocation Table $mbatFirstBlockId = $this->_readInt4($fh); // Number of blocks in Master Block Allocation Table $mbbatBlockCount = $this->_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); } // Read rest of Master Block Allocation Table (if any is left) $pos = $this->_getBlockOffset($mbatFirstBlockId); for ($i = 0; $i < $mbbatBlockCount; $i++) { fseek($fh, $pos); for ($j = 0; $j < $this->bigBlockSize / 4 - 1; $j++) { $mbatBlocks[] = $this->_readInt4($fh); } // Last block id in each block points to next block $pos = $this->_getBlockOffset($this->_readInt4($fh)); } // Read Big Block Allocation Table according to chain specified by // $mbatBlocks for ($i = 0; $i < $bbatBlockCount; $i++) { $pos = $this->_getBlockOffset($mbatBlocks[$i]); fseek($fh, $pos); for ($j = 0 ; $j < $this->bigBlockSize / 4; $j++) { $this->bbat[] = $this->_readInt4($fh); } } // Read short block allocation table (SBAT) $this->sbat = array(); $shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4; $sbatFh = $this->getStream($sbatFirstBlockId); for ($blockId = 0; $blockId < $shortBlockCount; $blockId++) { $this->sbat[$blockId] = $this->_readInt4($sbatFh); } fclose($sbatFh); $this->_readPpsWks($directoryFirstBlockId); return true; } /** * @param int $blockId block id * @return int byte offset from beginning of file * @access private */ function _getBlockOffset($blockId) { return 512 + $blockId * $this->bigBlockSize; } /** * Returns a stream for use with fread() etc. External callers should * use OLE_PPS_File::getStream(). * @param int|PPS $blockIdOrPps block id or PPS * @return resource read-only stream */ function getStream($blockIdOrPps) { include_once 'OLE/ChainedBlockStream.php'; static $isRegistered = false; if (!$isRegistered) { stream_wrapper_register('ole-chainedblockstream', 'OLE_ChainedBlockStream'); $isRegistered = true; } // Store current instance in global array, so that it can be accessed // in OLE_ChainedBlockStream::stream_open(). // Object is removed from self::$instances in OLE_Stream::close(). $GLOBALS['_OLE_INSTANCES'][] = $this; $instanceId = end(array_keys($GLOBALS['_OLE_INSTANCES'])); $path = 'ole-chainedblockstream://oleInstanceId=' . $instanceId; if (is_a($blockIdOrPps, 'OLE_PPS')) { $path .= '&blockId=' . $blockIdOrPps->_StartBlock; $path .= '&size=' . $blockIdOrPps->Size; } else { $path .= '&blockId=' . $blockIdOrPps; } return fopen($path, 'r'); } /** * Reads a signed char. * @param resource $fh file handle * @return int * @access private */ function _readInt1($fh) { list(, $tmp) = unpack("c", fread($fh, 1)); return $tmp; } /** * Reads an unsigned short (2 octets). * @param resource $fh file handle * @return int * @access private */ function _readInt2($fh) { list(, $tmp) = unpack("v", fread($fh, 2)); return $tmp; } /** * Reads an unsigned long (4 octets). * @param resource file handle * @return int * @access private */ function _readInt4($fh) { list(, $tmp) = unpack("V", fread($fh, 4)); return $tmp; } /** * Gets information about all PPS's on the OLE container from the PPS WK's
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -