00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 define('OLE_PPS_TYPE_ROOT', 5);
00027 define('OLE_PPS_TYPE_DIR', 1);
00028 define('OLE_PPS_TYPE_FILE', 2);
00029 define('OLE_DATA_SIZE_SMALL', 0x1000);
00030 define('OLE_LONG_INT_SIZE', 4);
00031 define('OLE_PPS_SIZE', 0x80);
00032
00033 require_once('PEAR.php');
00034 require_once 'classes/OLE/PPS.php';
00035
00043 class OLE extends PEAR
00044 {
00049 var $_file_handle;
00050
00055 var $_list;
00056
00062 function OLE()
00063 {
00064 $this->_list = array();
00065 }
00066
00074 function read($file)
00075 {
00076
00077 $big_block_size_offset = 30;
00078 $iBdbCnt_offset = 44;
00079 $bd_start_offset = 68;
00080
00081 $fh = @fopen($file, "r");
00082 if ($fh == false) {
00083 return $this->raiseError("Can't open file $file");
00084 }
00085 $this->_file_handle = $fh;
00086
00087
00088 fseek($fh, 0);
00089 $signature = fread($fh, 8);
00090 if ("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) {
00091 return $this->raiseError("File doesn't seem to be an OLE container.");
00092 }
00093 fseek($fh, $big_block_size_offset);
00094 $packed_array = unpack("v", fread($fh, 2));
00095 $big_block_size = pow(2, $packed_array['']);
00096
00097 $packed_array = unpack("v", fread($fh, 2));
00098 $small_block_size = pow(2, $packed_array['']);
00099 $i1stBdL = ($big_block_size - 0x4C) / OLE_LONG_INT_SIZE;
00100
00101 fseek($fh, $iBdbCnt_offset);
00102 $packed_array = unpack("V", fread($fh, 4));
00103 $iBdbCnt = $packed_array[''];
00104
00105 $packed_array = unpack("V", fread($fh, 4));
00106 $pps_wk_start = $packed_array[''];
00107
00108 fseek($fh, $bd_start_offset);
00109 $packed_array = unpack("V", fread($fh, 4));
00110 $bd_start = $packed_array[''];
00111 $packed_array = unpack("V", fread($fh, 4));
00112 $bd_count = $packed_array[''];
00113 $packed_array = unpack("V", fread($fh, 4));
00114 $iAll = $packed_array[''];
00115
00116 $ret = $this->_readPpsWks($pps_wk_start, $big_block_size);
00117 if (PEAR::isError($ret)) {
00118 return $ret;
00119 }
00120 return true;
00121 }
00122
00129 function _OLE()
00130 {
00131 fclose($this->_file_handle);
00132 }
00133
00143 function _readPpsWks($pps_wk_start, $big_block_size)
00144 {
00145 $pointer = ($pps_wk_start + 1) * $big_block_size;
00146 while (1)
00147 {
00148 fseek($this->_file_handle, $pointer);
00149 $pps_wk = fread($this->_file_handle, OLE_PPS_SIZE);
00150 if (strlen($pps_wk) != OLE_PPS_SIZE) {
00151 break;
00152
00153 }
00154 $name_length = unpack("c", substr($pps_wk, 64, 2));
00155 $name_length = $name_length[''] - 2;
00156 $name = substr($pps_wk, 0, $name_length);
00157 $type = unpack("c", substr($pps_wk, 66, 1));
00158 if (($type[''] != OLE_PPS_TYPE_ROOT) and
00159 ($type[''] != OLE_PPS_TYPE_DIR) and
00160 ($type[''] != OLE_PPS_TYPE_FILE))
00161 {
00162 return $this->raiseError("PPS at $pointer has unknown type: {$type['']}");
00163 }
00164 $prev = unpack("V", substr($pps_wk, 68, 4));
00165 $next = unpack("V", substr($pps_wk, 72, 4));
00166 $dir = unpack("V", substr($pps_wk, 76, 4));
00167
00168
00169 $time_1st = substr($pps_wk, 100, 8);
00170 $time_2nd = substr($pps_wk, 108, 8);
00171 $start_block = unpack("V", substr($pps_wk, 116, 4));
00172 $size = unpack("V", substr($pps_wk, 120, 4));
00173
00174
00175 $this->_list[] = new OLE_PPS(null, '', $type[''], $prev[''], $next[''],
00176 $dir[''], OLE::OLE2LocalDate($time_1st),
00177 OLE::OLE2LocalDate($time_2nd),
00178 ($start_block[''] + 1) * $big_block_size, array());
00179
00180 $this->_list[count($this->_list) - 1]->Size = $size[''];
00181
00182 if ($this->_ppsTreeComplete(0)) {
00183 break;
00184 }
00185 $pointer += OLE_PPS_SIZE;
00186 }
00187 }
00188
00197 function _ppsTreeComplete($index)
00198 {
00199 if ($this->_list[$index]->NextPps != -1) {
00200 if (!isset($this->_list[$this->_list[$index]->NextPps])) {
00201 return false;
00202 }
00203 else {
00204 return $this->_ppsTreeComplete($this->_list[$index]->NextPps);
00205 }
00206 }
00207 if ($this->_list[$index]->DirPps != -1) {
00208 if (!isset($this->_list[$this->_list[$index]->DirPps])) {
00209 return false;
00210 }
00211 else {
00212 return $this->_ppsTreeComplete($this->_list[$index]->DirPps);
00213 }
00214 }
00215 return true;
00216 }
00217
00226 function isFile($index)
00227 {
00228 if (isset($this->_list[$index])) {
00229 return ($this->_list[$index]->Type == OLE_PPS_TYPE_FILE);
00230 }
00231 return false;
00232 }
00233
00242 function isRoot($index)
00243 {
00244 if (isset($this->_list[$index])) {
00245 return ($this->_list[$index]->Type == OLE_PPS_TYPE_ROOT);
00246 }
00247 return false;
00248 }
00249
00256 function ppsTotal()
00257 {
00258 return count($this->_list);
00259 }
00260
00272 function getData($index, $position, $length)
00273 {
00274
00275 if (!isset($this->_list[$index]) or ($position >= $this->_list[$index]->Size) or ($position < 0)) {
00276 return '';
00277 }
00278
00279 fseek($this->_file_handle, $this->_list[$index]->_data + $position);
00280 return fread($this->_file_handle, $length);
00281 }
00282
00291 function getDataLength($index)
00292 {
00293 if (isset($this->_list[$index])) {
00294 return $this->_list[$index]->Size;
00295 }
00296 return 0;
00297 }
00298
00307 function Asc2Ucs($ascii)
00308 {
00309 $rawname = '';
00310 for ($i = 0; $i < strlen($ascii); $i++) {
00311 $rawname .= $ascii{$i}."\x00";
00312 }
00313 return $rawname;
00314 }
00315
00325 function LocalDate2OLE($date = null)
00326 {
00327 if (!isset($date)) {
00328 return "\x00\x00\x00\x00\x00\x00\x00\x00";
00329 }
00330
00331
00332 $factor = pow(2,32);
00333
00334
00335 $days = 134774;
00336
00337 $big_date = $days*24*3600 + gmmktime(date("H",$date),date("i",$date),date("s",$date),
00338 date("m",$date),date("d",$date),date("Y",$date));
00339
00340 $big_date *= 10000000;
00341
00342 $high_part = floor($big_date/$factor);
00343
00344 $low_part = floor((($big_date/$factor) - $high_part)*$factor);
00345
00346
00347 $res = '';
00348
00349 for ($i=0; $i<4; $i++)
00350 {
00351 $hex = $low_part % 0x100;
00352 $res .= pack('c', $hex);
00353 $low_part /= 0x100;
00354 }
00355 for ($i=0; $i<4; $i++)
00356 {
00357 $hex = $high_part % 0x100;
00358 $res .= pack('c', $hex);
00359 $high_part /= 0x100;
00360 }
00361 return $res;
00362 }
00363
00372 function OLE2LocalDate($string)
00373 {
00374 if (strlen($string) != 8) {
00375 return new PEAR_Error("Expecting 8 byte string");
00376 }
00377
00378
00379 $factor = pow(2,32);
00380 $high_part = 0;
00381 for ($i=0; $i<4; $i++)
00382 {
00383 $al = unpack('C', $string{(7 - $i)});
00384 $high_part += $al[''];
00385 if ($i < 3) {
00386 $high_part *= 0x100;
00387 }
00388 }
00389 $low_part = 0;
00390 for ($i=4; $i<8; $i++)
00391 {
00392 $al = unpack('C', $string{(7 - $i)});
00393 $low_part += $al[''];
00394 if ($i < 7) {
00395 $low_part *= 0x100;
00396 }
00397 }
00398 $big_date = ($high_part*$factor) + $low_part;
00399
00400 $big_date /= 10000000;
00401
00402
00403 $days = 134774;
00404
00405
00406 $big_date -= $days*24*3600;
00407 return floor($big_date);
00408 }
00409 }
00410 ?>