For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
6.5 KiB

  1. <?php
  2. /**
  3. * PHPExcel_Shared_OLE_ChainedBlockStream
  4. *
  5. * Copyright (c) 2006 - 2015 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Shared_OLE
  23. * @copyright Copyright (c) 2006 - 2007 Christian Schmidt
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  26. */
  27. class PHPExcel_Shared_OLE_ChainedBlockStream
  28. {
  29. /**
  30. * The OLE container of the file that is being read.
  31. * @var OLE
  32. */
  33. public $ole;
  34. /**
  35. * Parameters specified by fopen().
  36. * @var array
  37. */
  38. public $params;
  39. /**
  40. * The binary data of the file.
  41. * @var string
  42. */
  43. public $data;
  44. /**
  45. * The file pointer.
  46. * @var int byte offset
  47. */
  48. public $pos;
  49. /**
  50. * Implements support for fopen().
  51. * For creating streams using this wrapper, use OLE_PPS_File::getStream().
  52. *
  53. * @param string $path resource name including scheme, e.g.
  54. * ole-chainedblockstream://oleInstanceId=1
  55. * @param string $mode only "r" is supported
  56. * @param int $options mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH
  57. * @param string &$openedPath absolute path of the opened stream (out parameter)
  58. * @return bool true on success
  59. */
  60. public function stream_open($path, $mode, $options, &$openedPath)
  61. {
  62. if ($mode != 'r') {
  63. if ($options & STREAM_REPORT_ERRORS) {
  64. trigger_error('Only reading is supported', E_USER_WARNING);
  65. }
  66. return false;
  67. }
  68. // 25 is length of "ole-chainedblockstream://"
  69. parse_str(substr($path, 25), $this->params);
  70. if (!isset($this->params['oleInstanceId'], $this->params['blockId'], $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']])) {
  71. if ($options & STREAM_REPORT_ERRORS) {
  72. trigger_error('OLE stream not found', E_USER_WARNING);
  73. }
  74. return false;
  75. }
  76. $this->ole = $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']];
  77. $blockId = $this->params['blockId'];
  78. $this->data = '';
  79. if (isset($this->params['size']) && $this->params['size'] < $this->ole->bigBlockThreshold && $blockId != $this->ole->root->_StartBlock) {
  80. // Block id refers to small blocks
  81. $rootPos = $this->ole->_getBlockOffset($this->ole->root->_StartBlock);
  82. while ($blockId != -2) {
  83. $pos = $rootPos + $blockId * $this->ole->bigBlockSize;
  84. $blockId = $this->ole->sbat[$blockId];
  85. fseek($this->ole->_file_handle, $pos);
  86. $this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize);
  87. }
  88. } else {
  89. // Block id refers to big blocks
  90. while ($blockId != -2) {
  91. $pos = $this->ole->_getBlockOffset($blockId);
  92. fseek($this->ole->_file_handle, $pos);
  93. $this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize);
  94. $blockId = $this->ole->bbat[$blockId];
  95. }
  96. }
  97. if (isset($this->params['size'])) {
  98. $this->data = substr($this->data, 0, $this->params['size']);
  99. }
  100. if ($options & STREAM_USE_PATH) {
  101. $openedPath = $path;
  102. }
  103. return true;
  104. }
  105. /**
  106. * Implements support for fclose().
  107. *
  108. */
  109. public function stream_close()
  110. {
  111. $this->ole = null;
  112. unset($GLOBALS['_OLE_INSTANCES']);
  113. }
  114. /**
  115. * Implements support for fread(), fgets() etc.
  116. *
  117. * @param int $count maximum number of bytes to read
  118. * @return string
  119. */
  120. public function stream_read($count)
  121. {
  122. if ($this->stream_eof()) {
  123. return false;
  124. }
  125. $s = substr($this->data, $this->pos, $count);
  126. $this->pos += $count;
  127. return $s;
  128. }
  129. /**
  130. * Implements support for feof().
  131. *
  132. * @return bool TRUE if the file pointer is at EOF; otherwise FALSE
  133. */
  134. public function stream_eof()
  135. {
  136. return $this->pos >= strlen($this->data);
  137. }
  138. /**
  139. * Returns the position of the file pointer, i.e. its offset into the file
  140. * stream. Implements support for ftell().
  141. *
  142. * @return int
  143. */
  144. public function stream_tell()
  145. {
  146. return $this->pos;
  147. }
  148. /**
  149. * Implements support for fseek().
  150. *
  151. * @param int $offset byte offset
  152. * @param int $whence SEEK_SET, SEEK_CUR or SEEK_END
  153. * @return bool
  154. */
  155. public function stream_seek($offset, $whence)
  156. {
  157. if ($whence == SEEK_SET && $offset >= 0) {
  158. $this->pos = $offset;
  159. } elseif ($whence == SEEK_CUR && -$offset <= $this->pos) {
  160. $this->pos += $offset;
  161. } elseif ($whence == SEEK_END && -$offset <= sizeof($this->data)) {
  162. $this->pos = strlen($this->data) + $offset;
  163. } else {
  164. return false;
  165. }
  166. return true;
  167. }
  168. /**
  169. * Implements support for fstat(). Currently the only supported field is
  170. * "size".
  171. * @return array
  172. */
  173. public function stream_stat()
  174. {
  175. return array(
  176. 'size' => strlen($this->data),
  177. );
  178. }
  179. // Methods used by stream_wrapper_register() that are not implemented:
  180. // bool stream_flush ( void )
  181. // int stream_write ( string data )
  182. // bool rename ( string path_from, string path_to )
  183. // bool mkdir ( string path, int mode, int options )
  184. // bool rmdir ( string path, int options )
  185. // bool dir_opendir ( string path, int options )
  186. // array url_stat ( string path, int flags )
  187. // string dir_readdir ( void )
  188. // bool dir_rewinddir ( void )
  189. // bool dir_closedir ( void )
  190. }