Advertisement
krot

excel_class

Apr 8th, 2018
256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 41.81 KB | None | 0 0
  1. <?php
  2. include_once("include/utils/utils.php");
  3. define('ABC_CRITICAL',      0);
  4. define('ABC_ERROR',         1);
  5. define('ABC_ALERT',         2);
  6. define('ABC_WARNING',       3);
  7. define('ABC_NOTICE',        4);
  8. define('ABC_INFO',          5);
  9. define('ABC_DEBUG',         6);
  10. define('ABC_TRACE',         7);
  11. define('ABC_VAR_DUMP',      8);
  12. define('ABC_NO_LOG',      -1);
  13. $php_version = split( "\.", phpversion() );
  14. if( $php_version[0] == 4 && $php_version[1] <= 1 ) {
  15.     if( !function_exists('var_export') ) {
  16.         function var_export( $exp, $ret ) {
  17. ob_start();
  18. var_dump( $exp );
  19. $result = ob_get_contents();
  20. ob_end_clean();
  21. return $result;
  22. }}}function print_bt()
  23. {
  24. print "<code>\n";
  25. $cs = debug_backtrace();
  26. for( $i = 1; $i < count($cs) ; $i++ )
  27. {
  28. $item = $cs[ $i ];
  29. for( $j = 0; $j < count($item['args']); $j++ )
  30. if( is_string($item['args'][$j]) )
  31. $item['args'][$j] = "\"" . $item['args'][$j] . "\"";
  32. $args = join(",", $item['args'] );
  33. if( isset( $item['class'] ) )
  34. $str = sprintf("%s(%d): %s%s%s(%s)",
  35. $item['file'],
  36. $item['line'],
  37. $item['class'],
  38. $item['type'],
  39. $item['function'],
  40. $args );
  41. else
  42. $str = sprintf("%s(%d): %s(%s)",
  43. $item['file'],
  44. $item['line'],
  45. $item['function'],
  46. $args );
  47. echo $str . "<br>\n";
  48. }print "</code>\n";
  49. }function _die( $str )
  50. {
  51. print "Script died with reason: $str<br>\n";
  52. print_bt();
  53. exit();
  54. }class DebugOut
  55. {
  56. var $priorities = array(ABC_CRITICAL    => 'critical',
  57.                         ABC_ERROR       => 'error',
  58.                         ABC_ALERT       => 'alert',
  59.                         ABC_WARNING     => 'warning',
  60.                         ABC_NOTICE      => 'notice',
  61.                         ABC_INFO        => 'info',
  62.                         ABC_DEBUG       => 'debug',
  63.                         ABC_TRACE       => 'trace',
  64.                         ABC_VAR_DUMP        => 'dump'
  65.                         );
  66. var $_ready = false;
  67. var $_currentPriority = ABC_DEBUG;
  68. var $_consumers = array();
  69. var  $_filename;
  70. var  $_fp;
  71. var  $_logger_name;
  72.  function DebugOut($name, $logger_name, $level ){
  73.      $this->_filename = $name;
  74.      $this->_currentPriority = $level;
  75.      $this->_logger_name = $logger_name;
  76.      if ($level > ABC_NO_LOG){
  77.         $this->_openfile();
  78.      }     /*Destructor Registering*/
  79.      register_shutdown_function(array($this,"close"));
  80.  } function log($message, $priority = ABC_INFO) {
  81.         // Abort early if the priority is above the maximum logging level.
  82.         if ($priority > $this->_currentPriority) {
  83.             return false;
  84.         }        // Add to loglines array
  85.         return $this->_writeLine($message, $priority, strftime('%b %d %H:%M:%S'));
  86.  } function dump($variable,$name) {
  87.        $priority = ABC_VAR_DUMP;
  88.        if ($priority > $this->_currentPriority ) {
  89.             return false;
  90.        }       $time = strftime('%b %d %H:%M:%S');
  91.        $message = var_export($variable,true);
  92.        return fwrite($this->_fp,
  93.                      sprintf("%s %s [%s] variable %s = %s \r\n",
  94.                              $time,
  95.                              $this->_logger_name,
  96.                              $this->priorities[$priority],
  97.                              $name,
  98.                              $message)
  99.                              );
  100.  } function info($message) {
  101.         return $this->log($message, ABC_INFO);
  102.  } function debug($message) {
  103.         return $this->log($message, ABC_DEBUG);
  104.  } function notice($message) {
  105.         return $this->log($message, ABC_NOTICE);
  106.  } function warning($message) {
  107.         return $this->log($message, ABC_WARNING);
  108.  } function trace($message) {
  109.         return $this->log($message, ABC_TRACE);
  110.  } function error($message) {
  111.         return $this->log($message, ABC_ERROR);
  112.  } /**
  113.   * Writes a line to the logfile
  114.   *
  115.   * @param  string $line      The line to write
  116.   * @param  integer $priority The priority of this line/msg
  117.   * @return integer           Number of bytes written or -1 on error
  118.   * @access private
  119.   */
  120.  function _writeLine($message, $priority, $time) {
  121.     if( fwrite($this->_fp, sprintf("%s %s [%s] %s\r\n", $time, $this->_logger_name, $this->priorities[$priority], $message)) ) {
  122.         return fflush($this->_fp);
  123.     } else {
  124.         return false;
  125.     } } function _openfile() {
  126.     if (($this->_fp = @fopen($this->_filename, 'a')) == false) {
  127.         return false;
  128.     }        return true;
  129.  } function close(){
  130.     if($this->_currentPriority != ABC_NO_LOG){
  131.         $this->info("Logger stoped");
  132.         return fclose($this->_fp);
  133.     } } /*
  134.   * Managerial Functions.
  135.   *
  136.   */
  137.  function Factory($name, $logger_name, $level) {
  138.     $instance = new DebugOut($name, $logger_name, $level);
  139.     return $instance;
  140.  } function &getWriterSingleton($name, $logger_name, $level = ABC_DEBUG){
  141.       static $instances;
  142.       if (!isset($instances)){
  143.         $instances = array();
  144.       }      $signature = serialize(array($name, $level));
  145.       if (!isset($instances[$signature])) {
  146.             $instances[$signature] = DebugOut::Factory($name, $logger_name, $level);
  147.       }      
  148.       return $instances[$signature];
  149.  } function attach(&$logObserver) {
  150.     if (!is_object($logObserver)) {
  151.         return false;
  152.     }    $logObserver->_listenerID = uniqid(rand());
  153.     $this->_listeners[$logObserver->_listenerID] = &$logObserver;
  154.  }}define ('ABC_BAD_DATE', -1);
  155. class ExcelDateUtil{
  156. /*
  157.  * return 1900 Date as integer TIMESTAMP.
  158.  * for UNIX date must be
  159.  *
  160.  */
  161. function xls2tstamp($date) {
  162. $date=$date>25568?$date:25569;
  163. /*There was a bug if Converting date before 1-1-1970 (tstamp 0)*/
  164.    $ofs=(70 * 365 + 17+2) * 86400;
  165.    return ($date * 86400) - $ofs;
  166. }function getDateArray($xls_date){
  167.     $ret = array();
  168.     // leap year bug
  169.     if ($xls_date == 60) {
  170.         $ret['day']   = 29;
  171.         $ret['month'] = 2;
  172.         $ret['year']  = 1900;
  173.         return $ret;
  174.     } else if ($xls_date < 60) {
  175.         // 29-02-1900 bug
  176.         $xls_date++;
  177.     }    // Modified Julian to DMY calculation with an addition of 2415019
  178.     $l = $xls_date + 68569 + 2415019;
  179.     $n = (int)(( 4 * $l ) / 146097);
  180.     $l = $l - (int)(( 146097 * $n + 3 ) / 4);
  181.     $i = (int)(( 4000 * ( $l + 1 ) ) / 1461001);
  182.     $l = $l - (int)(( 1461 * $i ) / 4) + 31;
  183.     $j = (int)(( 80 * $l ) / 2447);
  184.     $ret['day'] = $l - (int)(( 2447 * $j ) / 80);
  185.     $l = (int)($j / 11);
  186.     $ret['month'] = $j + 2 - ( 12 * $l );
  187.     $ret['year'] = 100 * ( $n - 49 ) + $i + $l;
  188.     return $ret;
  189. }function isInternalDateFormat($format) {
  190.     $retval =false;
  191.     switch(format) {
  192.     // Internal Date Formats as described on page 427 in
  193.     // Microsoft Excel Dev's Kit...
  194.         case 0x0e:
  195.         case 0x0f:
  196.         case 0x10:
  197.         case 0x11:
  198.         case 0x12:
  199.         case 0x13:
  200.         case 0x14:
  201.         case 0x15:
  202.         case 0x16:
  203.         case 0x2d:
  204.         case 0x2e:
  205.         case 0x2f:
  206.         // Additional internal date formats found by inspection
  207.         // Using Excel v.X 10.1.0 (Mac)
  208.         case 0xa4:
  209.         case 0xa5:
  210.         case 0xa6:
  211.         case 0xa7:
  212.         case 0xa8:
  213.         case 0xa9:
  214.         case 0xaa:
  215.         case 0xab:
  216.         case 0xac:
  217.         case 0xad:
  218.         $retval = true; break;
  219.         default: $retval = false; break;
  220.     }         return $retval;
  221. }}define('EXCEL_FONT_RID',0x31);
  222. define('XF_SCRIPT_NONE',0);
  223. define('XF_SCRIPT_SUPERSCRIPT',1);
  224. define('XF_SCRIPT_SUBSCRIPT',2);
  225. define('XF_UNDERLINE_NONE',0x0);
  226. define('XF_UNDERLINE_SINGLE',0x1);
  227. define('XF_UNDERLINE_DOUBLE',0x2);
  228. define('XF_UNDERLINE_SINGLE_ACCOUNTING',0x3);
  229. define('XF_UNDERLINE_DOUBLE_ACCOUNTING',0x4);
  230. define('XF_STYLE_ITALIC', 0x2);
  231. define('XF_STYLE_STRIKEOUT', 0x8);
  232. define('XF_BOLDNESS_REGULAR',0x190);
  233. define('XF_BOLDNESS_BOLD',0x2BC);
  234. class ExcelFont {
  235.  function basicFontRecord() {
  236.     return  array('size'     => 10,
  237.                     'script'   => XF_SCRIPT_NONE,
  238.                     'undeline' => XF_UNDERLINE_NONE,
  239.                     'italic'   => false,
  240.                     'strikeout'=> false,
  241.                     'bold'     => false,
  242.                     'boldness' => XF_BOLDNESS_REGULAR,
  243.                     'palete'   => 0,
  244.                     'name'     => 'Arial');
  245.  } function getFontRecord(&$wb,$ptr) {
  246.     $retval = array('size'     => 0,
  247.                     'script'   => XF_SCRIPT_NONE,
  248.                     'undeline' => XF_UNDERLINE_NONE,
  249.                     'italic'   => false,
  250.                     'strikeout'=> false,
  251.                     'bold'     => false,
  252.                     'boldness' => XF_BOLDNESS_REGULAR,
  253.                     'palete'   => 0,
  254.                     'name'     => '');
  255.     $retval['size'] = (ord($wb[$ptr])+ 256*ord($wb[$ptr+1]))/20;
  256.     $style=ord($wb[$ptr+2]);
  257.     if (($style & XF_STYLE_ITALIC) != 0) {
  258.         $retval['italic'] = true;
  259.     }    if (($style & XF_STYLE_STRIKEOUT) != 0) {
  260.         $retval['strikeout'] = true;
  261.     }    $retval['palete'] = ord($wb[$ptr+4])+256*ord($wb[$ptr+5]);
  262.     $retval['boldness'] = ord($wb[$ptr+6])+256*ord($wb[$ptr+7]);
  263.     $retval['bold'] = $retval['boldness'] == XF_BOLDNESS_REGULAR ? false:true;
  264.     $retval['script'] =  ord($wb[$ptr+8])+256*ord($wb[$ptr+9]);
  265.     $retval['underline'] = ord($wb[$ptr+10]);
  266.     $length = ord($wb[$ptr+14]);
  267.     if($length >0) {
  268.         if(ord($wb[$ptr+15]) == 0) { // Compressed Unicode
  269.             $retval['name'] = substr($wb,$ptr+16,$length);
  270.         } else { // Uncompressed Unicode
  271.             $retval['name'] = ExcelFont::getUnicodeString($wb,$ptr+15,$length);
  272.         }    }    return $retval;
  273.  } function toString(&$record,$index) {
  274.     $retval = sprintf("Font Index = %d \nFont Size =%d\nItalic = %s\nStrikeoout=%s\nPalete=%s\nBoldness = %s Bold=%s\n Script = %d\n Underline = %d\n FontName=%s<hr>",
  275.                 $index,
  276.                 $record['size'],
  277.                 $record['italic']    == true?"true":"false",
  278.                 $record['strikeout'] == true?"true":"false",
  279.                 $record['palete'],
  280.                 $record['boldness'],
  281.                 $record['bold'] == true?"true":"false",
  282.                 $record['script'],
  283.                 $record['underline'],
  284.                 $record['name']
  285.                 );
  286.     return $retval;
  287.  } function getUnicodeString(&$string,$offset,$length) {
  288.         $bstring = "";
  289.         $index   = $offset + 1;   // start with low bits.
  290.         for ($k = 0; $k < $length; $k++)
  291.         {
  292.             $bstring = $bstring.$string[$index];
  293.             $index        += 2;
  294.         }        return substr($bstring,0,$length);
  295.  } function ExcelToCSS($rec, $app_font=true, $app_size=true, $app_italic=true, $app_bold=true){
  296.     $ret = "";
  297.     if($app_font==true){
  298.         $ret = $ret."font-family:".$rec['name']."; ";
  299.     }    if($app_size==true){
  300.         $ret = $ret."font-size:".$rec['size']."pt; ";
  301.     }    if($app_bold==true){
  302.         if($rec['bold']==true){
  303.             $ret = $ret."font-weight:bold; ";
  304.         } else {
  305.             $ret = $ret."font-weight:normal; ";
  306.         }    }    if($app_italic==true){
  307.         if($rec['italic']==true){
  308.             $ret = $ret."font-style:italic; ";
  309.         } else {
  310.             $ret = $ret."font-style:normal; ";
  311.         }    }    return $ret;
  312.  }}define ( DP_EMPTY, 0 );
  313. define ( DP_STRING_SOURCE, 1 );
  314. define ( DP_FILE_SOURCE, 2 );
  315. //------------------------------------------------------------------------
  316. class ExcelParserUtil
  317. {
  318. function str2long($str) {
  319. return ord($str[0]) + 256*(ord($str[1]) +
  320. 256*(ord($str[2]) + 256*(ord($str[3])) ));
  321. }}//------------------------------------------------------------------------
  322. class DataProvider
  323. {
  324. function DataProvider( $data, $dataType )
  325. {
  326. switch( $dataType )
  327. {
  328. case DP_FILE_SOURCE:
  329. if( !( $this->_data = @fopen( $data, "rb" )) )
  330. return;
  331. $this->_size = @filesize( $data );
  332. if( !$this->_size )
  333. _die("Failed to determine file size.");
  334. break;
  335. case DP_STRING_SOURCE:
  336. $this->_data = $data;
  337. $this->_size = strlen( $data );
  338. break;
  339. default:
  340. _die("Invalid data type provided.");
  341. }$this->_type = $dataType;
  342. register_shutdown_function( array( $this, "close") );
  343. }function get( $offset, $length )
  344. {
  345. if( !$this->isValid() )
  346. _die("Data provider is empty.");
  347. if( $this->_baseOfs + $offset + $length > $this->_size )
  348. _die("Invalid offset/length.");
  349. switch( $this->_type )
  350. {
  351. case DP_FILE_SOURCE:
  352. {
  353. if( @fseek( $this->_data, $this->_baseOfs + $offset, SEEK_SET ) == -1 )
  354. _die("Failed to seek file position specified by offest.");
  355. return @fread( $this->_data, $length );
  356. }case DP_STRING_SOURCE:
  357. {
  358. $rc = substr( $this->_data, $this->_baseOfs + $offset, $length );
  359. return $rc;
  360. }default:
  361. _die("Invalid data type or class was not initialized.");
  362. }}function getByte( $offset )
  363. {
  364. return $this->get( $offset, 1 );
  365. }function getOrd( $offset )
  366. {
  367. return ord( $this->getByte( $offset ) );
  368. }function getLong( $offset )
  369. {
  370. $str = $this->get( $offset, 4 );
  371. return ExcelParserUtil::str2long( $str );
  372. }function getSize()
  373. {
  374. if( !$this->isValid() )
  375. _die("Data provider is empty.");
  376. return $this->_size;
  377. }function getBlocks()
  378. {
  379. if( !$this->isValid() )
  380. _die("Data provider is empty.");
  381. return (int)(($this->_size - 1) / 0x200) - 1;
  382. }function ReadFromFat( $chain, $gran = 0x200 )
  383. {
  384. $rc = '';
  385. for( $i = 0; $i < count($chain); $i++ )
  386. $rc .= $this->get( $chain[$i] * $gran, $gran );
  387. return $rc;
  388. }function close()
  389. {
  390. switch($this->_type )
  391. {
  392. case DP_FILE_SOURCE:
  393. @fclose( $this->_data );
  394. case DP_STRING_SOURCE:
  395. $this->_data = null;
  396. default:
  397. $_type = DP_EMPTY;
  398. break;
  399. }}function isValid()
  400. {
  401. return $this->_type != DP_EMPTY;
  402. }var $_type = DP_EMPTY;
  403. var $_data = null;
  404. var $_size = -1;
  405. var $_baseOfs = 0;
  406. }class ExcelFileParser {
  407. var $dp = null;
  408. var $max_blocks;
  409. var $max_sblocks;
  410. // Internal variables
  411. var $fat;
  412. var $sfat;
  413. // Removed: var $sbd;
  414. // Removed: var $syear;
  415. var $formats;
  416. var $xf;
  417. var $fonts;
  418.     var $dbglog;
  419.     function ExcelFileParser($logfile="",$level=ABC_NO_LOG) {
  420. $this->dbglog = &DebugOut::getWriterSingleton($logfile,"",$level);
  421.         $this->dbglog->info("Logger started");
  422.     }function populateFormat() {
  423. $this->dbglog->trace(" populateFormat() function call");
  424. $ret = array (
  425.         0=> "General",
  426.         1=> "0",
  427.         2=> "0.00",
  428.         3=> "#,##0",
  429.         4=> "#,##0.00",
  430.         5=> "($#,##0_);($#,##0)",
  431.         6=> "($#,##0_);[Red]($#,##0)",
  432.         7=> "($#,##0.00);($#,##0.00)",
  433.         8=> "($#,##0.00_);[Red]($#,##0.00)",
  434.         9=> "0%",
  435.         0xa=> "0.00%",
  436.         0xb=> "0.00E+00",
  437.         0xc=> "# ?/?",
  438.         0xd=> "# ??/??",
  439.         0xe=> "m/d/yy",
  440.         0xf=> "d-mmm-yy",
  441.         0x10=> "d-mmm",
  442.         0x11=> "mmm-yy",
  443.         0x12=> "h:mm AM/PM",
  444.         0x13=> "h:mm:ss AM/PM",
  445.         0x14=> "h:mm",
  446.         0x15=> "h:mm:ss",
  447.         0x16=> "m/d/yy h:mm",
  448.         // 0x17 - 0x24 reserved for international and undocumented
  449.         0x17=> "0x17",
  450.         0x18=> "0x18",
  451.         0x19=> "0x19",
  452.         0x1a=> "0x1a",
  453.         0x1b=> "0x1b",
  454.         0x1c=> "0x1c",
  455.         0x1d=> "0x1d",
  456.         0x1e=> "0x1e",
  457.         0x1f=> "0x1f",
  458.         0x20=> "0x20",
  459.         0x21=> "0x21",
  460.         0x22=> "0x22",
  461.         0x23=> "0x23",
  462.         0x24=> "0x24",
  463.         // 0x17 - 0x24 reserved for international and undocumented
  464.         0x25=> "(#,##0_);(#,##0)",
  465.         0x26=> "(#,##0_);[Red](#,##0)",
  466.         0x27=> "(#,##0.00_);(#,##0.00)",
  467.         0x28=> "(#,##0.00_);[Red](#,##0.00)",
  468.         0x29=> "_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)",
  469.         0x2a=> "_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)",
  470.         0x2b=> "_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)",
  471.         0x2c=> "_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)",
  472.         0x2d=> "mm:ss",
  473.         0x2e=> "[h]:mm:ss",
  474.         0x2f=> "mm:ss.0",
  475.         0x30=> "##0.0E+0",
  476.         0x31=> "@");
  477.             $this->dbglog->dump($ret,"\$ret");
  478.             $this->dbglog->trace("populateFormat() function return");
  479.         return $ret;
  480. }function xls2tstamp($date) {
  481. $date=$date>25568?$date:25569;
  482. /*There was a bug if Converting date before 1-1-1970 (tstamp 0)*/
  483.    $ofs=(70 * 365 + 17+2) * 86400;
  484.    return ($date * 86400) - $ofs;
  485. }function getDateArray($date) {
  486.    return ExcelDateUtil::getDateArray($date);
  487. }function isDateFormat($val){
  488. $f_i=$this->xf['format'][$val];
  489. if(preg_match("/[m|d|y]/i",$this->format[$f_i])!=0){
  490.     if(strrpos($this->format[$f_i],'[')!=FALSE) {
  491.         $tmp = preg_replace("/(\[\/?)(\w+)([^\]]*\])/","'\\1'.''.'\\3'",$this->format[$f_i]);
  492.     if(preg_match("/[m|d|y]/i",$tmp)!=0)
  493.        return TRUE;
  494.      else
  495.        return FALSE;
  496.     } else {
  497.         return TRUE;
  498.     }} else
  499.   return FALSE;
  500. }function getUnicodeString($str,$ofs){
  501.    $size=0;
  502.    $i_ofs=0;
  503. /*   if (ord($str[$ofs])==255) {
  504.      $size=ord($str[$ofs])+ 256*(ord($str[$ofs+1]));
  505.      $i_ofs=2;
  506.    } else {*/
  507.      $size=ord($str[$ofs]);
  508.      $i_ofs=1;
  509. /*   }*/
  510.    return substr($str,$ofs+$i_ofs+1,$size);
  511. }function getByteString($str,$ofs){
  512.    $size=0;
  513.    $i_ofs=0;
  514. //   if (ord($str[$ofs])==255) {
  515. //     $size=ord($str[$ofs])+ 256*(ord($str[$ofs+1]));
  516. //     $i_ofs=2;
  517. //   } else {
  518.      $size=ord($str[$ofs]);
  519.      $i_ofs=1;
  520. //   }   return substr($str,$ofs+$i_ofs+1,$size);
  521. }/*
  522.  * Get blocks chain
  523.  */
  524. function get_blocks_chain($start,$small_fat=false) {
  525. $this->dbglog->trace("get_blocks_chain(".var_export($start,true).",".var_export($small_fat,true).") function call ");
  526. $chain = array();
  527. $next_block = $start;
  528. if( !$small_fat ) {
  529. while(  ($next_block!=0xfffffffe) &&
  530. ($next_block <= $this->max_blocks) &&
  531. ($next_block < count($this->fat)) )
  532. {
  533. $chain[] = $next_block;
  534. $next_block = $this->fat[$next_block];
  535. }} else {
  536. while(  ($next_block!=0xfffffffe) &&
  537. ($next_block <= $this->max_sblocks) &&
  538. ($next_block < count($this->sfat)) )
  539. {
  540. $chain[] = $next_block;
  541. $next_block = $this->sfat[$next_block];
  542. }}if( $next_block != 0xfffffffe )
  543. return false;
  544. $this->dbglog->dump($chain,"\$chain");
  545. $this->dbglog->trace("get_blocks_chain() function return");
  546. return $chain;
  547. }/* Find stream by name
  548.  *
  549.  */
  550. function find_stream( $dir, $item_name,$item_num=0) {
  551.         $this->dbglog->trace("find_stream(".var_export($dir,true).",".var_export($item_name,true).",".var_export($item_num,true).") function call ");
  552. $dt = $dir->getOrd( $item_num * 0x80 + 0x42 );
  553. $prev = $dir->getLong( $item_num * 0x80 + 0x44 );
  554. $next = $dir->getLong( $item_num * 0x80 + 0x48 );
  555. $dir_ = $dir->getLong( $item_num * 0x80 + 0x4c );
  556. $curr_name = '';
  557. if( ($dt==2) || ($dt==5) )
  558. for( $i=0;
  559.  $i < ( $dir->getOrd( $item_num * 0x80 + 0x40 ) +
  560.   256 * $dir->getOrd( $item_num * 0x80 + 0x41 ) )/2-1;
  561.  $i++ )
  562. $curr_name .= $dir->getByte( $item_num * 0x80 + $i * 2 );
  563. if( (($dt==2) || ($dt==5)) && (strcmp($curr_name,$item_name)==0) ){
  564.     $this->dbglog->trace("find_stream() function return with ".var_export($item_num,true));
  565. return $item_num;
  566. }if( $prev != 0xffffffff ) {
  567. $i = $this->find_stream( $dir, $item_name, $prev);
  568. if( $i>=0 ){
  569.     $this->dbglog->trace("find_stream() function return with ".var_export($i,true));
  570.     return $i;
  571.     }}if( $next != 0xffffffff ) {
  572. $i = $this->find_stream( $dir, $item_name, $next);
  573. if( $i>=0 ){
  574.     $this->dbglog->trace("find_stream() function return with ".var_export($i,true));
  575.     return $i;
  576. }}if( $dir_ != 0xffffffff ) {
  577. $i = $this->find_stream( $dir, $item_name, $dir_ );
  578. if( $i>=0 ) {
  579.     $this->dbglog->trace("find_stream() function return with ".var_export($i,true));
  580.     return $i;
  581. }}        $this->dbglog->trace("find_stream() function return with -1");
  582. return -1;
  583. }function rk_decode($rk) {
  584.     $this->dbglog->trace("rk_decode(".var_export($rk,true).") function call");
  585. $res = array();
  586. if( $rk & 2 ) {
  587. // integer
  588. $val = ($rk & 0xfffffffc) >> 2;
  589. if( $rk & 1 ) $val = $val / 100;
  590. if (((float)$val) == floor((float)$val)){
  591.    $res['val'] = (int)$val;
  592.    $res['type'] = 1;
  593. } else {
  594.    $res['val'] = (float)$val;
  595.    $res['type'] = 2;
  596. }} else {
  597. // float
  598. $res['type'] = 2;
  599. $frk = $rk;
  600. $fexp =  (($frk & 0x7ff00000) >> 20) - 1023;
  601. $val = 1+(($frk & 0x000fffff) >> 2)/262144;
  602. if( $fexp > 0 ) {
  603. for( $i=0; $i<$fexp; $i++ )
  604. $val *= 2;
  605. } else {
  606. if( $fexp==-1023 ) {
  607. $val=0;
  608. } else {
  609.  for( $i=0; $i<abs($fexp); $i++ )
  610. $val /= 2;
  611. }}if( $rk & 1 ) $val = $val / 100;
  612. if( $rk & 0x80000000 ) $val = -$val;
  613. $res['val'] = (float)$val;
  614. }$this->dbglog->trace("rk_decode() function returns");
  615. return $res;
  616. }// Parse worksheet
  617. //-----------------
  618. function parse_worksheet($ws) {
  619.         $this->dbglog->debug("parse_worksheet(DATA) function");
  620. if( strlen($ws) <= 0 ){
  621.     $this->dbglog->trace("parse_worksheet() function returns 7 (Data not Found)");
  622.         return 7;
  623.     }if( strlen($ws) <  4 ){
  624.     $this->dbglog->trace("parse_worksheet() function returns 6 (File Corrupted)");
  625.     return 6;
  626. }// parse workbook header
  627. if( strlen($ws) < 256*ord($ws[3])+ord($ws[2]) ) return 6;
  628. if( ord($ws[0]) != 0x09 ) return 6;
  629. $vers = ord($ws[1]);
  630. if( ($vers!=0) && ($vers!=2) && ($vers!=4) && ($vers!=8) )
  631. return 8;
  632. if( $vers!=8 ) {
  633.  $biff_ver = ($ver+4)/2;
  634. } else {
  635.  if( strlen($ws) < 12 ) return 6;
  636.  switch( ord($ws[4])+256*ord($ws[5]) ) {
  637. case 0x0500:
  638. if( ord($ws[0x0a])+256*ord($ws[0x0b]) < 1994 ) {
  639. $biff_ver = 5;
  640. } else {
  641. switch(ord( $ws[8])+256*ord($ws[9]) ) {
  642.  case 2412:
  643.  case 3218:
  644.  case 3321:
  645. /*dbg*/             $this->dbglog->debug("Parsed BIFF version is 5");
  646. $biff_ver = 5;
  647.  break;
  648.  default:
  649.     $this->dbglog->debug("Parsed BIFF version is 7");
  650. $biff_ver = 7;
  651. break;
  652. }}break;
  653. case 0x0600:
  654. /*DBG*/    $this->dbglog->debug("Parsed BIFF version is 8");
  655. $biff_ver = 8;
  656. break;
  657. default:
  658. return 8;
  659.  }}if( $biff_ver < 5 ) {
  660. /*DBG*/  $this->dbglog->debug("parse_worksheet() function found ($biff_ver < 5) return 8");
  661.   return 8;
  662. }$ptr = 0;
  663. $data = array('biff_version' => $biff_ver );
  664. while( (ord($ws[$ptr])!=0x0a) && ($ptr<strlen($ws)) ) {
  665.  switch (ord($ws[$ptr])+256*ord($ws[$ptr+1])) {
  666.   // Number
  667.   case 0x0203:
  668. /*DBG*/     $this->dbglog->trace("found NUMBER");
  669. if( ($biff_ver < 3) ){
  670. /*DBG*/         $this->dbglog->trace("$biff_ver < 3 break;");
  671.     break;
  672. }if( (ord($ws[$ptr+2])+256*ord($ws[$ptr+3])) < 14 ){
  673. /*DBG*/         $this->dbglog->debug("parse_worksheet() return 6");
  674. return 6;
  675. }$row = ord($ws[$ptr+4])+256*ord($ws[$ptr+5]);
  676. $col = ord($ws[$ptr+6])+256*ord($ws[$ptr+7]);
  677. $num_lo = ExcelParserUtil::str2long(substr($ws,$ptr+10,4));
  678. $num_hi = ExcelParserUtil::str2long(substr($ws,$ptr+14,4));
  679. $xf_i = ord($ws[$ptr+8])+256*ord($ws[$ptr+9]);
  680. if($this->isDateFormat($xf_i)){
  681. $data['cell'][$row][$col]['type'] = 3;
  682. } else {
  683. $data['cell'][$row][$col]['type'] = 2;
  684. }$fonti = $this->xf['font'][$xf_i];
  685.     $data['cell'][$row][$fc+$i]['font'] = $fonti;
  686. $fexp = (($num_hi & 0x7ff00000) >> 20) - 1023;
  687. $val = 1+(($num_hi & 0x000fffff)+$num_lo/4294967296)/1048576;
  688. if( $fexp > 0 ) {
  689. for( $i=0; $i<$fexp; $i++ )
  690. $val *= 2;
  691. } else {
  692. for( $i=0; $i<abs($fexp); $i++ )
  693. $val /= 2;
  694. }if( $num_hi & 0x80000000 ) $val = -$val;
  695. $data['cell'][$row][$col]['data'] = (float)$val;
  696. if( !isset($data['max_row']) ||
  697.     ($data['max_row'] < $row) )
  698. $data['max_row'] = $row;
  699. if( !isset($data['max_col']) ||
  700.     ($data['max_col'] < $col) )
  701. $data['max_col'] = $col;
  702. break;
  703.   // RK
  704.   case 0x027e:
  705. /*DBG*/  $this->dbglog->trace("found RK");
  706. if( ($biff_ver < 3) ) break;
  707. if( (ord($ws[$ptr+2])+256*ord($ws[$ptr+3])) < 0x0a )
  708. return 6;
  709. $row  = ord($ws[$ptr+4])+256*ord($ws[$ptr+5]);
  710. $col  = ord($ws[$ptr+6])+256*ord($ws[$ptr+7]);
  711. $xf_i = ord($ws[$ptr+8])+256*ord($ws[$ptr+9]);
  712. $val  = $this->rk_decode(
  713. ExcelParserUtil::str2long(substr($ws,$ptr+10,4))
  714. );
  715. if($this->isDateFormat($xf_i)==TRUE){
  716. $data['cell'][$row][$col]['type'] = 3;
  717. } else {
  718. $data['cell'][$row][$col]['type'] = $val['type'];
  719. }$fonti = $this->xf['font'][$xf_i];
  720.     $data['cell'][$row][$col]['font'] = $fonti;
  721. $data['cell'][$row][$col]['data'] = $val['val'];
  722. if( !isset($data['max_row']) ||
  723.     ($data['max_row'] < $row) )
  724. $data['max_row'] = $row;
  725. if( !isset($data['max_col']) ||
  726.     ($data['max_col'] < $col) )
  727. $data['max_col'] = $col;
  728. break;
  729.   // MULRK
  730.   case 0x00bd:
  731. /*DBG*/  $this->dbglog->trace("found  MULL RK");
  732. if( ($biff_ver < 5) ) break;
  733. $sz = ord($ws[$ptr+2])+256*ord($ws[$ptr+3]);
  734. if( $sz < 6 ) return 6;
  735. $row = ord($ws[$ptr+4])+256*ord($ws[$ptr+5]);
  736. $fc = ord($ws[$ptr+6])+256*ord($ws[$ptr+7]);
  737. $lc = ord($ws[$ptr+$sz+2])+256*ord($ws[$ptr+$sz+3]);
  738. for( $i=0; $i<=$lc-$fc; $i++) {
  739.  $val = $this->rk_decode(
  740. ExcelParserUtil::str2long(substr($ws,$ptr+10+$i*6,4))
  741. );
  742.    $xf_i=ord($ws[$ptr+8+$i*6])+256*ord($ws[($ptr+9+$i*6)]);
  743.    if($this->isDateFormat($xf_i)==TRUE) {
  744.    $data['cell'][$row][$fc+$i]['type'] = 3;
  745.    } else {
  746.    $data['cell'][$row][$fc+$i]['type'] = $val['type'];
  747.    }   $fonti = $this->xf['font'][$xf_i];
  748.        $data['cell'][$row][$fc+$i]['font'] = $fonti;
  749.    $data['cell'][$row][$fc+$i]['data'] = $val['val'];
  750. }if( !isset($data['max_row']) ||
  751.     ($data['max_row'] < $row) )
  752. $data['max_row'] = $row;
  753. if( !isset($data['max_col']) ||
  754.     ($data['max_col'] < $lc) )
  755. $data['max_col'] = $lc;
  756. break;
  757.   // LABEL
  758.   case 0x0204:
  759. /*DBG*/  $this->dbglog->trace("found LABEL");
  760. if( ($biff_ver < 3) ){
  761.     break;
  762. }if( (ord($ws[$ptr+2])+256*ord($ws[$ptr+3])) < 8 ){
  763. return 6;
  764. }$row = ord($ws[$ptr+4])+256*ord($ws[$ptr+5]);
  765. $col = ord($ws[$ptr+6])+256*ord($ws[$ptr+7]);
  766. $xf = ord($ws[$ptr+8])+256*ord($ws[$ptr+9]);
  767. $fonti = $this->xf['font'][$xf];
  768. $font =  $this->fonts[$fonti];
  769. $str_len = ord($ws[$ptr+10])+256*ord($ws[$ptr+11]);
  770. if( $ptr+12+$str_len > strlen($ws) )
  771. return 6;
  772. $this->sst['unicode'][] = false;
  773. $this->sst['data'][] = substr($ws,$ptr+12,$str_len);
  774. $data['cell'][$row][$col]['type'] = 0;
  775. $sst_ind = count($this->sst['data'])-1;
  776. $data['cell'][$row][$col]['data'] = $sst_ind;
  777. $data['cell'][$row][$col]['font'] = $fonti;
  778. /*echo str_replace("\n","<br>\n", ExcelFont::toString($font,$fonti));
  779.     echo "FontRecord for sting ".$this->sst['data'][$sst_ind]."<br>";*/
  780. if( !isset($data['max_row']) ||
  781.     ($data['max_row'] < $row) )
  782. $data['max_row'] = $row;
  783. if( !isset($data['max_col']) ||
  784.     ($data['max_col'] < $col) )
  785. $data['max_col'] = $col;
  786. break;
  787.   // LABELSST
  788.   case 0x00fd:
  789. if( $biff_ver < 8 ) break;
  790. if( (ord($ws[$ptr+2])+256*ord($ws[$ptr+3])) < 0x0a )
  791. return 6;
  792. $row = ord($ws[$ptr+4])+256*ord($ws[$ptr+5]);
  793. $col = ord($ws[$ptr+6])+256*ord($ws[$ptr+7]);
  794. $xf = ord($ws[$ptr+8])+256*ord($ws[$ptr+9]);
  795. $fonti = $this->xf['font'][$xf];
  796. $font = &$this->fonts[$fonti];
  797. $data['cell'][$row][$col]['type'] = 0;
  798. $sst_ind = ExcelParserUtil::str2long(substr($ws,$ptr+10,4));
  799. $data['cell'][$row][$col]['data'] = $sst_ind;
  800. $data['cell'][$row][$col]['font'] = $fonti;
  801. /*            echo "FontRecord for sting at $row,$col<br>";
  802. echo str_replace("\n","<br>\n", ExcelFont::toString($font,$fonti));*/
  803. if( !isset($data['max_row']) ||
  804.     ($data['max_row'] < $row) )
  805. $data['max_row'] = $row;
  806. if( !isset($data['max_col']) ||
  807.     ($data['max_col'] < $col) )
  808. $data['max_col'] = $col;
  809. break;
  810.   // unknown, unsupported or unused opcode
  811.   default:
  812. break;
  813.  } $ptr += 4+256*ord($ws[$ptr+3])+ord($ws[$ptr+2]);
  814. }/*DEBUG*/ $this->dbglog->debug("parse_worksheet() function returns ".var_export($data,true)); /*DEBUG*/
  815. return $data;
  816. }// Parse workbook
  817. //----------------
  818. function parse_workbook( $f_header, $dp ) {
  819. /*DBG*/ $this->dbglog->debug("parse_workbook() function");
  820. $root_entry_block = $f_header->getLong(0x30);
  821. $num_fat_blocks = $f_header->getLong(0x2c);
  822. /*TRC*/ $this->dbglog->trace("Header parsed");
  823. $this->fat = array();
  824. for( $i = 0; $i < $num_fat_blocks; $i++ ){
  825. /*TRC*/$this->dbglog->trace("FOR LOOP iteration i =".$i);
  826. $fat_block = $f_header->getLong( 0x4c + 4 * $i );
  827. $fatbuf = $dp->get( $fat_block * 0x200, 0x200 );
  828. $fat = new DataProvider( $fatbuf, DP_STRING_SOURCE );
  829. if( $fat->getSize() < 0x200 ){
  830. /*DBG*/    $this->dbglog->debug("parse_workbook() function found (strlen($fat) < 0x200) returns 6");
  831. return 6;
  832. }for( $j=0; $j<0x80; $j++ )
  833. $this->fat[] = $fat->getLong( $j * 4 );
  834. $fat->close();
  835. unset( $fat_block, $fatbuf, $fat );
  836. }/*DBG*/ $this->dbglog->dump( $this->fat, "\$fat" );
  837. if( count($this->fat) < $num_fat_blocks ) {
  838. /*DBG*/    $this->dbglog->debug("parse_workbook() function found (count($this->fat) < $num_fat_blocks) returns 6");
  839. return 6;
  840. }$chain = $this->get_blocks_chain($root_entry_block);
  841. $dir = new DataProvider( $dp->ReadFromFat( $chain ), DP_STRING_SOURCE );
  842. unset( $chain );
  843. $this->sfat = array();
  844. $small_block = $f_header->getLong( 0x3c );
  845. if( $small_block != 0xfeffffff ) {
  846. $root_entry_index = $this->find_stream( $dir, 'Root Entry');
  847. if( $root_entry_index < 0 ) {
  848. /*DBG*/    $this->dbglog->debug("parse_workbook() function dont found Root Entry returns 6");
  849.     return 6;
  850.  }
  851.  $sdc_start_block = $dir->getLong( $root_entry_index * 0x80 + 0x74 );
  852.  $small_data_chain = $this->get_blocks_chain($sdc_start_block);
  853.  $this->max_sblocks = count($small_data_chain) * 8;
  854.  
  855.  $schain = $this->get_blocks_chain($small_block);
  856.  for( $i = 0; $i < count( $schain ); $i++ ) {
  857.  
  858. $sfatbuf = $dp->get( $schain[$i] * 0x200, 0x200 );
  859. $sfat = new DataProvider( $sfatbuf, DP_STRING_SOURCE );
  860. //$this->dbglog->dump( strlen($sfatbuf), "strlen(\$sftabuf)");
  861. //$this->dbglog->dump( $sfat, "\$sfat");
  862.   if( $sfat->getSize() < 0x200 ) {
  863. /*DBG*/     $this->dbglog->debug("parse_workbook() function found (strlen($sfat) < 0x200)  returns 6");
  864.      return 6;
  865.        }      
  866.   for( $j=0; $j<0x80; $j++ )
  867.    $this->sfat[] = $sfat->getLong( $j * 4 );
  868.    
  869.    $sfat->close();
  870.    unset( $sfatbuf, $sfat );
  871.  } unset( $schain );
  872.  $sfcbuf = $dp->ReadFromFat( $small_data_chain );
  873.   $sdp = new DataProvider( $sfcbuf, DP_STRING_SOURCE );
  874.   unset( $sfcbuf, $small_data_chain );
  875. }$workbook_index = $this->find_stream( $dir, 'Workbook' );
  876. if( $workbook_index<0 ) {
  877. $workbook_index = $this->find_stream( $dir, 'Book' );
  878. if( $workbook_index<0 ){
  879. /*DBG*/        $this->dbglog->debug("parse_workbook() function workbook index not found returns 7");
  880. return 7;
  881. }}$workbook_start_block = $dir->getLong( $workbook_index * 0x80 + 0x74 );
  882. $workbook_length = $dir->getLong( $workbook_index * 0x80 + 0x78 );
  883. $wb = '';
  884. if( $workbook_length > 0 ) {
  885. if( $workbook_length >= 0x1000 ) {
  886. $chain = $this->get_blocks_chain($workbook_start_block);
  887. $wb = $dp->ReadFromFat( $chain );
  888.  } else {
  889. $chain = $this->get_blocks_chain($workbook_start_block,true);
  890. $wb = $sdp->ReadFromFat( $chain, 0x40 );
  891. unset( $sdp );
  892.  }$wb = substr($wb,0,$workbook_length);
  893. if( strlen($wb) != $workbook_length )
  894. return 6;
  895. unset( $chain );
  896. }// Unset fat arrays
  897. unset( $this->fat, $this->sfat );
  898. if( strlen($wb) <= 0 ) {
  899. /*DBG*/    $this->dbglog->debug("parse_workbook() function workbook found (strlen($wb) <= 0) returns 7");
  900.    return 7;
  901. }if( strlen($wb) <  4 ) {
  902. /*DBG*/    $this->dbglog->debug("parse_workbook() function workbook found (strlen($wb) < 4) returns 6");
  903.     return 6;
  904. }// parse workbook header
  905. if( strlen($wb) < 256*ord($wb[3])+ord($wb[2]) ){
  906. /*DBG*/ $this->dbglog->debug("parse_workbook() function workbook found (strlen($wb) < 256*ord($wb[3])+ord($wb[2])) < 4) returns 6");
  907. return 6;
  908. }if( ord($wb[0]) != 0x09 ){
  909. /*DBG*/ $this->dbglog->debug("parse_workbook() function workbook found (ord($wb[0]) != 0x09) returns 6");
  910. return 6;
  911. }$vers = ord($wb[1]);
  912. if( ($vers!=0) && ($vers!=2) && ($vers!=4) && ($vers!=8) ){
  913. return 8;
  914.         }if( $vers!=8 )
  915.  $biff_ver = ($ver+4)/2;
  916. else {
  917. if( strlen($wb) < 12 ) return 6;
  918.  switch( ord($wb[4])+256*ord($wb[5]) )
  919.  {
  920. case 0x0500:
  921. if( ord($wb[0x0a])+256*ord($wb[0x0b]) < 1994 )
  922. $biff_ver = 5;
  923. else {
  924. switch(ord( $wb[8])+256*ord($wb[9]) ) {
  925.  case 2412:
  926.  case 3218:
  927.  case 3321:
  928. $biff_ver = 5;
  929. break;
  930.  default:
  931. $biff_ver = 7;
  932. break;
  933. }}break;
  934. case 0x0600:
  935. $biff_ver = 8;
  936. break;
  937. default:
  938. return 8;
  939.  }}if( $biff_ver < 5 ) return 8;
  940. $ptr = 0;
  941. $this->worksheet['offset'] = array();
  942. $this->worksheet['options'] = array();
  943. $this->worksheet['unicode'] = array();
  944. $this->worksheet['name'] = array();
  945. $this->worksheet['data'] = array();
  946. $this->format = $this->populateFormat();
  947. $this->fonts = array();
  948. $this->fonts[0] = ExcelFont::basicFontRecord();
  949. $this->xf = array();
  950. $this->xf['format'] = array();
  951. $this->xf['font'] = array();
  952. $this->xf['type_prot'] = array();
  953. $this->xf['alignment'] = array();
  954. $this->xf['decoration'] = array();
  955. $xf_cnt=0;
  956. $this->sst['unicode'] = array();
  957. $this->sst['data'] = array();
  958. $opcode = 0;
  959. $sst_defined = false;
  960. $wblen = strlen($wb);
  961. while( (ord($wb[$ptr])!=0x0a) && ($ptr<$wblen) )
  962. {
  963. $oc = ord($wb[$ptr])+256*ord($wb[$ptr+1]);
  964. if( $oc != 0x3c )
  965. $opcode = $oc;
  966.  switch ($opcode)
  967.  {
  968.   case 0x0085:
  969. $ofs = ExcelParserUtil::str2long(substr($wb,$ptr+4,4));
  970. $this->worksheet['offset'][] = $ofs;
  971. $this->worksheet['options'][] = ord($wb[$ptr+8])+256*ord($wb[$ptr+9]);
  972. if( $biff_ver==8 ) {
  973. $len = ord($wb[$ptr+10]);
  974. if( (ord($wb[$ptr+11]) & 1) > 0 ) {
  975.  $this->worksheet['unicode'][] = true;
  976. $len = $len*2;
  977.  } else {
  978.  $this->worksheet['unicode'][] = false;
  979.  } $this->worksheet['name'][] = substr($wb,$ptr+12,$len);
  980. } else {
  981. $this->worksheet['unicode'][] = false;
  982. $len = ord($wb[$ptr+10]);
  983. $this->worksheet['name'][] = substr($wb,$ptr+11,$len);
  984. }$pws = $this->parse_worksheet(substr($wb,$ofs));
  985. if( is_array($pws) )
  986. $this->worksheet['data'][] = $pws;
  987. else
  988. return $pws;
  989. break;
  990.  // Format
  991.   case 0x041e:
  992.    $fidx = ord($wb[$ptr+4])+256*ord($wb[$ptr+5]);
  993.   if($fidx<0x31 ||$fidx==0x31 )
  994.   break;
  995.   elseif($biff_ver>7)
  996.     $this->format[$fidx] = $this->getUnicodeString($wb,$ptr+6);
  997.         break;
  998.  // FONT 0x31
  999.    case EXCEL_FONT_RID:
  1000.                 $rec = ExcelFont::getFontRecord($wb,$ptr+4);
  1001.                 $this->fonts[count($this->fonts)] = $rec;
  1002. /*echo str_replace("\n","<br>\n",ExcelFont::toString($rec,count($this->fonts)-1));
  1003. echo "FontRecord<br>" */;
  1004.         break;
  1005.  // XF
  1006.   case 0x00e0:
  1007.   $this->xf['font'][$xf_cnt] = ord($wb[$ptr+4])+256*ord($wb[$ptr+5]);
  1008.   $this->xf['format'][$xf_cnt] = ord($wb[$ptr+6])+256*ord($wb[$ptr+7]);
  1009.   $this->xf['type'][$xf_cnt]  = "1";
  1010.   $this->xf['bitmask'][$xf_cnt] = "1";
  1011.   $xf_cnt++;
  1012.         break;
  1013.   // SST
  1014.   case 0x00fc:
  1015. if( $biff_ver < 8 ) break;
  1016. $sbuflen = ord($wb[$ptr+2]) + 256*ord($wb[$ptr+3]);
  1017. if( $oc != 0x3c ) {
  1018.  if( $sst_defined ) return 6;
  1019. $snum = ExcelParserUtil::str2long(substr($wb,$ptr+8,4));
  1020. $sptr = $ptr+12;
  1021. $sst_defined = true;
  1022. } else {
  1023.  if( $rslen > $slen ) {
  1024. $sptr = $ptr+4;
  1025. $rslen -= $slen;
  1026. $slen = $rslen;
  1027. if( (ord($wb[$sptr]) & 1) > 0 ) {
  1028.  if( $char_bytes == 1 ) {
  1029.   $sstr = '';
  1030. for( $i=0; $i<strlen($str); $i++ )
  1031. $sstr .= $str[$i].chr(0);
  1032. $str = $sstr;
  1033. $char_bytes=2;
  1034.  } $schar_bytes = 2;
  1035. } else {
  1036.  $schar_bytes = 1;
  1037. }if( $sptr+$slen*$schar_bytes > $ptr+4+$sbuflen )
  1038. $slen = ($ptr+$sbuflen-$sptr+3)/$schar_bytes;
  1039. $sstr = substr($wb,$sptr+1,$slen*$schar_bytes);
  1040. if( ($char_bytes == 2) && ($schar_bytes == 1) )
  1041. {
  1042. $sstr2 = '';
  1043. for( $i=0; $i<strlen($sstr); $i++ )
  1044. $sstr2 .= $sstr[$i].chr(0);
  1045. $sstr = $sstr2;
  1046. }$str .= $sstr;
  1047. $sptr += $slen*$schar_bytes+1+4*$rt+$fesz;
  1048.  if( $slen < $rslen ) {
  1049. if( ($sptr >= strlen($wb)) ||
  1050.     ($sptr < $ptr+4+$sbuflen) ||
  1051.     (ord($wb[$sptr]) != 0x3c) )
  1052. {
  1053.     return 6;
  1054. }break;
  1055.  } else {
  1056. if( $char_bytes == 2 ) {
  1057. $this->sst['unicode'][] = true;
  1058. } else {
  1059. $this->sst['unicode'][] = false;
  1060. }$this->sst['data'][] = $str;
  1061. $snum--;
  1062.  } } else {
  1063. $sptr = $ptr+4;
  1064. if( $sptr > $ptr ) $sptr += 4*$rt+$fesz;
  1065.  }}while(  ($sptr < $ptr+4+$sbuflen) &&
  1066. ($sptr < strlen($wb)) &&
  1067. ($snum > 0) )
  1068. {
  1069.  $rslen = ord($wb[$sptr])+256*ord($wb[$sptr+1]);
  1070.  $slen = $rslen;
  1071.  if( (ord($wb[$sptr+2]) & 1) > 0 ) {
  1072. $char_bytes = 2;
  1073.  } else {
  1074. $char_bytes = 1;
  1075.  } $rt = 0;
  1076.  $fesz = 0;
  1077.  switch (ord($wb[$sptr+2]) & 0x0c) {
  1078.   // Rich-Text with Far-East
  1079.   case 0x0c:
  1080. $rt = ord($wb[$sptr+3])+256*(ord($wb[$sptr+4]));
  1081. $fesz = ExcelParserUtil::str2long(substr($wb,$sptr+5,4));
  1082. if( $sptr+9+$slen*$char_bytes > $ptr+4+$sbuflen )
  1083. $slen = ($ptr+$sbuflen-$sptr-5)/$char_bytes;
  1084. $str = substr($wb,$sptr+9,$slen*$char_bytes);
  1085. $sptr += $slen*$char_bytes+9;
  1086. break;
  1087.   // Rich-Text
  1088.   case 8:
  1089. $rt = ord($wb[$sptr+3])+256*(ord($wb[$sptr+4]));
  1090. if( $sptr+5+$slen*$char_bytes > $ptr+4+$sbuflen )
  1091. $slen = ($ptr+$sbuflen-$sptr-1)/$char_bytes;
  1092. $str = substr($wb,$sptr+5,$slen*$char_bytes);
  1093. $sptr += $slen*$char_bytes+5;
  1094. break;
  1095.   // Far-East
  1096.   case 4:
  1097. $fesz = ExcelParserUtil::str2long(substr($wb,$sptr+3,4));
  1098. if( $sptr+7+$slen*$char_bytes > $ptr+4+$sbuflen )
  1099. $slen = ($ptr+$sbuflen-$sptr-3)/$char_bytes;
  1100. $str = substr($wb,$sptr+7,$slen*$char_bytes);
  1101. $sptr += $slen*$char_bytes+7;
  1102. break;
  1103.   // Compressed or uncompressed unicode
  1104.   case 0:
  1105. if( $sptr+3+$slen*$char_bytes > $ptr+4+$sbuflen )
  1106. $slen = ($ptr+$sbuflen-$sptr+1)/$char_bytes;
  1107.  $str = substr($wb,$sptr+3,$slen*$char_bytes);
  1108.  $sptr += $slen*$char_bytes+3;
  1109. break;
  1110.  } if( $slen < $rslen ) {
  1111. if( ($sptr >= strlen($wb)) ||
  1112.     ($sptr < $ptr+4+$sbuflen) ||
  1113.     (ord($wb[$sptr]) != 0x3c) ) return 6;
  1114.  } else {
  1115. if( $char_bytes == 2 ) {
  1116. $this->sst['unicode'][] = true;
  1117. } else {
  1118. $this->sst['unicode'][] = false;
  1119. }$sptr += 4*$rt+$fesz;
  1120. $this->sst['data'][] = $str;
  1121.  $snum--;
  1122.  }} // switch
  1123. break;
  1124.  } // switch
  1125. // !!! Optimization:
  1126. //  $this->wsb[] = substr($wb,$ptr,4+256*ord($wb[$ptr+3])+ord($wb[$ptr+2]));
  1127. $ptr += 4+256*ord($wb[$ptr+3])+ord($wb[$ptr+2]);
  1128. } // while
  1129. // !!! Optimization:
  1130. //  $this->workbook = $wb;
  1131. $this->biff_version = $biff_ver;
  1132. /*DBG*/ $this->dbglog->debug("parse_workbook() function returns 0");
  1133. return 0;
  1134. }// ParseFromString & ParseFromFile
  1135. //---------------------------------
  1136. //
  1137. // IN:
  1138. //string contents - File contents
  1139. //string filename - File name of an existing Excel file.
  1140. //
  1141. // OUT:
  1142. //0 - success
  1143. //1 - can't open file
  1144. //2 - file too small to be an Excel file
  1145. //3 - error reading header
  1146. //4 - error reading file
  1147. //5 - This is not an Excel file or file stored in < Excel 5.0
  1148. //6 - file corrupted
  1149. //7 - data not found
  1150. //8 - Unsupported file version
  1151. function ParseFromString( $contents )
  1152. {
  1153. $this->dbglog->info("ParseFromString() enter.");
  1154. $this->dp = new DataProvider( $contents, DP_STRING_SOURCE );
  1155. return $this->InitParser();
  1156. }function ParseFromFile( $filename )
  1157. {
  1158. $this->dbglog->info("ParseFromFile() enter.");
  1159. $this->dp = new DataProvider( $filename, DP_FILE_SOURCE );
  1160. return $this->InitParser();
  1161. }function InitParser()
  1162. {
  1163. $this->dbglog->info("InitParser() enter.");
  1164. if( !$this->dp->isValid() )
  1165. {
  1166. $this->dbglog->error("InitParser() Failed to open file.");
  1167. $this->dbglog->error("InitParser() function returns 1");
  1168. return 1;
  1169. }if( $this->dp->getSize() <= 0x200 )
  1170. {
  1171. $this->dbglog->error("InitParser() File too small to be an Excel file.");
  1172. $this->dbglog->error("InitParser() function returns 2");
  1173. return 2;
  1174. }$this->max_blocks = $this->dp->getBlocks();
  1175. // read file header
  1176. $hdrbuf = $this->dp->get( 0, 0x200 );
  1177. if( strlen( $hdrbuf ) < 0x200 )
  1178. {
  1179. $this->dbglog->error("InitParser() Error reading header.");
  1180. $this->dbglog->error("InitParser() function returns 3");
  1181. return 3;
  1182. }// check file header
  1183. $header_sig = array(0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1);
  1184. for( $i = 0; $i < count($header_sig); $i++ )
  1185. if( $header_sig[$i] != ord( $hdrbuf[$i] ) ){
  1186. /*DBG*/        $this->dbglog->error("InitParser() function founds invalid header");
  1187. /*DBG*/        $this->dbglog->error("InitParser() function returns 5");
  1188. return 5;
  1189.             }$f_header = new DataProvider( $hdrbuf, DP_STRING_SOURCE );
  1190. unset( $hdrbuf, $header_sig, $i );
  1191. $this->dp->_baseOfs = 0x200;
  1192. $rc = $this->parse_workbook( $f_header, $this->dp );
  1193. unset( $f_header );
  1194. unset( $this->dp, $this->max_blocks, $this->max_sblocks );
  1195. return $rc;
  1196. }}function uc2html($str) {
  1197. $ret = '';
  1198. for( $i=0; $i<strlen($str)/2; $i++ ) {
  1199. $charcode = ord($str[$i*2])+256*ord($str[$i*2+1]);
  1200. $ret .= '&#'.$charcode;
  1201. }return $ret;
  1202. }
  1203. //------------------------读取Excel文件
  1204. function Read_Excel_File($ExcelFile,&$result) {
  1205. $exc = new ExcelFileParser("", ABC_NO_LOG );
  1206. $res=$exc->ParseFromFile($ExcelFile);$result=null;
  1207. switch ($res) {
  1208.     case 0: break;
  1209.     case 1: $err="无法打开文件"; break;
  1210.     case 2: $err="文件太小,可能不是Excel文件"; break;
  1211.     case 3: $err="文件头读取错误"; break;
  1212.     case 4: $err="读取文件时出错"; break;
  1213.     case 5: $err="这不是一个Excel文件或者是Excel5.0以前版本文件"; break;
  1214.     case 6: $err="文件损坏"; break;
  1215.     case 7: $err="在文件中没有发现Excel数据"; break;
  1216.     case 8: $err="不支持的文件版本"; break;
  1217.     default:
  1218.         $err="未知错误"; break;
  1219. }
  1220. for( $ws_num=0; $ws_num<count($exc->worksheet['name']); $ws_num++ )
  1221. {
  1222.     $Sheetname=$exc->worksheet['name'][$ws_num];   
  1223.     $ws = $exc->worksheet['data'][$ws_num];
  1224.     for( $j=0; $j<=$ws['max_row']; $j++ ) {
  1225.         for( $i=0; $i<=$ws['max_col']; $i++ ) {
  1226.            
  1227.            $data = $ws['cell'][$j][$i];
  1228.            
  1229.            switch ($data['type']) {
  1230.             // string
  1231.             case 0:
  1232.                 $ind = $data['data'];
  1233.                 if( $exc->sst['unicode'][$ind] ) {
  1234.                     //$s = uc2html($exc->sst['data'][$ind]);
  1235.                     $s = iconv_ec('utf-16le','utf-8',$exc->sst['data'][$ind]);
  1236.                 } else
  1237.                     $s = $exc->sst['data'][$ind];
  1238.                 if( strlen(trim($s))==0 )
  1239.                     $V="";
  1240.                 else
  1241.                     $V=$s;
  1242.                 break;
  1243.             // integer number
  1244.             case 1:
  1245.                 $V=(int)($data['data']);
  1246.                 break;
  1247.             // float number
  1248.             case 2:
  1249.                 $V=(float)($data['data']);
  1250.                 break;
  1251.             // date
  1252.             case 3:
  1253.                 $ret = $exc->getDateArray($data['data']);
  1254.                 $V=$ret['year']."-".$ret['month']."-".$ret['day']." ".$ret['hour'];
  1255.                 break;
  1256.             default:
  1257.                 break;
  1258.            }                                           
  1259.             $result[$Sheetname][$j][$i]=$V;
  1260.         }      
  1261.     }
  1262. }
  1263. if ($err=='') {return 0;} else {return $err;}
  1264. }
  1265. //------------------------建立Excel文件
  1266. function Create_Excel_File($ExcelFile,$Data) {
  1267.    
  1268. header ('Content-type: application/x-msexcel');
  1269. header ("Content-Disposition: attachment; filename=$ExcelFile" );  
  1270. function xlsBOF() {
  1271.     echo pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);  
  1272.     return;
  1273. }
  1274. function xlsEOF() {
  1275.     echo pack("ss", 0x0A, 0x00);
  1276.     return;
  1277. }
  1278. function xlsWriteNumber($Row, $Col, $Value) {
  1279.     echo pack("sssss", 0x203, 14, $Row, $Col, 0x0);
  1280.     echo pack("d", $Value);
  1281.     return;
  1282. }
  1283. function xlsWriteLabel($Row, $Col, $Value ) {
  1284.     $L = strlen($Value);
  1285.     echo pack("ssssss", 0x204, 8 + $L, $Row, $Col, 0x0, $L);
  1286.     echo $Value;
  1287. return;
  1288. }
  1289. xlsBOF();
  1290. for ($i=0;$i<count($Data[0]);$i++)
  1291. {
  1292.     for ($j=0;$j<count($Data);$j++)
  1293.     {
  1294.         $v=$Data[$j][$i];      
  1295.        
  1296.         xlsWriteLabel($j,$i,$v);
  1297.     }
  1298. }
  1299. xlsEOF();
  1300. }
  1301. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement