File indexing completed on 2024-12-22 05:33:12
0001 <?php 0002 ///////////////////////////////////////////////////////////////// 0003 /// getID3() by James Heinrich <info@getid3.org> // 0004 // available at http://getid3.sourceforge.net // 0005 // or http://www.getid3.org // 0006 // also https://github.com/JamesHeinrich/getID3 // 0007 ///////////////////////////////////////////////////////////////// 0008 // See readme.txt for more details // 0009 ///////////////////////////////////////////////////////////////// 0010 // // 0011 // module.audio-video.swf.php // 0012 // module for analyzing Shockwave Flash files // 0013 // dependencies: NONE // 0014 // /// 0015 ///////////////////////////////////////////////////////////////// 0016 0017 0018 class getid3_swf extends getid3_handler 0019 { 0020 public $ReturnAllTagData = false; 0021 0022 public function Analyze() { 0023 $info = &$this->getid3->info; 0024 0025 $info['fileformat'] = 'swf'; 0026 $info['video']['dataformat'] = 'swf'; 0027 0028 // http://www.openswf.org/spec/SWFfileformat.html 0029 0030 $this->fseek($info['avdataoffset']); 0031 0032 $SWFfileData = $this->fread($info['avdataend'] - $info['avdataoffset']); // 8 + 2 + 2 + max(9) bytes NOT including Frame_Size RECT data 0033 0034 $info['swf']['header']['signature'] = substr($SWFfileData, 0, 3); 0035 switch ($info['swf']['header']['signature']) { 0036 case 'FWS': 0037 $info['swf']['header']['compressed'] = false; 0038 break; 0039 0040 case 'CWS': 0041 $info['swf']['header']['compressed'] = true; 0042 break; 0043 0044 default: 0045 $info['error'][] = 'Expecting "FWS" or "CWS" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['swf']['header']['signature']).'"'; 0046 unset($info['swf']); 0047 unset($info['fileformat']); 0048 return false; 0049 break; 0050 } 0051 $info['swf']['header']['version'] = getid3_lib::LittleEndian2Int(substr($SWFfileData, 3, 1)); 0052 $info['swf']['header']['length'] = getid3_lib::LittleEndian2Int(substr($SWFfileData, 4, 4)); 0053 0054 if ($info['swf']['header']['compressed']) { 0055 $SWFHead = substr($SWFfileData, 0, 8); 0056 $SWFfileData = substr($SWFfileData, 8); 0057 if ($decompressed = @gzuncompress($SWFfileData)) { 0058 $SWFfileData = $SWFHead.$decompressed; 0059 } else { 0060 $info['error'][] = 'Error decompressing compressed SWF data ('.strlen($SWFfileData).' bytes compressed, should be '.($info['swf']['header']['length'] - 8).' bytes uncompressed)'; 0061 return false; 0062 } 0063 } 0064 0065 $FrameSizeBitsPerValue = (ord(substr($SWFfileData, 8, 1)) & 0xF8) >> 3; 0066 $FrameSizeDataLength = ceil((5 + (4 * $FrameSizeBitsPerValue)) / 8); 0067 $FrameSizeDataString = str_pad(decbin(ord(substr($SWFfileData, 8, 1)) & 0x07), 3, '0', STR_PAD_LEFT); 0068 for ($i = 1; $i < $FrameSizeDataLength; $i++) { 0069 $FrameSizeDataString .= str_pad(decbin(ord(substr($SWFfileData, 8 + $i, 1))), 8, '0', STR_PAD_LEFT); 0070 } 0071 list($X1, $X2, $Y1, $Y2) = explode("\n", wordwrap($FrameSizeDataString, $FrameSizeBitsPerValue, "\n", 1)); 0072 $info['swf']['header']['frame_width'] = getid3_lib::Bin2Dec($X2); 0073 $info['swf']['header']['frame_height'] = getid3_lib::Bin2Dec($Y2); 0074 0075 // http://www-lehre.informatik.uni-osnabrueck.de/~fbstark/diplom/docs/swf/Flash_Uncovered.htm 0076 // Next in the header is the frame rate, which is kind of weird. 0077 // It is supposed to be stored as a 16bit integer, but the first byte 0078 // (or last depending on how you look at it) is completely ignored. 0079 // Example: 0x000C -> 0x0C -> 12 So the frame rate is 12 fps. 0080 0081 // Byte at (8 + $FrameSizeDataLength) is always zero and ignored 0082 $info['swf']['header']['frame_rate'] = getid3_lib::LittleEndian2Int(substr($SWFfileData, 9 + $FrameSizeDataLength, 1)); 0083 $info['swf']['header']['frame_count'] = getid3_lib::LittleEndian2Int(substr($SWFfileData, 10 + $FrameSizeDataLength, 2)); 0084 0085 $info['video']['frame_rate'] = $info['swf']['header']['frame_rate']; 0086 $info['video']['resolution_x'] = intval(round($info['swf']['header']['frame_width'] / 20)); 0087 $info['video']['resolution_y'] = intval(round($info['swf']['header']['frame_height'] / 20)); 0088 $info['video']['pixel_aspect_ratio'] = (float) 1; 0089 0090 if (($info['swf']['header']['frame_count'] > 0) && ($info['swf']['header']['frame_rate'] > 0)) { 0091 $info['playtime_seconds'] = $info['swf']['header']['frame_count'] / $info['swf']['header']['frame_rate']; 0092 } 0093 //echo __LINE__.'='.number_format(microtime(true) - $start_time, 3).'<br>'; 0094 0095 0096 // SWF tags 0097 0098 $CurrentOffset = 12 + $FrameSizeDataLength; 0099 $SWFdataLength = strlen($SWFfileData); 0100 0101 while ($CurrentOffset < $SWFdataLength) { 0102 //echo __LINE__.'='.number_format(microtime(true) - $start_time, 3).'<br>'; 0103 0104 $TagIDTagLength = getid3_lib::LittleEndian2Int(substr($SWFfileData, $CurrentOffset, 2)); 0105 $TagID = ($TagIDTagLength & 0xFFFC) >> 6; 0106 $TagLength = ($TagIDTagLength & 0x003F); 0107 $CurrentOffset += 2; 0108 if ($TagLength == 0x3F) { 0109 $TagLength = getid3_lib::LittleEndian2Int(substr($SWFfileData, $CurrentOffset, 4)); 0110 $CurrentOffset += 4; 0111 } 0112 0113 unset($TagData); 0114 $TagData['offset'] = $CurrentOffset; 0115 $TagData['size'] = $TagLength; 0116 $TagData['id'] = $TagID; 0117 $TagData['data'] = substr($SWFfileData, $CurrentOffset, $TagLength); 0118 switch ($TagID) { 0119 case 0: // end of movie 0120 break 2; 0121 0122 case 9: // Set background color 0123 //$info['swf']['tags'][] = $TagData; 0124 $info['swf']['bgcolor'] = strtoupper(str_pad(dechex(getid3_lib::BigEndian2Int($TagData['data'])), 6, '0', STR_PAD_LEFT)); 0125 break; 0126 0127 default: 0128 if ($this->ReturnAllTagData) { 0129 $info['swf']['tags'][] = $TagData; 0130 } 0131 break; 0132 } 0133 0134 $CurrentOffset += $TagLength; 0135 } 0136 0137 return true; 0138 } 0139 0140 }