PageRenderTime 27ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/branches/v1.7.2/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php

#
PHP | 234 lines | 104 code | 21 blank | 109 comment | 25 complexity | ec8c970027ba677b975b41955c0e5e0e MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (C) 2006 - 2010 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. /** PHPExcel root directory */
  28. if (!defined('PHPEXCEL_ROOT')) {
  29. /**
  30. * @ignore
  31. */
  32. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../');
  33. }
  34. require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE.php';
  35. /**
  36. * PHPExcel_Shared_OLE_ChainedBlockStream
  37. *
  38. * Stream wrapper for reading data stored in an OLE file. Implements methods
  39. * for PHP's stream_wrapper_register(). For creating streams using this
  40. * wrapper, use PHPExcel_Shared_OLE_PPS_File::getStream().
  41. *
  42. * @category PHPExcel
  43. * @package PHPExcel_Shared_OLE
  44. */
  45. class PHPExcel_Shared_OLE_ChainedBlockStream
  46. {
  47. /**
  48. * The OLE container of the file that is being read.
  49. * @var OLE
  50. */
  51. public $ole;
  52. /**
  53. * Parameters specified by fopen().
  54. * @var array
  55. */
  56. public $params;
  57. /**
  58. * The binary data of the file.
  59. * @var string
  60. */
  61. public $data;
  62. /**
  63. * The file pointer.
  64. * @var int byte offset
  65. */
  66. public $pos;
  67. /**
  68. * Implements support for fopen().
  69. * For creating streams using this wrapper, use OLE_PPS_File::getStream().
  70. * @param string resource name including scheme, e.g.
  71. * ole-chainedblockstream://oleInstanceId=1
  72. * @param string only "r" is supported
  73. * @param int mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH
  74. * @param string absolute path of the opened stream (out parameter)
  75. * @return bool true on success
  76. */
  77. public function stream_open($path, $mode, $options, &$openedPath)
  78. {
  79. if ($mode != 'r') {
  80. if ($options & STREAM_REPORT_ERRORS) {
  81. trigger_error('Only reading is supported', E_USER_WARNING);
  82. }
  83. return false;
  84. }
  85. // 25 is length of "ole-chainedblockstream://"
  86. parse_str(substr($path, 25), $this->params);
  87. if (!isset($this->params['oleInstanceId'],
  88. $this->params['blockId'],
  89. $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']])) {
  90. if ($options & STREAM_REPORT_ERRORS) {
  91. trigger_error('OLE stream not found', E_USER_WARNING);
  92. }
  93. return false;
  94. }
  95. $this->ole = $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']];
  96. $blockId = $this->params['blockId'];
  97. $this->data = '';
  98. if (isset($this->params['size']) &&
  99. $this->params['size'] < $this->ole->bigBlockThreshold &&
  100. $blockId != $this->ole->root->_StartBlock) {
  101. // Block id refers to small blocks
  102. $rootPos = $this->ole->_getBlockOffset($this->ole->root->_StartBlock);
  103. while ($blockId != -2) {
  104. $pos = $rootPos + $blockId * $this->ole->bigBlockSize;
  105. $blockId = $this->ole->sbat[$blockId];
  106. fseek($this->ole->_file_handle, $pos);
  107. $this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize);
  108. }
  109. } else {
  110. // Block id refers to big blocks
  111. while ($blockId != -2) {
  112. $pos = $this->ole->_getBlockOffset($blockId);
  113. fseek($this->ole->_file_handle, $pos);
  114. $this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize);
  115. $blockId = $this->ole->bbat[$blockId];
  116. }
  117. }
  118. if (isset($this->params['size'])) {
  119. $this->data = substr($this->data, 0, $this->params['size']);
  120. }
  121. if ($options & STREAM_USE_PATH) {
  122. $openedPath = $path;
  123. }
  124. return true;
  125. }
  126. /**
  127. * Implements support for fclose().
  128. * @return string
  129. */
  130. public function stream_close()
  131. {
  132. $this->ole = null;
  133. unset($GLOBALS['_OLE_INSTANCES']);
  134. }
  135. /**
  136. * Implements support for fread(), fgets() etc.
  137. * @param int maximum number of bytes to read
  138. * @return string
  139. */
  140. public function stream_read($count)
  141. {
  142. if ($this->stream_eof()) {
  143. return false;
  144. }
  145. $s = substr($this->data, $this->pos, $count);
  146. $this->pos += $count;
  147. return $s;
  148. }
  149. /**
  150. * Implements support for feof().
  151. * @return bool TRUE if the file pointer is at EOF; otherwise FALSE
  152. */
  153. public function stream_eof()
  154. {
  155. $eof = $this->pos >= strlen($this->data);
  156. // Workaround for bug in PHP 5.0.x: http://bugs.php.net/27508
  157. if (version_compare(PHP_VERSION, '5.0', '>=') &&
  158. version_compare(PHP_VERSION, '5.1', '<')) {
  159. $eof = !$eof;
  160. }
  161. return $eof;
  162. }
  163. /**
  164. * Returns the position of the file pointer, i.e. its offset into the file
  165. * stream. Implements support for ftell().
  166. * @return int
  167. */
  168. public function stream_tell()
  169. {
  170. return $this->pos;
  171. }
  172. /**
  173. * Implements support for fseek().
  174. * @param int byte offset
  175. * @param int SEEK_SET, SEEK_CUR or SEEK_END
  176. * @return bool
  177. */
  178. public function stream_seek($offset, $whence)
  179. {
  180. if ($whence == SEEK_SET && $offset >= 0) {
  181. $this->pos = $offset;
  182. } elseif ($whence == SEEK_CUR && -$offset <= $this->pos) {
  183. $this->pos += $offset;
  184. } elseif ($whence == SEEK_END && -$offset <= sizeof($this->data)) {
  185. $this->pos = strlen($this->data) + $offset;
  186. } else {
  187. return false;
  188. }
  189. return true;
  190. }
  191. /**
  192. * Implements support for fstat(). Currently the only supported field is
  193. * "size".
  194. * @return array
  195. */
  196. public function stream_stat()
  197. {
  198. return array(
  199. 'size' => strlen($this->data),
  200. );
  201. }
  202. // Methods used by stream_wrapper_register() that are not implemented:
  203. // bool stream_flush ( void )
  204. // int stream_write ( string data )
  205. // bool rename ( string path_from, string path_to )
  206. // bool mkdir ( string path, int mode, int options )
  207. // bool rmdir ( string path, int options )
  208. // bool dir_opendir ( string path, int options )
  209. // array url_stat ( string path, int flags )
  210. // string dir_readdir ( void )
  211. // bool dir_rewinddir ( void )
  212. // bool dir_closedir ( void )
  213. }