PageRenderTime 42ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/php/functions/Excel/oleread.php

https://bitbucket.org/cgcamilo/eraazul
PHP | 271 lines | 168 code | 58 blank | 45 comment | 35 complexity | a7d919a8a79b1978ac4bb0144c188a06 MD5 | raw file
  1. <?php
  2. define('NUM_BIG_BLOCK_DEPOT_BLOCKS_POS', 0x2c);
  3. define('SMALL_BLOCK_DEPOT_BLOCK_POS', 0x3c);
  4. define('ROOT_START_BLOCK_POS', 0x30);
  5. define('BIG_BLOCK_SIZE', 0x200);
  6. define('SMALL_BLOCK_SIZE', 0x40);
  7. define('EXTENSION_BLOCK_POS', 0x44);
  8. define('NUM_EXTENSION_BLOCK_POS', 0x48);
  9. define('PROPERTY_STORAGE_BLOCK_SIZE', 0x80);
  10. define('BIG_BLOCK_DEPOT_BLOCKS_POS', 0x4c);
  11. define('SMALL_BLOCK_THRESHOLD', 0x1000);
  12. // property storage offsets
  13. define('SIZE_OF_NAME_POS', 0x40);
  14. define('TYPE_POS', 0x42);
  15. define('START_BLOCK_POS', 0x74);
  16. define('SIZE_POS', 0x78);
  17. define('IDENTIFIER_OLE', pack("CCCCCCCC",0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1));
  18. //echo 'ROOT_START_BLOCK_POS = '.ROOT_START_BLOCK_POS."\n";
  19. //echo bin2hex($data[ROOT_START_BLOCK_POS])."\n";
  20. //echo "a=";
  21. //echo $data[ROOT_START_BLOCK_POS];
  22. //function log
  23. function GetInt4d($data, $pos)
  24. {
  25. $value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24);
  26. if ($value>=4294967294)
  27. {
  28. $value=-2;
  29. }
  30. return $value;
  31. }
  32. class OLERead {
  33. var $data = '';
  34. function OLERead(){
  35. }
  36. function read($sFileName){
  37. // check if file exist and is readable (Darko Miljanovic)
  38. if(!is_readable($sFileName)) {
  39. $this->error = 1;
  40. return false;
  41. }
  42. $this->data = @file_get_contents($sFileName);
  43. if (!$this->data) {
  44. $this->error = 1;
  45. return false;
  46. }
  47. //echo IDENTIFIER_OLE;
  48. //echo 'start';
  49. if (substr($this->data, 0, 8) != IDENTIFIER_OLE) {
  50. $this->error = 1;
  51. return false;
  52. }
  53. $this->numBigBlockDepotBlocks = GetInt4d($this->data, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
  54. $this->sbdStartBlock = GetInt4d($this->data, SMALL_BLOCK_DEPOT_BLOCK_POS);
  55. $this->rootStartBlock = GetInt4d($this->data, ROOT_START_BLOCK_POS);
  56. $this->extensionBlock = GetInt4d($this->data, EXTENSION_BLOCK_POS);
  57. $this->numExtensionBlocks = GetInt4d($this->data, NUM_EXTENSION_BLOCK_POS);
  58. /*
  59. echo $this->numBigBlockDepotBlocks." ";
  60. echo $this->sbdStartBlock." ";
  61. echo $this->rootStartBlock." ";
  62. echo $this->extensionBlock." ";
  63. echo $this->numExtensionBlocks." ";
  64. */
  65. //echo "sbdStartBlock = $this->sbdStartBlock\n";
  66. $bigBlockDepotBlocks = array();
  67. $pos = BIG_BLOCK_DEPOT_BLOCKS_POS;
  68. // echo "pos = $pos";
  69. $bbdBlocks = $this->numBigBlockDepotBlocks;
  70. if ($this->numExtensionBlocks != 0) {
  71. $bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
  72. }
  73. for ($i = 0; $i < $bbdBlocks; $i++) {
  74. $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos);
  75. $pos += 4;
  76. }
  77. for ($j = 0; $j < $this->numExtensionBlocks; $j++) {
  78. $pos = ($this->extensionBlock + 1) * BIG_BLOCK_SIZE;
  79. $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, BIG_BLOCK_SIZE / 4 - 1);
  80. for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; $i++) {
  81. $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos);
  82. $pos += 4;
  83. }
  84. $bbdBlocks += $blocksToRead;
  85. if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
  86. $this->extensionBlock = GetInt4d($this->data, $pos);
  87. }
  88. }
  89. // var_dump($bigBlockDepotBlocks);
  90. // readBigBlockDepot
  91. $pos = 0;
  92. $index = 0;
  93. $this->bigBlockChain = array();
  94. for ($i = 0; $i < $this->numBigBlockDepotBlocks; $i++) {
  95. $pos = ($bigBlockDepotBlocks[$i] + 1) * BIG_BLOCK_SIZE;
  96. //echo "pos = $pos";
  97. for ($j = 0 ; $j < BIG_BLOCK_SIZE / 4; $j++) {
  98. $this->bigBlockChain[$index] = GetInt4d($this->data, $pos);
  99. $pos += 4 ;
  100. $index++;
  101. }
  102. }
  103. //var_dump($this->bigBlockChain);
  104. //echo '=====2';
  105. // readSmallBlockDepot();
  106. $pos = 0;
  107. $index = 0;
  108. $sbdBlock = $this->sbdStartBlock;
  109. $this->smallBlockChain = array();
  110. while ($sbdBlock != -2) {
  111. $pos = ($sbdBlock + 1) * BIG_BLOCK_SIZE;
  112. for ($j = 0; $j < BIG_BLOCK_SIZE / 4; $j++) {
  113. $this->smallBlockChain[$index] = GetInt4d($this->data, $pos);
  114. $pos += 4;
  115. $index++;
  116. }
  117. $sbdBlock = $this->bigBlockChain[$sbdBlock];
  118. }
  119. // readData(rootStartBlock)
  120. $block = $this->rootStartBlock;
  121. $pos = 0;
  122. $this->entry = $this->__readData($block);
  123. /*
  124. while ($block != -2) {
  125. $pos = ($block + 1) * BIG_BLOCK_SIZE;
  126. $this->entry = $this->entry.substr($this->data, $pos, BIG_BLOCK_SIZE);
  127. $block = $this->bigBlockChain[$block];
  128. }
  129. */
  130. //echo '==='.$this->entry."===";
  131. $this->__readPropertySets();
  132. }
  133. function __readData($bl) {
  134. $block = $bl;
  135. $pos = 0;
  136. $data = '';
  137. while ($block != -2) {
  138. $pos = ($block + 1) * BIG_BLOCK_SIZE;
  139. $data = $data.substr($this->data, $pos, BIG_BLOCK_SIZE);
  140. //echo "pos = $pos data=$data\n";
  141. $block = $this->bigBlockChain[$block];
  142. }
  143. return $data;
  144. }
  145. function __readPropertySets(){
  146. $offset = 0;
  147. //var_dump($this->entry);
  148. while ($offset < strlen($this->entry)) {
  149. $d = substr($this->entry, $offset, PROPERTY_STORAGE_BLOCK_SIZE);
  150. $nameSize = ord($d[SIZE_OF_NAME_POS]) | (ord($d[SIZE_OF_NAME_POS+1]) << 8);
  151. $type = ord($d[TYPE_POS]);
  152. //$maxBlock = strlen($d) / BIG_BLOCK_SIZE - 1;
  153. $startBlock = GetInt4d($d, START_BLOCK_POS);
  154. $size = GetInt4d($d, SIZE_POS);
  155. $name = '';
  156. for ($i = 0; $i < $nameSize ; $i++) {
  157. $name .= $d[$i];
  158. }
  159. $name = str_replace("\x00", "", $name);
  160. $this->props[] = array (
  161. 'name' => $name,
  162. 'type' => $type,
  163. 'startBlock' => $startBlock,
  164. 'size' => $size);
  165. if (($name == "Workbook") || ($name == "Book")) {
  166. $this->wrkbook = count($this->props) - 1;
  167. }
  168. if ($name == "Root Entry") {
  169. $this->rootentry = count($this->props) - 1;
  170. }
  171. //echo "name ==$name=\n";
  172. $offset += PROPERTY_STORAGE_BLOCK_SIZE;
  173. }
  174. }
  175. function getWorkBook(){
  176. if ($this->props[$this->wrkbook]['size'] < SMALL_BLOCK_THRESHOLD){
  177. // getSmallBlockStream(PropertyStorage ps)
  178. $rootdata = $this->__readData($this->props[$this->rootentry]['startBlock']);
  179. $streamData = '';
  180. $block = $this->props[$this->wrkbook]['startBlock'];
  181. //$count = 0;
  182. $pos = 0;
  183. while ($block != -2) {
  184. $pos = $block * SMALL_BLOCK_SIZE;
  185. $streamData .= substr($rootdata, $pos, SMALL_BLOCK_SIZE);
  186. $block = $this->smallBlockChain[$block];
  187. }
  188. return $streamData;
  189. }else{
  190. $numBlocks = $this->props[$this->wrkbook]['size'] / BIG_BLOCK_SIZE;
  191. if ($this->props[$this->wrkbook]['size'] % BIG_BLOCK_SIZE != 0) {
  192. $numBlocks++;
  193. }
  194. if ($numBlocks == 0) return '';
  195. //echo "numBlocks = $numBlocks\n";
  196. //byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE];
  197. //print_r($this->wrkbook);
  198. $streamData = '';
  199. $block = $this->props[$this->wrkbook]['startBlock'];
  200. //$count = 0;
  201. $pos = 0;
  202. //echo "block = $block";
  203. while ($block != -2) {
  204. $pos = ($block + 1) * BIG_BLOCK_SIZE;
  205. $streamData .= substr($this->data, $pos, BIG_BLOCK_SIZE);
  206. $block = $this->bigBlockChain[$block];
  207. }
  208. //echo 'stream'.$streamData;
  209. return $streamData;
  210. }
  211. }
  212. }
  213. ?>