Added PHP files needed to read XLS files. refs #1249
Showing
2 changed files
with
1359 additions
and
0 deletions
com/ExcelReader/oleread.inc
0 → 100755
| 1 | <?php | ||
| 2 | namespace Tz\Wordpress\Tools\ExcelReader; | ||
| 3 | |||
| 4 | define('NUM_BIG_BLOCK_DEPOT_BLOCKS_POS', 0x2c); | ||
| 5 | define('SMALL_BLOCK_DEPOT_BLOCK_POS', 0x3c); | ||
| 6 | define('ROOT_START_BLOCK_POS', 0x30); | ||
| 7 | define('BIG_BLOCK_SIZE', 0x200); | ||
| 8 | define('SMALL_BLOCK_SIZE', 0x40); | ||
| 9 | define('EXTENSION_BLOCK_POS', 0x44); | ||
| 10 | define('NUM_EXTENSION_BLOCK_POS', 0x48); | ||
| 11 | define('PROPERTY_STORAGE_BLOCK_SIZE', 0x80); | ||
| 12 | define('BIG_BLOCK_DEPOT_BLOCKS_POS', 0x4c); | ||
| 13 | define('SMALL_BLOCK_THRESHOLD', 0x1000); | ||
| 14 | // property storage offsets | ||
| 15 | define('SIZE_OF_NAME_POS', 0x40); | ||
| 16 | define('TYPE_POS', 0x42); | ||
| 17 | define('START_BLOCK_POS', 0x74); | ||
| 18 | define('SIZE_POS', 0x78); | ||
| 19 | define('IDENTIFIER_OLE', pack("CCCCCCCC",0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1)); | ||
| 20 | |||
| 21 | //echo 'ROOT_START_BLOCK_POS = '.ROOT_START_BLOCK_POS."\n"; | ||
| 22 | |||
| 23 | //echo bin2hex($data[ROOT_START_BLOCK_POS])."\n"; | ||
| 24 | //echo "a="; | ||
| 25 | //echo $data[ROOT_START_BLOCK_POS]; | ||
| 26 | //function log | ||
| 27 | |||
| 28 | function GetInt4d($data, $pos) | ||
| 29 | { | ||
| 30 | $value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24); | ||
| 31 | if ($value>=4294967294) | ||
| 32 | { | ||
| 33 | $value=-2; | ||
| 34 | } | ||
| 35 | return $value; | ||
| 36 | } | ||
| 37 | |||
| 38 | |||
| 39 | class OLERead { | ||
| 40 | var $data = ''; | ||
| 41 | |||
| 42 | |||
| 43 | function OLERead(){ | ||
| 44 | |||
| 45 | |||
| 46 | } | ||
| 47 | |||
| 48 | function read($sFileName){ | ||
| 49 | |||
| 50 | // check if file exist and is readable (Darko Miljanovic) | ||
| 51 | if(!is_readable($sFileName)) { | ||
| 52 | $this->error = 1; | ||
| 53 | return false; | ||
| 54 | } | ||
| 55 | |||
| 56 | $this->data = @file_get_contents($sFileName); | ||
| 57 | if (!$this->data) { | ||
| 58 | $this->error = 1; | ||
| 59 | return false; | ||
| 60 | } | ||
| 61 | //echo IDENTIFIER_OLE; | ||
| 62 | //echo 'start'; | ||
| 63 | if (substr($this->data, 0, 8) != IDENTIFIER_OLE) { | ||
| 64 | $this->error = 1; | ||
| 65 | return false; | ||
| 66 | } | ||
| 67 | $this->numBigBlockDepotBlocks = GetInt4d($this->data, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); | ||
| 68 | $this->sbdStartBlock = GetInt4d($this->data, SMALL_BLOCK_DEPOT_BLOCK_POS); | ||
| 69 | $this->rootStartBlock = GetInt4d($this->data, ROOT_START_BLOCK_POS); | ||
| 70 | $this->extensionBlock = GetInt4d($this->data, EXTENSION_BLOCK_POS); | ||
| 71 | $this->numExtensionBlocks = GetInt4d($this->data, NUM_EXTENSION_BLOCK_POS); | ||
| 72 | |||
| 73 | /* | ||
| 74 | echo $this->numBigBlockDepotBlocks." "; | ||
| 75 | echo $this->sbdStartBlock." "; | ||
| 76 | echo $this->rootStartBlock." "; | ||
| 77 | echo $this->extensionBlock." "; | ||
| 78 | echo $this->numExtensionBlocks." "; | ||
| 79 | */ | ||
| 80 | //echo "sbdStartBlock = $this->sbdStartBlock\n"; | ||
| 81 | $bigBlockDepotBlocks = array(); | ||
| 82 | $pos = BIG_BLOCK_DEPOT_BLOCKS_POS; | ||
| 83 | // echo "pos = $pos"; | ||
| 84 | $bbdBlocks = $this->numBigBlockDepotBlocks; | ||
| 85 | |||
| 86 | if ($this->numExtensionBlocks != 0) { | ||
| 87 | $bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4; | ||
| 88 | } | ||
| 89 | |||
| 90 | for ($i = 0; $i < $bbdBlocks; $i++) { | ||
| 91 | $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos); | ||
| 92 | $pos += 4; | ||
| 93 | } | ||
| 94 | |||
| 95 | |||
| 96 | for ($j = 0; $j < $this->numExtensionBlocks; $j++) { | ||
| 97 | $pos = ($this->extensionBlock + 1) * BIG_BLOCK_SIZE; | ||
| 98 | $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, BIG_BLOCK_SIZE / 4 - 1); | ||
| 99 | |||
| 100 | for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; $i++) { | ||
| 101 | $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos); | ||
| 102 | $pos += 4; | ||
| 103 | } | ||
| 104 | |||
| 105 | $bbdBlocks += $blocksToRead; | ||
| 106 | if ($bbdBlocks < $this->numBigBlockDepotBlocks) { | ||
| 107 | $this->extensionBlock = GetInt4d($this->data, $pos); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | // var_dump($bigBlockDepotBlocks); | ||
| 112 | |||
| 113 | // readBigBlockDepot | ||
| 114 | $pos = 0; | ||
| 115 | $index = 0; | ||
| 116 | $this->bigBlockChain = array(); | ||
| 117 | |||
| 118 | for ($i = 0; $i < $this->numBigBlockDepotBlocks; $i++) { | ||
| 119 | $pos = ($bigBlockDepotBlocks[$i] + 1) * BIG_BLOCK_SIZE; | ||
| 120 | //echo "pos = $pos"; | ||
| 121 | for ($j = 0 ; $j < BIG_BLOCK_SIZE / 4; $j++) { | ||
| 122 | $this->bigBlockChain[$index] = GetInt4d($this->data, $pos); | ||
| 123 | $pos += 4 ; | ||
| 124 | $index++; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | //var_dump($this->bigBlockChain); | ||
| 129 | //echo '=====2'; | ||
| 130 | // readSmallBlockDepot(); | ||
| 131 | $pos = 0; | ||
| 132 | $index = 0; | ||
| 133 | $sbdBlock = $this->sbdStartBlock; | ||
| 134 | $this->smallBlockChain = array(); | ||
| 135 | |||
| 136 | while ($sbdBlock != -2) { | ||
| 137 | |||
| 138 | $pos = ($sbdBlock + 1) * BIG_BLOCK_SIZE; | ||
| 139 | |||
| 140 | for ($j = 0; $j < BIG_BLOCK_SIZE / 4; $j++) { | ||
| 141 | $this->smallBlockChain[$index] = GetInt4d($this->data, $pos); | ||
| 142 | $pos += 4; | ||
| 143 | $index++; | ||
| 144 | } | ||
| 145 | |||
| 146 | $sbdBlock = $this->bigBlockChain[$sbdBlock]; | ||
| 147 | } | ||
| 148 | |||
| 149 | |||
| 150 | // readData(rootStartBlock) | ||
| 151 | $block = $this->rootStartBlock; | ||
| 152 | $pos = 0; | ||
| 153 | $this->entry = $this->__readData($block); | ||
| 154 | |||
| 155 | /* | ||
| 156 | while ($block != -2) { | ||
| 157 | $pos = ($block + 1) * BIG_BLOCK_SIZE; | ||
| 158 | $this->entry = $this->entry.substr($this->data, $pos, BIG_BLOCK_SIZE); | ||
| 159 | $block = $this->bigBlockChain[$block]; | ||
| 160 | } | ||
| 161 | */ | ||
| 162 | //echo '==='.$this->entry."==="; | ||
| 163 | $this->__readPropertySets(); | ||
| 164 | |||
| 165 | } | ||
| 166 | |||
| 167 | function __readData($bl) { | ||
| 168 | $block = $bl; | ||
| 169 | $pos = 0; | ||
| 170 | $data = ''; | ||
| 171 | |||
| 172 | while ($block != -2) { | ||
| 173 | $pos = ($block + 1) * BIG_BLOCK_SIZE; | ||
| 174 | $data = $data.substr($this->data, $pos, BIG_BLOCK_SIZE); | ||
| 175 | //echo "pos = $pos data=$data\n"; | ||
| 176 | $block = $this->bigBlockChain[$block]; | ||
| 177 | } | ||
| 178 | return $data; | ||
| 179 | } | ||
| 180 | |||
| 181 | function __readPropertySets(){ | ||
| 182 | $offset = 0; | ||
| 183 | //var_dump($this->entry); | ||
| 184 | while ($offset < strlen($this->entry)) { | ||
| 185 | $d = substr($this->entry, $offset, PROPERTY_STORAGE_BLOCK_SIZE); | ||
| 186 | |||
| 187 | $nameSize = ord($d[SIZE_OF_NAME_POS]) | (ord($d[SIZE_OF_NAME_POS+1]) << 8); | ||
| 188 | |||
| 189 | $type = ord($d[TYPE_POS]); | ||
| 190 | //$maxBlock = strlen($d) / BIG_BLOCK_SIZE - 1; | ||
| 191 | |||
| 192 | $startBlock = GetInt4d($d, START_BLOCK_POS); | ||
| 193 | $size = GetInt4d($d, SIZE_POS); | ||
| 194 | |||
| 195 | $name = ''; | ||
| 196 | for ($i = 0; $i < $nameSize ; $i++) { | ||
| 197 | $name .= $d[$i]; | ||
| 198 | } | ||
| 199 | |||
| 200 | $name = str_replace("\x00", "", $name); | ||
| 201 | |||
| 202 | $this->props[] = array ( | ||
| 203 | 'name' => $name, | ||
| 204 | 'type' => $type, | ||
| 205 | 'startBlock' => $startBlock, | ||
| 206 | 'size' => $size); | ||
| 207 | |||
| 208 | if (($name == "Workbook") || ($name == "Book")) { | ||
| 209 | $this->wrkbook = count($this->props) - 1; | ||
| 210 | } | ||
| 211 | |||
| 212 | if ($name == "Root Entry") { | ||
| 213 | $this->rootentry = count($this->props) - 1; | ||
| 214 | } | ||
| 215 | |||
| 216 | //echo "name ==$name=\n"; | ||
| 217 | |||
| 218 | |||
| 219 | $offset += PROPERTY_STORAGE_BLOCK_SIZE; | ||
| 220 | } | ||
| 221 | |||
| 222 | } | ||
| 223 | |||
| 224 | |||
| 225 | function getWorkBook(){ | ||
| 226 | if ($this->props[$this->wrkbook]['size'] < SMALL_BLOCK_THRESHOLD){ | ||
| 227 | // getSmallBlockStream(PropertyStorage ps) | ||
| 228 | |||
| 229 | $rootdata = $this->__readData($this->props[$this->rootentry]['startBlock']); | ||
| 230 | |||
| 231 | $streamData = ''; | ||
| 232 | $block = $this->props[$this->wrkbook]['startBlock']; | ||
| 233 | //$count = 0; | ||
| 234 | $pos = 0; | ||
| 235 | while ($block != -2) { | ||
| 236 | $pos = $block * SMALL_BLOCK_SIZE; | ||
| 237 | $streamData .= substr($rootdata, $pos, SMALL_BLOCK_SIZE); | ||
| 238 | |||
| 239 | $block = $this->smallBlockChain[$block]; | ||
| 240 | } | ||
| 241 | |||
| 242 | return $streamData; | ||
| 243 | |||
| 244 | |||
| 245 | }else{ | ||
| 246 | |||
| 247 | $numBlocks = $this->props[$this->wrkbook]['size'] / BIG_BLOCK_SIZE; | ||
| 248 | if ($this->props[$this->wrkbook]['size'] % BIG_BLOCK_SIZE != 0) { | ||
| 249 | $numBlocks++; | ||
| 250 | } | ||
| 251 | |||
| 252 | if ($numBlocks == 0) return ''; | ||
| 253 | |||
| 254 | //echo "numBlocks = $numBlocks\n"; | ||
| 255 | //byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE]; | ||
| 256 | //print_r($this->wrkbook); | ||
| 257 | $streamData = ''; | ||
| 258 | $block = $this->props[$this->wrkbook]['startBlock']; | ||
| 259 | //$count = 0; | ||
| 260 | $pos = 0; | ||
| 261 | //echo "block = $block"; | ||
| 262 | while ($block != -2) { | ||
| 263 | $pos = ($block + 1) * BIG_BLOCK_SIZE; | ||
| 264 | $streamData .= substr($this->data, $pos, BIG_BLOCK_SIZE); | ||
| 265 | $block = $this->bigBlockChain[$block]; | ||
| 266 | } | ||
| 267 | //echo 'stream'.$streamData; | ||
| 268 | return $streamData; | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | } | ||
| 273 | ?> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
com/ExcelReader/reader.php
0 → 100755
| 1 | <?php | ||
| 2 | namespace Tz\Wordpress\Tools\ExcelReader; | ||
| 3 | /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ | ||
| 4 | |||
| 5 | /** | ||
| 6 | * A class for reading Microsoft Excel Spreadsheets. | ||
| 7 | * | ||
| 8 | * Originally developed by Vadim Tkachenko under the name PHPExcelReader. | ||
| 9 | * (http://sourceforge.net/projects/phpexcelreader) | ||
| 10 | * Based on the Java version by Andy Khan (http://www.andykhan.com). Now | ||
| 11 | * maintained by David Sanders. Reads only Biff 7 and Biff 8 formats. | ||
| 12 | * | ||
| 13 | * PHP versions 4 and 5 | ||
| 14 | * | ||
| 15 | * LICENSE: This source file is subject to version 3.0 of the PHP license | ||
| 16 | * that is available through the world-wide-web at the following URI: | ||
| 17 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of | ||
| 18 | * the PHP License and are unable to obtain it through the web, please | ||
| 19 | * send a note to license@php.net so we can mail you a copy immediately. | ||
| 20 | * | ||
| 21 | * @category Spreadsheet | ||
| 22 | * @package Spreadsheet_Excel_Reader | ||
| 23 | * @author Vadim Tkachenko <vt@apachephp.com> | ||
| 24 | * @license http://www.php.net/license/3_0.txt PHP License 3.0 | ||
| 25 | * @version CVS: $Id: reader.php 19 2007-03-13 12:42:41Z shangxiao $ | ||
| 26 | * @link http://pear.php.net/package/Spreadsheet_Excel_Reader | ||
| 27 | * @see OLE, Spreadsheet_Excel_Writer | ||
| 28 | */ | ||
| 29 | |||
| 30 | |||
| 31 | //require_once 'PEAR.php'; | ||
| 32 | //require_once 'Spreadsheet/Excel/Reader/OLERead.php'; | ||
| 33 | //require_once 'OLE.php'; | ||
| 34 | require_once 'oleread.inc'; | ||
| 35 | |||
| 36 | define('SPREADSHEET_EXCEL_READER_BIFF8', 0x600); | ||
| 37 | define('SPREADSHEET_EXCEL_READER_BIFF7', 0x500); | ||
| 38 | define('SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS', 0x5); | ||
| 39 | define('SPREADSHEET_EXCEL_READER_WORKSHEET', 0x10); | ||
| 40 | |||
| 41 | define('SPREADSHEET_EXCEL_READER_TYPE_BOF', 0x809); | ||
| 42 | define('SPREADSHEET_EXCEL_READER_TYPE_EOF', 0x0a); | ||
| 43 | define('SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET', 0x85); | ||
| 44 | define('SPREADSHEET_EXCEL_READER_TYPE_DIMENSION', 0x200); | ||
| 45 | define('SPREADSHEET_EXCEL_READER_TYPE_ROW', 0x208); | ||
| 46 | define('SPREADSHEET_EXCEL_READER_TYPE_DBCELL', 0xd7); | ||
| 47 | define('SPREADSHEET_EXCEL_READER_TYPE_FILEPASS', 0x2f); | ||
| 48 | define('SPREADSHEET_EXCEL_READER_TYPE_NOTE', 0x1c); | ||
| 49 | define('SPREADSHEET_EXCEL_READER_TYPE_TXO', 0x1b6); | ||
| 50 | define('SPREADSHEET_EXCEL_READER_TYPE_RK', 0x7e); | ||
| 51 | define('SPREADSHEET_EXCEL_READER_TYPE_RK2', 0x27e); | ||
| 52 | define('SPREADSHEET_EXCEL_READER_TYPE_MULRK', 0xbd); | ||
| 53 | define('SPREADSHEET_EXCEL_READER_TYPE_MULBLANK', 0xbe); | ||
| 54 | define('SPREADSHEET_EXCEL_READER_TYPE_INDEX', 0x20b); | ||
| 55 | define('SPREADSHEET_EXCEL_READER_TYPE_SST', 0xfc); | ||
| 56 | define('SPREADSHEET_EXCEL_READER_TYPE_EXTSST', 0xff); | ||
| 57 | define('SPREADSHEET_EXCEL_READER_TYPE_CONTINUE', 0x3c); | ||
| 58 | define('SPREADSHEET_EXCEL_READER_TYPE_LABEL', 0x204); | ||
| 59 | define('SPREADSHEET_EXCEL_READER_TYPE_LABELSST', 0xfd); | ||
| 60 | define('SPREADSHEET_EXCEL_READER_TYPE_NUMBER', 0x203); | ||
| 61 | define('SPREADSHEET_EXCEL_READER_TYPE_NAME', 0x18); | ||
| 62 | define('SPREADSHEET_EXCEL_READER_TYPE_ARRAY', 0x221); | ||
| 63 | define('SPREADSHEET_EXCEL_READER_TYPE_STRING', 0x207); | ||
| 64 | define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA', 0x406); | ||
| 65 | define('SPREADSHEET_EXCEL_READER_TYPE_FORMULA2', 0x6); | ||
| 66 | define('SPREADSHEET_EXCEL_READER_TYPE_FORMAT', 0x41e); | ||
| 67 | define('SPREADSHEET_EXCEL_READER_TYPE_XF', 0xe0); | ||
| 68 | define('SPREADSHEET_EXCEL_READER_TYPE_BOOLERR', 0x205); | ||
| 69 | define('SPREADSHEET_EXCEL_READER_TYPE_UNKNOWN', 0xffff); | ||
| 70 | define('SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR', 0x22); | ||
| 71 | define('SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS', 0xE5); | ||
| 72 | |||
| 73 | define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS' , 25569); | ||
| 74 | define('SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904', 24107); | ||
| 75 | define('SPREADSHEET_EXCEL_READER_MSINADAY', 86400); | ||
| 76 | //define('SPREADSHEET_EXCEL_READER_MSINADAY', 24 * 60 * 60); | ||
| 77 | |||
| 78 | //define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%.2f"); | ||
| 79 | define('SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT', "%s"); | ||
| 80 | |||
| 81 | |||
| 82 | /* | ||
| 83 | * Place includes, constant defines and $_GLOBAL settings here. | ||
| 84 | * Make sure they have appropriate docblocks to avoid phpDocumentor | ||
| 85 | * construing they are documented by the page-level docblock. | ||
| 86 | */ | ||
| 87 | |||
| 88 | /** | ||
| 89 | * A class for reading Microsoft Excel Spreadsheets. | ||
| 90 | * | ||
| 91 | * Originally developed by Vadim Tkachenko under the name PHPExcelReader. | ||
| 92 | * (http://sourceforge.net/projects/phpexcelreader) | ||
| 93 | * Based on the Java version by Andy Khan (http://www.andykhan.com). Now | ||
| 94 | * maintained by David Sanders. Reads only Biff 7 and Biff 8 formats. | ||
| 95 | * | ||
| 96 | * @category Spreadsheet | ||
| 97 | * @package Spreadsheet_Excel_Reader | ||
| 98 | * @author Vadim Tkachenko <vt@phpapache.com> | ||
| 99 | * @copyright 1997-2005 The PHP Group | ||
| 100 | * @license http://www.php.net/license/3_0.txt PHP License 3.0 | ||
| 101 | * @version Release: @package_version@ | ||
| 102 | * @link http://pear.php.net/package/PackageName | ||
| 103 | * @see OLE, Spreadsheet_Excel_Writer | ||
| 104 | */ | ||
| 105 | class Spreadsheet_Excel_Reader | ||
| 106 | { | ||
| 107 | /** | ||
| 108 | * Array of worksheets found | ||
| 109 | * | ||
| 110 | * @var array | ||
| 111 | * @access public | ||
| 112 | */ | ||
| 113 | var $boundsheets = array(); | ||
| 114 | |||
| 115 | /** | ||
| 116 | * Array of format records found | ||
| 117 | * | ||
| 118 | * @var array | ||
| 119 | * @access public | ||
| 120 | */ | ||
| 121 | var $formatRecords = array(); | ||
| 122 | |||
| 123 | /** | ||
| 124 | * todo | ||
| 125 | * | ||
| 126 | * @var array | ||
| 127 | * @access public | ||
| 128 | */ | ||
| 129 | var $sst = array(); | ||
| 130 | |||
| 131 | /** | ||
| 132 | * Array of worksheets | ||
| 133 | * | ||
| 134 | * The data is stored in 'cells' and the meta-data is stored in an array | ||
| 135 | * called 'cellsInfo' | ||
| 136 | * | ||
| 137 | * Example: | ||
| 138 | * | ||
| 139 | * $sheets --> 'cells' --> row --> column --> Interpreted value | ||
| 140 | * --> 'cellsInfo' --> row --> column --> 'type' - Can be 'date', 'number', or 'unknown' | ||
| 141 | * --> 'raw' - The raw data that Excel stores for that data cell | ||
| 142 | * | ||
| 143 | * @var array | ||
| 144 | * @access public | ||
| 145 | */ | ||
| 146 | var $sheets = array(); | ||
| 147 | |||
| 148 | /** | ||
| 149 | * The data returned by OLE | ||
| 150 | * | ||
| 151 | * @var string | ||
| 152 | * @access public | ||
| 153 | */ | ||
| 154 | var $data; | ||
| 155 | |||
| 156 | /** | ||
| 157 | * OLE object for reading the file | ||
| 158 | * | ||
| 159 | * @var OLE object | ||
| 160 | * @access private | ||
| 161 | */ | ||
| 162 | var $_ole; | ||
| 163 | |||
| 164 | /** | ||
| 165 | * Default encoding | ||
| 166 | * | ||
| 167 | * @var string | ||
| 168 | * @access private | ||
| 169 | */ | ||
| 170 | var $_defaultEncoding; | ||
| 171 | |||
| 172 | /** | ||
| 173 | * Default number format | ||
| 174 | * | ||
| 175 | * @var integer | ||
| 176 | * @access private | ||
| 177 | */ | ||
| 178 | var $_defaultFormat = SPREADSHEET_EXCEL_READER_DEF_NUM_FORMAT; | ||
| 179 | |||
| 180 | /** | ||
| 181 | * todo | ||
| 182 | * List of formats to use for each column | ||
| 183 | * | ||
| 184 | * @var array | ||
| 185 | * @access private | ||
| 186 | */ | ||
| 187 | var $_columnsFormat = array(); | ||
| 188 | |||
| 189 | /** | ||
| 190 | * todo | ||
| 191 | * | ||
| 192 | * @var integer | ||
| 193 | * @access private | ||
| 194 | */ | ||
| 195 | var $_rowoffset = 1; | ||
| 196 | |||
| 197 | /** | ||
| 198 | * todo | ||
| 199 | * | ||
| 200 | * @var integer | ||
| 201 | * @access private | ||
| 202 | */ | ||
| 203 | var $_coloffset = 1; | ||
| 204 | |||
| 205 | /** | ||
| 206 | * List of default date formats used by Excel | ||
| 207 | * | ||
| 208 | * @var array | ||
| 209 | * @access public | ||
| 210 | */ | ||
| 211 | var $dateFormats = array ( | ||
| 212 | 0xe => "d/m/Y", | ||
| 213 | 0xf => "d-M-Y", | ||
| 214 | 0x10 => "d-M", | ||
| 215 | 0x11 => "M-Y", | ||
| 216 | 0x12 => "h:i a", | ||
| 217 | 0x13 => "h:i:s a", | ||
| 218 | 0x14 => "H:i", | ||
| 219 | 0x15 => "H:i:s", | ||
| 220 | 0x16 => "d/m/Y H:i", | ||
| 221 | 0x2d => "i:s", | ||
| 222 | 0x2e => "H:i:s", | ||
| 223 | 0x2f => "i:s.S"); | ||
| 224 | |||
| 225 | /** | ||
| 226 | * Default number formats used by Excel | ||
| 227 | * | ||
| 228 | * @var array | ||
| 229 | * @access public | ||
| 230 | */ | ||
| 231 | var $numberFormats = array( | ||
| 232 | 0x1 => "%1.0f", // "0" | ||
| 233 | 0x2 => "%1.2f", // "0.00", | ||
| 234 | 0x3 => "%1.0f", //"#,##0", | ||
| 235 | 0x4 => "%1.2f", //"#,##0.00", | ||
| 236 | 0x5 => "%1.0f", /*"$#,##0;($#,##0)",*/ | ||
| 237 | 0x6 => '$%1.0f', /*"$#,##0;($#,##0)",*/ | ||
| 238 | 0x7 => '$%1.2f', //"$#,##0.00;($#,##0.00)", | ||
| 239 | 0x8 => '$%1.2f', //"$#,##0.00;($#,##0.00)", | ||
| 240 | 0x9 => '%1.0f%%', // "0%" | ||
| 241 | 0xa => '%1.2f%%', // "0.00%" | ||
| 242 | 0xb => '%1.2f', // 0.00E00", | ||
| 243 | 0x25 => '%1.0f', // "#,##0;(#,##0)", | ||
| 244 | 0x26 => '%1.0f', //"#,##0;(#,##0)", | ||
| 245 | 0x27 => '%1.2f', //"#,##0.00;(#,##0.00)", | ||
| 246 | 0x28 => '%1.2f', //"#,##0.00;(#,##0.00)", | ||
| 247 | 0x29 => '%1.0f', //"#,##0;(#,##0)", | ||
| 248 | 0x2a => '$%1.0f', //"$#,##0;($#,##0)", | ||
| 249 | 0x2b => '%1.2f', //"#,##0.00;(#,##0.00)", | ||
| 250 | 0x2c => '$%1.2f', //"$#,##0.00;($#,##0.00)", | ||
| 251 | 0x30 => '%1.0f'); //"##0.0E0"; | ||
| 252 | |||
| 253 | // }}} | ||
| 254 | // {{{ Spreadsheet_Excel_Reader() | ||
| 255 | |||
| 256 | /** | ||
| 257 | * Constructor | ||
| 258 | * | ||
| 259 | * Some basic initialisation | ||
| 260 | */ | ||
| 261 | function Spreadsheet_Excel_Reader() | ||
| 262 | { | ||
| 263 | $this->_ole =& new OLERead(); | ||
| 264 | $this->setUTFEncoder('iconv'); | ||
| 265 | } | ||
| 266 | |||
| 267 | // }}} | ||
| 268 | // {{{ setOutputEncoding() | ||
| 269 | |||
| 270 | /** | ||
| 271 | * Set the encoding method | ||
| 272 | * | ||
| 273 | * @param string Encoding to use | ||
| 274 | * @access public | ||
| 275 | */ | ||
| 276 | function setOutputEncoding($encoding) | ||
| 277 | { | ||
| 278 | $this->_defaultEncoding = $encoding; | ||
| 279 | } | ||
| 280 | |||
| 281 | // }}} | ||
| 282 | // {{{ setUTFEncoder() | ||
| 283 | |||
| 284 | /** | ||
| 285 | * $encoder = 'iconv' or 'mb' | ||
| 286 | * set iconv if you would like use 'iconv' for encode UTF-16LE to your encoding | ||
| 287 | * set mb if you would like use 'mb_convert_encoding' for encode UTF-16LE to your encoding | ||
| 288 | * | ||
| 289 | * @access public | ||
| 290 | * @param string Encoding type to use. Either 'iconv' or 'mb' | ||
| 291 | */ | ||
| 292 | function setUTFEncoder($encoder = 'iconv') | ||
| 293 | { | ||
| 294 | $this->_encoderFunction = ''; | ||
| 295 | |||
| 296 | if ($encoder == 'iconv') { | ||
| 297 | $this->_encoderFunction = function_exists('iconv') ? 'iconv' : ''; | ||
| 298 | } elseif ($encoder == 'mb') { | ||
| 299 | $this->_encoderFunction = function_exists('mb_convert_encoding') ? | ||
| 300 | 'mb_convert_encoding' : | ||
| 301 | ''; | ||
| 302 | } | ||
| 303 | } | ||
| 304 | |||
| 305 | // }}} | ||
| 306 | // {{{ setRowColOffset() | ||
| 307 | |||
| 308 | /** | ||
| 309 | * todo | ||
| 310 | * | ||
| 311 | * @access public | ||
| 312 | * @param offset | ||
| 313 | */ | ||
| 314 | function setRowColOffset($iOffset) | ||
| 315 | { | ||
| 316 | $this->_rowoffset = $iOffset; | ||
| 317 | $this->_coloffset = $iOffset; | ||
| 318 | } | ||
| 319 | |||
| 320 | // }}} | ||
| 321 | // {{{ setDefaultFormat() | ||
| 322 | |||
| 323 | /** | ||
| 324 | * Set the default number format | ||
| 325 | * | ||
| 326 | * @access public | ||
| 327 | * @param Default format | ||
| 328 | */ | ||
| 329 | function setDefaultFormat($sFormat) | ||
| 330 | { | ||
| 331 | $this->_defaultFormat = $sFormat; | ||
| 332 | } | ||
| 333 | |||
| 334 | // }}} | ||
| 335 | // {{{ setColumnFormat() | ||
| 336 | |||
| 337 | /** | ||
| 338 | * Force a column to use a certain format | ||
| 339 | * | ||
| 340 | * @access public | ||
| 341 | * @param integer Column number | ||
| 342 | * @param string Format | ||
| 343 | */ | ||
| 344 | function setColumnFormat($column, $sFormat) | ||
| 345 | { | ||
| 346 | $this->_columnsFormat[$column] = $sFormat; | ||
| 347 | } | ||
| 348 | |||
| 349 | |||
| 350 | // }}} | ||
| 351 | // {{{ read() | ||
| 352 | |||
| 353 | /** | ||
| 354 | * Read the spreadsheet file using OLE, then parse | ||
| 355 | * | ||
| 356 | * @access public | ||
| 357 | * @param filename | ||
| 358 | * @todo return a valid value | ||
| 359 | */ | ||
| 360 | function read($sFileName) | ||
| 361 | { | ||
| 362 | /* | ||
| 363 | require_once 'OLE.php'; | ||
| 364 | $ole = new OLE(); | ||
| 365 | $ole->read($sFileName); | ||
| 366 | |||
| 367 | foreach ($ole->_list as $i => $pps) { | ||
| 368 | if (($pps->Name == 'Workbook' || $pps->Name == 'Book') && | ||
| 369 | $pps->Size >= SMALL_BLOCK_THRESHOLD) { | ||
| 370 | |||
| 371 | $this->data = $ole->getData($i, 0, $ole->getDataLength($i)); | ||
| 372 | } elseif ($pps->Name == 'Root Entry') { | ||
| 373 | $this->data = $ole->getData($i, 0, $ole->getDataLength($i)); | ||
| 374 | } | ||
| 375 | //var_dump(strlen($ole->getData($i, 0, $ole->getDataLength($i))), $pps->Name, md5($this->data), $ole->getDataLength($i)); | ||
| 376 | } | ||
| 377 | //exit; | ||
| 378 | $this->_parse(); | ||
| 379 | |||
| 380 | return sizeof($this->sheets) > 0; | ||
| 381 | */ | ||
| 382 | |||
| 383 | $res = $this->_ole->read($sFileName); | ||
| 384 | |||
| 385 | // oops, something goes wrong (Darko Miljanovic) | ||
| 386 | if($res === false) { | ||
| 387 | // check error code | ||
| 388 | if($this->_ole->error == 1) { | ||
| 389 | // bad file | ||
| 390 | die('The filename ' . $sFileName . ' is not readable'); | ||
| 391 | } | ||
| 392 | // check other error codes here (eg bad fileformat, etc...) | ||
| 393 | } | ||
| 394 | |||
| 395 | $this->data = $this->_ole->getWorkBook(); | ||
| 396 | |||
| 397 | |||
| 398 | /* | ||
| 399 | $res = $this->_ole->read($sFileName); | ||
| 400 | |||
| 401 | if ($this->isError($res)) { | ||
| 402 | // var_dump($res); | ||
| 403 | return $this->raiseError($res); | ||
| 404 | } | ||
| 405 | |||
| 406 | $total = $this->_ole->ppsTotal(); | ||
| 407 | for ($i = 0; $i < $total; $i++) { | ||
| 408 | if ($this->_ole->isFile($i)) { | ||
| 409 | $type = unpack("v", $this->_ole->getData($i, 0, 2)); | ||
| 410 | if ($type[''] == 0x0809) { // check if it's a BIFF stream | ||
| 411 | $this->_index = $i; | ||
| 412 | $this->data = $this->_ole->getData($i, 0, $this->_ole->getDataLength($i)); | ||
| 413 | break; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | if ($this->_index === null) { | ||
| 419 | return $this->raiseError("$file doesn't seem to be an Excel file"); | ||
| 420 | } | ||
| 421 | |||
| 422 | */ | ||
| 423 | |||
| 424 | //echo "data =".$this->data; | ||
| 425 | //$this->readRecords(); | ||
| 426 | $this->_parse(); | ||
| 427 | } | ||
| 428 | |||
| 429 | |||
| 430 | // }}} | ||
| 431 | // {{{ _parse() | ||
| 432 | |||
| 433 | /** | ||
| 434 | * Parse a workbook | ||
| 435 | * | ||
| 436 | * @access private | ||
| 437 | * @return bool | ||
| 438 | */ | ||
| 439 | function _parse() | ||
| 440 | { | ||
| 441 | $pos = 0; | ||
| 442 | |||
| 443 | $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; | ||
| 444 | $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; | ||
| 445 | |||
| 446 | $version = ord($this->data[$pos + 4]) | ord($this->data[$pos + 5])<<8; | ||
| 447 | $substreamType = ord($this->data[$pos + 6]) | ord($this->data[$pos + 7])<<8; | ||
| 448 | //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n"; | ||
| 449 | |||
| 450 | if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && | ||
| 451 | ($version != SPREADSHEET_EXCEL_READER_BIFF7)) { | ||
| 452 | return false; | ||
| 453 | } | ||
| 454 | |||
| 455 | if ($substreamType != SPREADSHEET_EXCEL_READER_WORKBOOKGLOBALS){ | ||
| 456 | return false; | ||
| 457 | } | ||
| 458 | |||
| 459 | //print_r($rec); | ||
| 460 | $pos += $length + 4; | ||
| 461 | |||
| 462 | $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; | ||
| 463 | $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; | ||
| 464 | |||
| 465 | while ($code != SPREADSHEET_EXCEL_READER_TYPE_EOF) { | ||
| 466 | switch ($code) { | ||
| 467 | case SPREADSHEET_EXCEL_READER_TYPE_SST: | ||
| 468 | //echo "Type_SST\n"; | ||
| 469 | $spos = $pos + 4; | ||
| 470 | $limitpos = $spos + $length; | ||
| 471 | $uniqueStrings = $this->_GetInt4d($this->data, $spos+4); | ||
| 472 | $spos += 8; | ||
| 473 | for ($i = 0; $i < $uniqueStrings; $i++) { | ||
| 474 | // Read in the number of characters | ||
| 475 | if ($spos == $limitpos) { | ||
| 476 | $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 477 | $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 478 | if ($opcode != 0x3c) { | ||
| 479 | return -1; | ||
| 480 | } | ||
| 481 | $spos += 4; | ||
| 482 | $limitpos = $spos + $conlength; | ||
| 483 | } | ||
| 484 | $numChars = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8); | ||
| 485 | //echo "i = $i pos = $pos numChars = $numChars "; | ||
| 486 | $spos += 2; | ||
| 487 | $optionFlags = ord($this->data[$spos]); | ||
| 488 | $spos++; | ||
| 489 | $asciiEncoding = (($optionFlags & 0x01) == 0) ; | ||
| 490 | $extendedString = ( ($optionFlags & 0x04) != 0); | ||
| 491 | |||
| 492 | // See if string contains formatting information | ||
| 493 | $richString = ( ($optionFlags & 0x08) != 0); | ||
| 494 | |||
| 495 | if ($richString) { | ||
| 496 | // Read in the crun | ||
| 497 | $formattingRuns = ord($this->data[$spos]) | (ord($this->data[$spos+1]) << 8); | ||
| 498 | $spos += 2; | ||
| 499 | } | ||
| 500 | |||
| 501 | if ($extendedString) { | ||
| 502 | // Read in cchExtRst | ||
| 503 | $extendedRunLength = $this->_GetInt4d($this->data, $spos); | ||
| 504 | $spos += 4; | ||
| 505 | } | ||
| 506 | |||
| 507 | $len = ($asciiEncoding)? $numChars : $numChars*2; | ||
| 508 | if ($spos + $len < $limitpos) { | ||
| 509 | $retstr = substr($this->data, $spos, $len); | ||
| 510 | $spos += $len; | ||
| 511 | }else{ | ||
| 512 | // found countinue | ||
| 513 | $retstr = substr($this->data, $spos, $limitpos - $spos); | ||
| 514 | $bytesRead = $limitpos - $spos; | ||
| 515 | $charsLeft = $numChars - (($asciiEncoding) ? $bytesRead : ($bytesRead / 2)); | ||
| 516 | $spos = $limitpos; | ||
| 517 | |||
| 518 | while ($charsLeft > 0){ | ||
| 519 | $opcode = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 520 | $conlength = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 521 | if ($opcode != 0x3c) { | ||
| 522 | return -1; | ||
| 523 | } | ||
| 524 | $spos += 4; | ||
| 525 | $limitpos = $spos + $conlength; | ||
| 526 | $option = ord($this->data[$spos]); | ||
| 527 | $spos += 1; | ||
| 528 | if ($asciiEncoding && ($option == 0)) { | ||
| 529 | $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength); | ||
| 530 | $retstr .= substr($this->data, $spos, $len); | ||
| 531 | $charsLeft -= $len; | ||
| 532 | $asciiEncoding = true; | ||
| 533 | }elseif (!$asciiEncoding && ($option != 0)){ | ||
| 534 | $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength); | ||
| 535 | $retstr .= substr($this->data, $spos, $len); | ||
| 536 | $charsLeft -= $len/2; | ||
| 537 | $asciiEncoding = false; | ||
| 538 | }elseif (!$asciiEncoding && ($option == 0)) { | ||
| 539 | // Bummer - the string starts off as Unicode, but after the | ||
| 540 | // continuation it is in straightforward ASCII encoding | ||
| 541 | $len = min($charsLeft, $limitpos - $spos); // min($charsLeft, $conlength); | ||
| 542 | for ($j = 0; $j < $len; $j++) { | ||
| 543 | $retstr .= $this->data[$spos + $j].chr(0); | ||
| 544 | } | ||
| 545 | $charsLeft -= $len; | ||
| 546 | $asciiEncoding = false; | ||
| 547 | }else{ | ||
| 548 | $newstr = ''; | ||
| 549 | for ($j = 0; $j < strlen($retstr); $j++) { | ||
| 550 | $newstr = $retstr[$j].chr(0); | ||
| 551 | } | ||
| 552 | $retstr = $newstr; | ||
| 553 | $len = min($charsLeft * 2, $limitpos - $spos); // min($charsLeft, $conlength); | ||
| 554 | $retstr .= substr($this->data, $spos, $len); | ||
| 555 | $charsLeft -= $len/2; | ||
| 556 | $asciiEncoding = false; | ||
| 557 | //echo "Izavrat\n"; | ||
| 558 | } | ||
| 559 | $spos += $len; | ||
| 560 | |||
| 561 | } | ||
| 562 | } | ||
| 563 | $retstr = ($asciiEncoding) ? $retstr : $this->_encodeUTF16($retstr); | ||
| 564 | // echo "Str $i = $retstr\n"; | ||
| 565 | if ($richString){ | ||
| 566 | $spos += 4 * $formattingRuns; | ||
| 567 | } | ||
| 568 | |||
| 569 | // For extended strings, skip over the extended string data | ||
| 570 | if ($extendedString) { | ||
| 571 | $spos += $extendedRunLength; | ||
| 572 | } | ||
| 573 | //if ($retstr == 'Derby'){ | ||
| 574 | // echo "bb\n"; | ||
| 575 | //} | ||
| 576 | $this->sst[]=$retstr; | ||
| 577 | } | ||
| 578 | /*$continueRecords = array(); | ||
| 579 | while ($this->getNextCode() == Type_CONTINUE) { | ||
| 580 | $continueRecords[] = &$this->nextRecord(); | ||
| 581 | } | ||
| 582 | //echo " 1 Type_SST\n"; | ||
| 583 | $this->shareStrings = new SSTRecord($r, $continueRecords); | ||
| 584 | //print_r($this->shareStrings->strings); | ||
| 585 | */ | ||
| 586 | // echo 'SST read: '.($time_end-$time_start)."\n"; | ||
| 587 | break; | ||
| 588 | |||
| 589 | case SPREADSHEET_EXCEL_READER_TYPE_FILEPASS: | ||
| 590 | return false; | ||
| 591 | break; | ||
| 592 | case SPREADSHEET_EXCEL_READER_TYPE_NAME: | ||
| 593 | //echo "Type_NAME\n"; | ||
| 594 | break; | ||
| 595 | case SPREADSHEET_EXCEL_READER_TYPE_FORMAT: | ||
| 596 | $indexCode = ord($this->data[$pos+4]) | ord($this->data[$pos+5]) << 8; | ||
| 597 | |||
| 598 | if ($version == SPREADSHEET_EXCEL_READER_BIFF8) { | ||
| 599 | $numchars = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8; | ||
| 600 | if (ord($this->data[$pos+8]) == 0){ | ||
| 601 | $formatString = substr($this->data, $pos+9, $numchars); | ||
| 602 | } else { | ||
| 603 | $formatString = substr($this->data, $pos+9, $numchars*2); | ||
| 604 | } | ||
| 605 | } else { | ||
| 606 | $numchars = ord($this->data[$pos+6]); | ||
| 607 | $formatString = substr($this->data, $pos+7, $numchars*2); | ||
| 608 | } | ||
| 609 | |||
| 610 | $this->formatRecords[$indexCode] = $formatString; | ||
| 611 | // echo "Type.FORMAT\n"; | ||
| 612 | break; | ||
| 613 | case SPREADSHEET_EXCEL_READER_TYPE_XF: | ||
| 614 | //global $dateFormats, $numberFormats; | ||
| 615 | $indexCode = ord($this->data[$pos+6]) | ord($this->data[$pos+7]) << 8; | ||
| 616 | //echo "\nType.XF ".count($this->formatRecords['xfrecords'])." $indexCode "; | ||
| 617 | if (array_key_exists($indexCode, $this->dateFormats)) { | ||
| 618 | //echo "isdate ".$dateFormats[$indexCode]; | ||
| 619 | $this->formatRecords['xfrecords'][] = array( | ||
| 620 | 'type' => 'date', | ||
| 621 | 'format' => $this->dateFormats[$indexCode] | ||
| 622 | ); | ||
| 623 | }elseif (array_key_exists($indexCode, $this->numberFormats)) { | ||
| 624 | //echo "isnumber ".$this->numberFormats[$indexCode]; | ||
| 625 | $this->formatRecords['xfrecords'][] = array( | ||
| 626 | 'type' => 'number', | ||
| 627 | 'format' => $this->numberFormats[$indexCode] | ||
| 628 | ); | ||
| 629 | }else{ | ||
| 630 | $isdate = FALSE; | ||
| 631 | if ($indexCode > 0){ | ||
| 632 | if (isset($this->formatRecords[$indexCode])) | ||
| 633 | $formatstr = $this->formatRecords[$indexCode]; | ||
| 634 | //echo '.other.'; | ||
| 635 | //echo "\ndate-time=$formatstr=\n"; | ||
| 636 | if ($formatstr) | ||
| 637 | if (preg_match("/[^hmsday\/\-:\s]/i", $formatstr) == 0) { // found day and time format | ||
| 638 | $isdate = TRUE; | ||
| 639 | $formatstr = str_replace('mm', 'i', $formatstr); | ||
| 640 | $formatstr = str_replace('h', 'H', $formatstr); | ||
| 641 | //echo "\ndate-time $formatstr \n"; | ||
| 642 | } | ||
| 643 | } | ||
| 644 | |||
| 645 | if ($isdate){ | ||
| 646 | $this->formatRecords['xfrecords'][] = array( | ||
| 647 | 'type' => 'date', | ||
| 648 | 'format' => $formatstr, | ||
| 649 | ); | ||
| 650 | }else{ | ||
| 651 | $this->formatRecords['xfrecords'][] = array( | ||
| 652 | 'type' => 'other', | ||
| 653 | 'format' => '', | ||
| 654 | 'code' => $indexCode | ||
| 655 | ); | ||
| 656 | } | ||
| 657 | } | ||
| 658 | //echo "\n"; | ||
| 659 | break; | ||
| 660 | case SPREADSHEET_EXCEL_READER_TYPE_NINETEENFOUR: | ||
| 661 | //echo "Type.NINETEENFOUR\n"; | ||
| 662 | $this->nineteenFour = (ord($this->data[$pos+4]) == 1); | ||
| 663 | break; | ||
| 664 | case SPREADSHEET_EXCEL_READER_TYPE_BOUNDSHEET: | ||
| 665 | //echo "Type.BOUNDSHEET\n"; | ||
| 666 | $rec_offset = $this->_GetInt4d($this->data, $pos+4); | ||
| 667 | $rec_typeFlag = ord($this->data[$pos+8]); | ||
| 668 | $rec_visibilityFlag = ord($this->data[$pos+9]); | ||
| 669 | $rec_length = ord($this->data[$pos+10]); | ||
| 670 | |||
| 671 | if ($version == SPREADSHEET_EXCEL_READER_BIFF8){ | ||
| 672 | $chartype = ord($this->data[$pos+11]); | ||
| 673 | if ($chartype == 0){ | ||
| 674 | $rec_name = substr($this->data, $pos+12, $rec_length); | ||
| 675 | } else { | ||
| 676 | $rec_name = $this->_encodeUTF16(substr($this->data, $pos+12, $rec_length*2)); | ||
| 677 | } | ||
| 678 | }elseif ($version == SPREADSHEET_EXCEL_READER_BIFF7){ | ||
| 679 | $rec_name = substr($this->data, $pos+11, $rec_length); | ||
| 680 | } | ||
| 681 | $this->boundsheets[] = array('name'=>$rec_name, | ||
| 682 | 'offset'=>$rec_offset); | ||
| 683 | |||
| 684 | break; | ||
| 685 | |||
| 686 | } | ||
| 687 | |||
| 688 | //echo "Code = ".base_convert($r['code'],10,16)."\n"; | ||
| 689 | $pos += $length + 4; | ||
| 690 | $code = ord($this->data[$pos]) | ord($this->data[$pos+1])<<8; | ||
| 691 | $length = ord($this->data[$pos+2]) | ord($this->data[$pos+3])<<8; | ||
| 692 | |||
| 693 | //$r = &$this->nextRecord(); | ||
| 694 | //echo "1 Code = ".base_convert($r['code'],10,16)."\n"; | ||
| 695 | } | ||
| 696 | |||
| 697 | foreach ($this->boundsheets as $key=>$val){ | ||
| 698 | $this->sn = $key; | ||
| 699 | $this->_parsesheet($val['offset']); | ||
| 700 | } | ||
| 701 | return true; | ||
| 702 | |||
| 703 | } | ||
| 704 | |||
| 705 | /** | ||
| 706 | * Parse a worksheet | ||
| 707 | * | ||
| 708 | * @access private | ||
| 709 | * @param todo | ||
| 710 | * @todo fix return codes | ||
| 711 | */ | ||
| 712 | function _parsesheet($spos) | ||
| 713 | { | ||
| 714 | $cont = true; | ||
| 715 | // read BOF | ||
| 716 | $code = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 717 | $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 718 | |||
| 719 | $version = ord($this->data[$spos + 4]) | ord($this->data[$spos + 5])<<8; | ||
| 720 | $substreamType = ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8; | ||
| 721 | |||
| 722 | if (($version != SPREADSHEET_EXCEL_READER_BIFF8) && ($version != SPREADSHEET_EXCEL_READER_BIFF7)) { | ||
| 723 | return -1; | ||
| 724 | } | ||
| 725 | |||
| 726 | if ($substreamType != SPREADSHEET_EXCEL_READER_WORKSHEET){ | ||
| 727 | return -2; | ||
| 728 | } | ||
| 729 | //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n"; | ||
| 730 | $spos += $length + 4; | ||
| 731 | //var_dump($this->formatRecords); | ||
| 732 | //echo "code $code $length"; | ||
| 733 | while($cont) { | ||
| 734 | //echo "mem= ".memory_get_usage()."\n"; | ||
| 735 | // $r = &$this->file->nextRecord(); | ||
| 736 | $lowcode = ord($this->data[$spos]); | ||
| 737 | if ($lowcode == SPREADSHEET_EXCEL_READER_TYPE_EOF) break; | ||
| 738 | $code = $lowcode | ord($this->data[$spos+1])<<8; | ||
| 739 | $length = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 740 | $spos += 4; | ||
| 741 | $this->sheets[$this->sn]['maxrow'] = $this->_rowoffset - 1; | ||
| 742 | $this->sheets[$this->sn]['maxcol'] = $this->_coloffset - 1; | ||
| 743 | //echo "Code=".base_convert($code,10,16)." $code\n"; | ||
| 744 | unset($this->rectype); | ||
| 745 | $this->multiplier = 1; // need for format with % | ||
| 746 | switch ($code) { | ||
| 747 | case SPREADSHEET_EXCEL_READER_TYPE_DIMENSION: | ||
| 748 | //echo 'Type_DIMENSION '; | ||
| 749 | if (!isset($this->numRows)) { | ||
| 750 | if (($length == 10) || ($version == SPREADSHEET_EXCEL_READER_BIFF7)){ | ||
| 751 | $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+2]) | ord($this->data[$spos+3]) << 8; | ||
| 752 | $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+6]) | ord($this->data[$spos+7]) << 8; | ||
| 753 | } else { | ||
| 754 | $this->sheets[$this->sn]['numRows'] = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8; | ||
| 755 | $this->sheets[$this->sn]['numCols'] = ord($this->data[$spos+10]) | ord($this->data[$spos+11]) << 8; | ||
| 756 | } | ||
| 757 | } | ||
| 758 | //echo 'numRows '.$this->numRows.' '.$this->numCols."\n"; | ||
| 759 | break; | ||
| 760 | case SPREADSHEET_EXCEL_READER_TYPE_MERGEDCELLS: | ||
| 761 | $cellRanges = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 762 | for ($i = 0; $i < $cellRanges; $i++) { | ||
| 763 | $fr = ord($this->data[$spos + 8*$i + 2]) | ord($this->data[$spos + 8*$i + 3])<<8; | ||
| 764 | $lr = ord($this->data[$spos + 8*$i + 4]) | ord($this->data[$spos + 8*$i + 5])<<8; | ||
| 765 | $fc = ord($this->data[$spos + 8*$i + 6]) | ord($this->data[$spos + 8*$i + 7])<<8; | ||
| 766 | $lc = ord($this->data[$spos + 8*$i + 8]) | ord($this->data[$spos + 8*$i + 9])<<8; | ||
| 767 | //$this->sheets[$this->sn]['mergedCells'][] = array($fr + 1, $fc + 1, $lr + 1, $lc + 1); | ||
| 768 | if ($lr - $fr > 0) { | ||
| 769 | $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['rowspan'] = $lr - $fr + 1; | ||
| 770 | } | ||
| 771 | if ($lc - $fc > 0) { | ||
| 772 | $this->sheets[$this->sn]['cellsInfo'][$fr+1][$fc+1]['colspan'] = $lc - $fc + 1; | ||
| 773 | } | ||
| 774 | } | ||
| 775 | //echo "Merged Cells $cellRanges $lr $fr $lc $fc\n"; | ||
| 776 | break; | ||
| 777 | case SPREADSHEET_EXCEL_READER_TYPE_RK: | ||
| 778 | case SPREADSHEET_EXCEL_READER_TYPE_RK2: | ||
| 779 | //echo 'SPREADSHEET_EXCEL_READER_TYPE_RK'."\n"; | ||
| 780 | $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 781 | $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 782 | $rknum = $this->_GetInt4d($this->data, $spos + 6); | ||
| 783 | $numValue = $this->_GetIEEE754($rknum); | ||
| 784 | //echo $numValue." "; | ||
| 785 | if ($this->isDate($spos)) { | ||
| 786 | list($string, $raw) = $this->createDate($numValue); | ||
| 787 | }else{ | ||
| 788 | $raw = $numValue; | ||
| 789 | if (isset($this->_columnsFormat[$column + 1])){ | ||
| 790 | $this->curformat = $this->_columnsFormat[$column + 1]; | ||
| 791 | } | ||
| 792 | $string = sprintf($this->curformat, $numValue * $this->multiplier); | ||
| 793 | //$this->addcell(RKRecord($r)); | ||
| 794 | } | ||
| 795 | $this->addcell($row, $column, $string, $raw); | ||
| 796 | //echo "Type_RK $row $column $string $raw {$this->curformat}\n"; | ||
| 797 | break; | ||
| 798 | case SPREADSHEET_EXCEL_READER_TYPE_LABELSST: | ||
| 799 | $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 800 | $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 801 | $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5])<<8; | ||
| 802 | $index = $this->_GetInt4d($this->data, $spos + 6); | ||
| 803 | //var_dump($this->sst); | ||
| 804 | $this->addcell($row, $column, $this->sst[$index]); | ||
| 805 | //echo "LabelSST $row $column $string\n"; | ||
| 806 | break; | ||
| 807 | case SPREADSHEET_EXCEL_READER_TYPE_MULRK: | ||
| 808 | $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 809 | $colFirst = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 810 | $colLast = ord($this->data[$spos + $length - 2]) | ord($this->data[$spos + $length - 1])<<8; | ||
| 811 | $columns = $colLast - $colFirst + 1; | ||
| 812 | $tmppos = $spos+4; | ||
| 813 | for ($i = 0; $i < $columns; $i++) { | ||
| 814 | $numValue = $this->_GetIEEE754($this->_GetInt4d($this->data, $tmppos + 2)); | ||
| 815 | if ($this->isDate($tmppos-4)) { | ||
| 816 | list($string, $raw) = $this->createDate($numValue); | ||
| 817 | }else{ | ||
| 818 | $raw = $numValue; | ||
| 819 | if (isset($this->_columnsFormat[$colFirst + $i + 1])){ | ||
| 820 | $this->curformat = $this->_columnsFormat[$colFirst + $i + 1]; | ||
| 821 | } | ||
| 822 | $string = sprintf($this->curformat, $numValue * $this->multiplier); | ||
| 823 | } | ||
| 824 | //$rec['rknumbers'][$i]['xfindex'] = ord($rec['data'][$pos]) | ord($rec['data'][$pos+1]) << 8; | ||
| 825 | $tmppos += 6; | ||
| 826 | $this->addcell($row, $colFirst + $i, $string, $raw); | ||
| 827 | //echo "MULRK $row ".($colFirst + $i)." $string\n"; | ||
| 828 | } | ||
| 829 | //MulRKRecord($r); | ||
| 830 | // Get the individual cell records from the multiple record | ||
| 831 | //$num = ; | ||
| 832 | |||
| 833 | break; | ||
| 834 | case SPREADSHEET_EXCEL_READER_TYPE_NUMBER: | ||
| 835 | $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 836 | $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 837 | $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent | ||
| 838 | if ($this->isDate($spos)) { | ||
| 839 | list($string, $raw) = $this->createDate($tmp['double']); | ||
| 840 | // $this->addcell(DateRecord($r, 1)); | ||
| 841 | }else{ | ||
| 842 | //$raw = $tmp['']; | ||
| 843 | if (isset($this->_columnsFormat[$column + 1])){ | ||
| 844 | $this->curformat = $this->_columnsFormat[$column + 1]; | ||
| 845 | } | ||
| 846 | $raw = $this->createNumber($spos); | ||
| 847 | $string = sprintf($this->curformat, $raw * $this->multiplier); | ||
| 848 | |||
| 849 | // $this->addcell(NumberRecord($r)); | ||
| 850 | } | ||
| 851 | $this->addcell($row, $column, $string, $raw); | ||
| 852 | //echo "Number $row $column $string\n"; | ||
| 853 | break; | ||
| 854 | case SPREADSHEET_EXCEL_READER_TYPE_FORMULA: | ||
| 855 | case SPREADSHEET_EXCEL_READER_TYPE_FORMULA2: | ||
| 856 | $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 857 | $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 858 | if ((ord($this->data[$spos+6])==0) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { | ||
| 859 | //String formula. Result follows in a STRING record | ||
| 860 | //echo "FORMULA $row $column Formula with a string<br>\n"; | ||
| 861 | } elseif ((ord($this->data[$spos+6])==1) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { | ||
| 862 | //Boolean formula. Result is in +2; 0=false,1=true | ||
| 863 | } elseif ((ord($this->data[$spos+6])==2) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { | ||
| 864 | //Error formula. Error code is in +2; | ||
| 865 | } elseif ((ord($this->data[$spos+6])==3) && (ord($this->data[$spos+12])==255) && (ord($this->data[$spos+13])==255)) { | ||
| 866 | //Formula result is a null string. | ||
| 867 | } else { | ||
| 868 | // result is a number, so first 14 bytes are just like a _NUMBER record | ||
| 869 | $tmp = unpack("ddouble", substr($this->data, $spos + 6, 8)); // It machine machine dependent | ||
| 870 | if ($this->isDate($spos)) { | ||
| 871 | list($string, $raw) = $this->createDate($tmp['double']); | ||
| 872 | // $this->addcell(DateRecord($r, 1)); | ||
| 873 | }else{ | ||
| 874 | //$raw = $tmp['']; | ||
| 875 | if (isset($this->_columnsFormat[$column + 1])){ | ||
| 876 | $this->curformat = $this->_columnsFormat[$column + 1]; | ||
| 877 | } | ||
| 878 | $raw = $this->createNumber($spos); | ||
| 879 | $string = sprintf($this->curformat, $raw * $this->multiplier); | ||
| 880 | |||
| 881 | // $this->addcell(NumberRecord($r)); | ||
| 882 | } | ||
| 883 | $this->addcell($row, $column, $string, $raw); | ||
| 884 | //echo "Number $row $column $string\n"; | ||
| 885 | } | ||
| 886 | break; | ||
| 887 | case SPREADSHEET_EXCEL_READER_TYPE_BOOLERR: | ||
| 888 | $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 889 | $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 890 | $string = ord($this->data[$spos+6]); | ||
| 891 | $this->addcell($row, $column, $string); | ||
| 892 | //echo 'Type_BOOLERR '."\n"; | ||
| 893 | break; | ||
| 894 | case SPREADSHEET_EXCEL_READER_TYPE_ROW: | ||
| 895 | case SPREADSHEET_EXCEL_READER_TYPE_DBCELL: | ||
| 896 | case SPREADSHEET_EXCEL_READER_TYPE_MULBLANK: | ||
| 897 | break; | ||
| 898 | case SPREADSHEET_EXCEL_READER_TYPE_LABEL: | ||
| 899 | $row = ord($this->data[$spos]) | ord($this->data[$spos+1])<<8; | ||
| 900 | $column = ord($this->data[$spos+2]) | ord($this->data[$spos+3])<<8; | ||
| 901 | $this->addcell($row, $column, substr($this->data, $spos + 8, ord($this->data[$spos + 6]) | ord($this->data[$spos + 7])<<8)); | ||
| 902 | |||
| 903 | // $this->addcell(LabelRecord($r)); | ||
| 904 | break; | ||
| 905 | |||
| 906 | case SPREADSHEET_EXCEL_READER_TYPE_EOF: | ||
| 907 | $cont = false; | ||
| 908 | break; | ||
| 909 | default: | ||
| 910 | //echo ' unknown :'.base_convert($r['code'],10,16)."\n"; | ||
| 911 | break; | ||
| 912 | |||
| 913 | } | ||
| 914 | $spos += $length; | ||
| 915 | } | ||
| 916 | |||
| 917 | if (!isset($this->sheets[$this->sn]['numRows'])) | ||
| 918 | $this->sheets[$this->sn]['numRows'] = $this->sheets[$this->sn]['maxrow']; | ||
| 919 | if (!isset($this->sheets[$this->sn]['numCols'])) | ||
| 920 | $this->sheets[$this->sn]['numCols'] = $this->sheets[$this->sn]['maxcol']; | ||
| 921 | |||
| 922 | } | ||
| 923 | |||
| 924 | /** | ||
| 925 | * Check whether the current record read is a date | ||
| 926 | * | ||
| 927 | * @param todo | ||
| 928 | * @return boolean True if date, false otherwise | ||
| 929 | */ | ||
| 930 | function isDate($spos) | ||
| 931 | { | ||
| 932 | //$xfindex = GetInt2d(, 4); | ||
| 933 | $xfindex = ord($this->data[$spos+4]) | ord($this->data[$spos+5]) << 8; | ||
| 934 | //echo 'check is date '.$xfindex.' '.$this->formatRecords['xfrecords'][$xfindex]['type']."\n"; | ||
| 935 | //var_dump($this->formatRecords['xfrecords'][$xfindex]); | ||
| 936 | if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'date') { | ||
| 937 | $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format']; | ||
| 938 | $this->rectype = 'date'; | ||
| 939 | return true; | ||
| 940 | } else { | ||
| 941 | if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 'number') { | ||
| 942 | $this->curformat = $this->formatRecords['xfrecords'][$xfindex]['format']; | ||
| 943 | $this->rectype = 'number'; | ||
| 944 | if (($xfindex == 0x9) || ($xfindex == 0xa)){ | ||
| 945 | $this->multiplier = 100; | ||
| 946 | } | ||
| 947 | }else{ | ||
| 948 | $this->curformat = $this->_defaultFormat; | ||
| 949 | $this->rectype = 'unknown'; | ||
| 950 | } | ||
| 951 | return false; | ||
| 952 | } | ||
| 953 | } | ||
| 954 | |||
| 955 | //}}} | ||
| 956 | //{{{ createDate() | ||
| 957 | |||
| 958 | /** | ||
| 959 | * Convert the raw Excel date into a human readable format | ||
| 960 | * | ||
| 961 | * Dates in Excel are stored as number of seconds from an epoch. On | ||
| 962 | * Windows, the epoch is 30/12/1899 and on Mac it's 01/01/1904 | ||
| 963 | * | ||
| 964 | * @access private | ||
| 965 | * @param integer The raw Excel value to convert | ||
| 966 | * @return array First element is the converted date, the second element is number a unix timestamp | ||
| 967 | */ | ||
| 968 | function createDate($numValue) | ||
| 969 | { | ||
| 970 | if ($numValue > 1) { | ||
| 971 | $utcDays = $numValue - ($this->nineteenFour ? SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS1904 : SPREADSHEET_EXCEL_READER_UTCOFFSETDAYS); | ||
| 972 | $utcValue = round(($utcDays+1) * SPREADSHEET_EXCEL_READER_MSINADAY); | ||
| 973 | $string = date ($this->curformat, $utcValue); | ||
| 974 | $raw = $utcValue; | ||
| 975 | } else { | ||
| 976 | $raw = $numValue; | ||
| 977 | $hours = floor($numValue * 24); | ||
| 978 | $mins = floor($numValue * 24 * 60) - $hours * 60; | ||
| 979 | $secs = floor($numValue * SPREADSHEET_EXCEL_READER_MSINADAY) - $hours * 60 * 60 - $mins * 60; | ||
| 980 | $string = date ($this->curformat, mktime($hours, $mins, $secs)); | ||
| 981 | } | ||
| 982 | |||
| 983 | return array($string, $raw); | ||
| 984 | } | ||
| 985 | |||
| 986 | function createNumber($spos) | ||
| 987 | { | ||
| 988 | $rknumhigh = $this->_GetInt4d($this->data, $spos + 10); | ||
| 989 | $rknumlow = $this->_GetInt4d($this->data, $spos + 6); | ||
| 990 | //for ($i=0; $i<8; $i++) { echo ord($this->data[$i+$spos+6]) . " "; } echo "<br>"; | ||
| 991 | $sign = ($rknumhigh & 0x80000000) >> 31; | ||
| 992 | $exp = ($rknumhigh & 0x7ff00000) >> 20; | ||
| 993 | $mantissa = (0x100000 | ($rknumhigh & 0x000fffff)); | ||
| 994 | $mantissalow1 = ($rknumlow & 0x80000000) >> 31; | ||
| 995 | $mantissalow2 = ($rknumlow & 0x7fffffff); | ||
| 996 | $value = $mantissa / pow( 2 , (20- ($exp - 1023))); | ||
| 997 | if ($mantissalow1 != 0) $value += 1 / pow (2 , (21 - ($exp - 1023))); | ||
| 998 | $value += $mantissalow2 / pow (2 , (52 - ($exp - 1023))); | ||
| 999 | //echo "Sign = $sign, Exp = $exp, mantissahighx = $mantissa, mantissalow1 = $mantissalow1, mantissalow2 = $mantissalow2<br>\n"; | ||
| 1000 | if ($sign) {$value = -1 * $value;} | ||
| 1001 | return $value; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | function addcell($row, $col, $string, $raw = '') | ||
| 1005 | { | ||
| 1006 | //echo "ADD cel $row-$col $string\n"; | ||
| 1007 | $this->sheets[$this->sn]['maxrow'] = max($this->sheets[$this->sn]['maxrow'], $row + $this->_rowoffset); | ||
| 1008 | $this->sheets[$this->sn]['maxcol'] = max($this->sheets[$this->sn]['maxcol'], $col + $this->_coloffset); | ||
| 1009 | $this->sheets[$this->sn]['cells'][$row + $this->_rowoffset][$col + $this->_coloffset] = $string; | ||
| 1010 | if ($raw) | ||
| 1011 | $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['raw'] = $raw; | ||
| 1012 | if (isset($this->rectype)) | ||
| 1013 | $this->sheets[$this->sn]['cellsInfo'][$row + $this->_rowoffset][$col + $this->_coloffset]['type'] = $this->rectype; | ||
| 1014 | |||
| 1015 | } | ||
| 1016 | |||
| 1017 | |||
| 1018 | function _GetIEEE754($rknum) | ||
| 1019 | { | ||
| 1020 | if (($rknum & 0x02) != 0) { | ||
| 1021 | $value = $rknum >> 2; | ||
| 1022 | } else { | ||
| 1023 | //mmp | ||
| 1024 | // first comment out the previously existing 7 lines of code here | ||
| 1025 | // $tmp = unpack("d", pack("VV", 0, ($rknum & 0xfffffffc))); | ||
| 1026 | // //$value = $tmp['']; | ||
| 1027 | // if (array_key_exists(1, $tmp)) { | ||
| 1028 | // $value = $tmp[1]; | ||
| 1029 | // } else { | ||
| 1030 | // $value = $tmp['']; | ||
| 1031 | // } | ||
| 1032 | // I got my info on IEEE754 encoding from | ||
| 1033 | // http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html | ||
| 1034 | // The RK format calls for using only the most significant 30 bits of the | ||
| 1035 | // 64 bit floating point value. The other 34 bits are assumed to be 0 | ||
| 1036 | // So, we use the upper 30 bits of $rknum as follows... | ||
| 1037 | $sign = ($rknum & 0x80000000) >> 31; | ||
| 1038 | $exp = ($rknum & 0x7ff00000) >> 20; | ||
| 1039 | $mantissa = (0x100000 | ($rknum & 0x000ffffc)); | ||
| 1040 | $value = $mantissa / pow( 2 , (20- ($exp - 1023))); | ||
| 1041 | if ($sign) {$value = -1 * $value;} | ||
| 1042 | //end of changes by mmp | ||
| 1043 | |||
| 1044 | } | ||
| 1045 | |||
| 1046 | if (($rknum & 0x01) != 0) { | ||
| 1047 | $value /= 100; | ||
| 1048 | } | ||
| 1049 | return $value; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | function _encodeUTF16($string) | ||
| 1053 | { | ||
| 1054 | $result = $string; | ||
| 1055 | if ($this->_defaultEncoding){ | ||
| 1056 | switch ($this->_encoderFunction){ | ||
| 1057 | case 'iconv' : $result = iconv('UTF-16LE', $this->_defaultEncoding, $string); | ||
| 1058 | break; | ||
| 1059 | case 'mb_convert_encoding' : $result = mb_convert_encoding($string, $this->_defaultEncoding, 'UTF-16LE' ); | ||
| 1060 | break; | ||
| 1061 | } | ||
| 1062 | } | ||
| 1063 | return $result; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | function _GetInt4d($data, $pos) | ||
| 1067 | { | ||
| 1068 | $value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24); | ||
| 1069 | if ($value>=4294967294) | ||
| 1070 | { | ||
| 1071 | $value=-2; | ||
| 1072 | } | ||
| 1073 | return $value; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | } | ||
| 1077 | |||
| 1078 | /* | ||
| 1079 | * Local variables: | ||
| 1080 | * tab-width: 4 | ||
| 1081 | * c-basic-offset: 4 | ||
| 1082 | * c-hanging-comment-ender-p: nil | ||
| 1083 | * End: | ||
| 1084 | */ | ||
| 1085 | |||
| 1086 | ?> |
-
Please register or sign in to post a comment