[ Index ] |
PHP Cross Reference of phpwcms V1.4.7 _r403 (01.11.10) |
[Summary view] [Print] [Text view]
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 3 // +----------------------------------------------------------------------+ 4 // | PHP Version 4 | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2002 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 of the PHP license, | 9 // | that is bundled with this package in the file LICENSE, and is | 10 // | available at through the world-wide-web at | 11 // | http://www.php.net/license/2_02.txt. | 12 // | If you did not receive a copy of the PHP license and are unable to | 13 // | obtain it through the world-wide-web, please send a note to | 14 // | license@php.net so we can mail you a copy immediately. | 15 // +----------------------------------------------------------------------+ 16 // | Author: Xavier Noguer <xnoguer@php.net> | 17 // | Based on OLE::Storage_Lite by Kawai, Takanori | 18 // +----------------------------------------------------------------------+ 19 // 20 // $Id: OLE.php,v 1.7 2003/08/21 15:15:40 xnoguer Exp $ 21 22 23 /** 24 * Constants for OLE package 25 */ 26 define('OLE_PPS_TYPE_ROOT', 5); 27 define('OLE_PPS_TYPE_DIR', 1); 28 define('OLE_PPS_TYPE_FILE', 2); 29 define('OLE_DATA_SIZE_SMALL', 0x1000); 30 define('OLE_LONG_INT_SIZE', 4); 31 define('OLE_PPS_SIZE', 0x80); 32 33 require_once('PEAR.php'); 34 require_once 'OLE/PPS.php'; 35 36 /** 37 * OLE package base class. 38 * 39 * @author Xavier Noguer <xnoguer@php.net> 40 * @category Structures 41 * @package OLE 42 */ 43 class OLE extends PEAR 44 { 45 /** 46 * The file handle for reading an OLE container 47 * @var resource 48 */ 49 var $_file_handle; 50 51 /** 52 * Array of PPS's found on the OLE container 53 * @var array 54 */ 55 var $_list; 56 57 /** 58 * Creates a new OLE object 59 * Remember to use ampersand when creating an OLE object ($my_ole =& new OLE();) 60 * @access public 61 */ 62 function OLE() 63 { 64 $this->_list = array(); 65 } 66 67 /** 68 * Reads an OLE container from the contents of the file given. 69 * 70 * @acces public 71 * @param string $file 72 * @return mixed true on success, PEAR_Error on failure 73 */ 74 function read($file) 75 { 76 /* consider storing offsets as constants */ 77 $big_block_size_offset = 30; 78 $iBdbCnt_offset = 44; 79 $bd_start_offset = 68; 80 81 $fh = @fopen($file, "r"); 82 if ($fh == false) { 83 return $this->raiseError("Can't open file $file"); 84 } 85 $this->_file_handle = $fh; 86 87 /* begin reading OLE attributes */ 88 fseek($fh, 0); 89 $signature = fread($fh, 8); 90 if ("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) { 91 return $this->raiseError("File doesn't seem to be an OLE container."); 92 } 93 fseek($fh, $big_block_size_offset); 94 $packed_array = unpack("v", fread($fh, 2)); 95 $big_block_size = pow(2, $packed_array['']); 96 97 $packed_array = unpack("v", fread($fh, 2)); 98 $small_block_size = pow(2, $packed_array['']); 99 $i1stBdL = ($big_block_size - 0x4C) / OLE_LONG_INT_SIZE; 100 101 fseek($fh, $iBdbCnt_offset); 102 $packed_array = unpack("V", fread($fh, 4)); 103 $iBdbCnt = $packed_array['']; 104 105 $packed_array = unpack("V", fread($fh, 4)); 106 $pps_wk_start = $packed_array['']; 107 108 fseek($fh, $bd_start_offset); 109 $packed_array = unpack("V", fread($fh, 4)); 110 $bd_start = $packed_array['']; 111 $packed_array = unpack("V", fread($fh, 4)); 112 $bd_count = $packed_array['']; 113 $packed_array = unpack("V", fread($fh, 4)); 114 $iAll = $packed_array['']; // this may be wrong 115 /* create OLE_PPS objects from */ 116 $ret = $this->_readPpsWks($pps_wk_start, $big_block_size); 117 if (PEAR::isError($ret)) { 118 return $ret; 119 } 120 return true; 121 } 122 123 /** 124 * Destructor (using PEAR) 125 * Just closes the file handle on the OLE file. 126 * 127 * @access private 128 */ 129 function _OLE() 130 { 131 fclose($this->_file_handle); 132 } 133 134 /** 135 * Gets information about all PPS's on the OLE container from the PPS WK's 136 * creates an OLE_PPS object for each one. 137 * 138 * @access private 139 * @param integer $pps_wk_start Position inside the OLE file where PPS WK's start 140 * @param integer $big_block_size Size of big blobks in the OLE file 141 * @return mixed true on success, PEAR_Error on failure 142 */ 143 function _readPpsWks($pps_wk_start, $big_block_size) 144 { 145 $pointer = ($pps_wk_start + 1) * $big_block_size; 146 while (1) 147 { 148 fseek($this->_file_handle, $pointer); 149 $pps_wk = fread($this->_file_handle, OLE_PPS_SIZE); 150 if (strlen($pps_wk) != OLE_PPS_SIZE) { 151 break; // Excel likes to add a trailing byte sometimes 152 //return $this->raiseError("PPS at $pointer seems too short: ".strlen($pps_wk)); 153 } 154 $name_length = unpack("c", substr($pps_wk, 64, 2)); // FIXME (2 bytes??) 155 $name_length = $name_length[''] - 2; 156 $name = substr($pps_wk, 0, $name_length); 157 $type = unpack("c", substr($pps_wk, 66, 1)); 158 if (($type[''] != OLE_PPS_TYPE_ROOT) and 159 ($type[''] != OLE_PPS_TYPE_DIR) and 160 ($type[''] != OLE_PPS_TYPE_FILE)) 161 { 162 return $this->raiseError("PPS at $pointer has unknown type: {$type['']}"); 163 } 164 $prev = unpack("V", substr($pps_wk, 68, 4)); 165 $next = unpack("V", substr($pps_wk, 72, 4)); 166 $dir = unpack("V", substr($pps_wk, 76, 4)); 167 // there is no magic number, it can take different values. 168 //$magic = unpack("V", strrev(substr($pps_wk, 92, 4))); 169 $time_1st = substr($pps_wk, 100, 8); 170 $time_2nd = substr($pps_wk, 108, 8); 171 $start_block = unpack("V", substr($pps_wk, 116, 4)); 172 $size = unpack("V", substr($pps_wk, 120, 4)); 173 // _data member will point to position in file!! 174 // OLE_PPS object is created with an empty children array!! 175 $this->_list[] = new OLE_PPS(null, '', $type[''], $prev[''], $next[''], 176 $dir[''], OLE::OLE2LocalDate($time_1st), 177 OLE::OLE2LocalDate($time_2nd), 178 ($start_block[''] + 1) * $big_block_size, array()); 179 // give it a size 180 $this->_list[count($this->_list) - 1]->Size = $size['']; 181 // check if the PPS tree (starting from root) is complete 182 if ($this->_ppsTreeComplete(0)) { 183 break; 184 } 185 $pointer += OLE_PPS_SIZE; 186 } 187 } 188 189 /** 190 * It checks whether the PPS tree is complete (all PPS's read) 191 * starting with the given PPS (not necessarily root) 192 * 193 * @access private 194 * @param integer $index The index of the PPS from which we are checking 195 * @return boolean Whether the PPS tree for the given PPS is complete 196 */ 197 function _ppsTreeComplete($index) 198 { 199 if ($this->_list[$index]->NextPps != -1) { 200 if (!isset($this->_list[$this->_list[$index]->NextPps])) { 201 return false; 202 } 203 else { 204 return $this->_ppsTreeComplete($this->_list[$index]->NextPps); 205 } 206 } 207 if ($this->_list[$index]->DirPps != -1) { 208 if (!isset($this->_list[$this->_list[$index]->DirPps])) { 209 return false; 210 } 211 else { 212 return $this->_ppsTreeComplete($this->_list[$index]->DirPps); 213 } 214 } 215 return true; 216 } 217 218 /** 219 * Checks whether a PPS is a File PPS or not. 220 * If there is no PPS for the index given, it will return false. 221 * 222 * @access public 223 * @param integer $index The index for the PPS 224 * @return bool true if it's a File PPS, false otherwise 225 */ 226 function isFile($index) 227 { 228 if (isset($this->_list[$index])) { 229 return ($this->_list[$index]->Type == OLE_PPS_TYPE_FILE); 230 } 231 return false; 232 } 233 234 /** 235 * Checks whether a PPS is a Root PPS or not. 236 * If there is no PPS for the index given, it will return false. 237 * 238 * @access public 239 * @param integer $index The index for the PPS. 240 * @return bool true if it's a Root PPS, false otherwise 241 */ 242 function isRoot($index) 243 { 244 if (isset($this->_list[$index])) { 245 return ($this->_list[$index]->Type == OLE_PPS_TYPE_ROOT); 246 } 247 return false; 248 } 249 250 /** 251 * Gives the total number of PPS's found in the OLE container. 252 * 253 * @access public 254 * @return integer The total number of PPS's found in the OLE container 255 */ 256 function ppsTotal() 257 { 258 return count($this->_list); 259 } 260 261 /** 262 * Gets data from a PPS 263 * If there is no PPS for the index given, it will return an empty string. 264 * 265 * @access public 266 * @param integer $index The index for the PPS 267 * @param integer $position The position from which to start reading 268 * (relative to the PPS) 269 * @param integer $length The amount of bytes to read (at most) 270 * @return string The binary string containing the data requested 271 */ 272 function getData($index, $position, $length) 273 { 274 // if position is not valid return empty string 275 if (!isset($this->_list[$index]) or ($position >= $this->_list[$index]->Size) or ($position < 0)) { 276 return ''; 277 } 278 // Beware!!! _data member is actually a position 279 fseek($this->_file_handle, $this->_list[$index]->_data + $position); 280 return fread($this->_file_handle, $length); 281 } 282 283 /** 284 * Gets the data length from a PPS 285 * If there is no PPS for the index given, it will return 0. 286 * 287 * @access public 288 * @param integer $index The index for the PPS 289 * @return integer The amount of bytes in data the PPS has 290 */ 291 function getDataLength($index) 292 { 293 if (isset($this->_list[$index])) { 294 return $this->_list[$index]->Size; 295 } 296 return 0; 297 } 298 299 /** 300 * Utility function to transform ASCII text to Unicode 301 * 302 * @access public 303 * @static 304 * @param string $ascii The ASCII string to transform 305 * @return string The string in Unicode 306 */ 307 function Asc2Ucs($ascii) 308 { 309 $rawname = ''; 310 for ($i = 0; $i < strlen($ascii); $i++) { 311 $rawname .= $ascii{$i}."\x00"; 312 } 313 return $rawname; 314 } 315 316 /** 317 * Utility function 318 * Returns a string for the OLE container with the date given 319 * 320 * @access public 321 * @static 322 * @param integer $date A timestamp 323 * @return string The string for the OLE container 324 */ 325 function LocalDate2OLE($date = null) 326 { 327 if (!isset($date)) { 328 return "\x00\x00\x00\x00\x00\x00\x00\x00"; 329 } 330 331 // factor used for separating numbers into 4 bytes parts 332 $factor = pow(2,32); 333 334 // days from 1-1-1601 until the beggining of UNIX era 335 $days = 134774; 336 // calculate seconds 337 $big_date = $days*24*3600 + gmmktime(date("H",$date),date("i",$date),date("s",$date), 338 date("m",$date),date("d",$date),date("Y",$date)); 339 // multiply just to make MS happy 340 $big_date *= 10000000; 341 342 $high_part = floor($big_date/$factor); 343 // lower 4 bytes 344 $low_part = floor((($big_date/$factor) - $high_part)*$factor); 345 346 // Make HEX string 347 $res = ''; 348 349 for ($i=0; $i<4; $i++) 350 { 351 $hex = $low_part % 0x100; 352 $res .= pack('c', $hex); 353 $low_part /= 0x100; 354 } 355 for ($i=0; $i<4; $i++) 356 { 357 $hex = $high_part % 0x100; 358 $res .= pack('c', $hex); 359 $high_part /= 0x100; 360 } 361 return $res; 362 } 363 364 /** 365 * Returns a timestamp from an OLE container's date 366 * 367 * @access public 368 * @static 369 * @param integer $string A binary string with the encoded date 370 * @return string The timestamp corresponding to the string 371 */ 372 function OLE2LocalDate($string) 373 { 374 if (strlen($string) != 8) { 375 return new PEAR_Error("Expecting 8 byte string"); 376 } 377 378 // factor used for separating numbers into 4 bytes parts 379 $factor = pow(2,32); 380 $high_part = 0; 381 for ($i=0; $i<4; $i++) 382 { 383 $al = unpack('C', $string{(7 - $i)}); 384 $high_part += $al['']; 385 if ($i < 3) { 386 $high_part *= 0x100; 387 } 388 } 389 $low_part = 0; 390 for ($i=4; $i<8; $i++) 391 { 392 $al = unpack('C', $string{(7 - $i)}); 393 $low_part += $al['']; 394 if ($i < 7) { 395 $low_part *= 0x100; 396 } 397 } 398 $big_date = ($high_part*$factor) + $low_part; 399 // translate to seconds 400 $big_date /= 10000000; 401 402 // days from 1-1-1601 until the beggining of UNIX era 403 $days = 134774; 404 405 // translate to seconds from beggining of UNIX era 406 $big_date -= $days*24*3600; 407 return floor($big_date); 408 } 409 } 410 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Nov 16 22:51:00 2010 | Cross-referenced by PHPXref 0.7 |