diff options
author | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2006-01-02 01:06:06 +0000 |
---|---|---|
committer | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2006-01-02 01:06:06 +0000 |
commit | 83f3c4114164617f48f3b013027f9079ddc2675c (patch) | |
tree | 3fc5ba313a14992eb3683e2a2e46c095fc7a8f7f /modules/id3/getid3 | |
parent | 5c2efb82b74874e5f7220cb1a00479c009d9221b (diff) | |
download | ampache-83f3c4114164617f48f3b013027f9079ddc2675c.tar.gz ampache-83f3c4114164617f48f3b013027f9079ddc2675c.tar.bz2 ampache-83f3c4114164617f48f3b013027f9079ddc2675c.zip |
updated registration mojo thx pb1dft also some fluf updates
Diffstat (limited to 'modules/id3/getid3')
-rw-r--r-- | modules/id3/getid3/getid3.php | 140 | ||||
-rw-r--r-- | modules/id3/getid3/module.audio-video.asf.php | 9 | ||||
-rw-r--r-- | modules/id3/getid3/module.audio-video.flv.php | 210 | ||||
-rw-r--r-- | modules/id3/getid3/module.audio-video.riff.php | 4 | ||||
-rw-r--r-- | modules/id3/getid3/module.audio.mp3.php | 33 | ||||
-rw-r--r-- | modules/id3/getid3/module.tag.id3v2.php | 88 | ||||
-rw-r--r-- | modules/id3/getid3/write.id3v2.php | 1 | ||||
-rw-r--r-- | modules/id3/getid3/write.php | 8 | ||||
-rw-r--r-- | modules/id3/getid3/write.real.php | 251 |
9 files changed, 568 insertions, 176 deletions
diff --git a/modules/id3/getid3/getid3.php b/modules/id3/getid3/getid3.php index e87fcfb6..d0a8d479 100644 --- a/modules/id3/getid3/getid3.php +++ b/modules/id3/getid3/getid3.php @@ -10,7 +10,7 @@ ///////////////////////////////////////////////////////////////// // Defines -define('GETID3_VERSION', '1.7.4'); +define('GETID3_VERSION', '1.7.5-200512251515'); define('GETID3_FREAD_BUFFER_SIZE', 16384); // read buffer size in bytes @@ -111,26 +111,40 @@ class getID3 // ie for "C:/Program Files/Apache/" put "C:/PROGRA~1/APACHE/" // IMPORTANT: This path must include the trailing slash if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) { - $helperappsdir = GETID3_INCLUDEPATH.'..'.GETID3_OS_DIRSLASH.'helperapps'; // must not have any space in this path if (!is_dir($helperappsdir)) { + $this->startup_error .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'; + } elseif (strpos(realpath($helperappsdir), ' ') !== false) { + $DirPieces = explode(GETID3_OS_DIRSLASH, realpath($helperappsdir)); - foreach ($DirPieces as $key => $value) { - if ((strpos($value, '.') !== false) && (strpos($value, ' ') === false)) { - if (strpos($value, '.') > 8) { - $value = substr($value, 0, 6).'~1'; - } - } elseif ((strpos($value, ' ') !== false) || strlen($value) > 8) { - $value = substr($value, 0, 6).'~1'; - } - $DirPieces[$key] = strtoupper($value); - } - $this->startup_error .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary (on this server that would be something like "'.implode(GETID3_OS_DIRSLASH, $DirPieces).'" - NOTE: this may or may not be the actual 8.3 equivalent of "'.$helperappsdir.'", please double-check). You can run "dir /x" from the commandline to see the correct 8.3-style names. You need to edit the file "'.GETID3_INCLUDEPATH.'/getid3.php" around line '.(__LINE__ - 16); + $DirPieces8 = $DirPieces;
+
+ $CLIdir = $DirPieces[0].' && cd \\';
+ for ($i = 1; $i < count($DirPieces); $i++) {
+ if (strpos($DirPieces[$i], ' ') === false) {
+ $CLIdir .= ' && cd '.$DirPieces[$i];
+ } else {
+ ob_start();
+ system($CLIdir.' && dir /ad /x');
+ $subdirsraw = explode("\n", ob_get_contents());
+ ob_end_clean();
+ foreach ($subdirsraw as $line) {
+ if (eregi('^[0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [AP]M <DIR> ([^ ]{8}) '.preg_quote($DirPieces[$i]).'$', trim($line), $matches)) {
+ $CLIdir .= ' && cd '.$matches[1];
+ break;
+ }
+ }
+ $DirPieces8[$i] = $matches[1];
+ }
+ }
+ $helperappsdir = implode(GETID3_OS_DIRSLASH, $DirPieces8); + } define('GETID3_HELPERAPPSDIR', realpath($helperappsdir).GETID3_OS_DIRSLASH); + } } @@ -436,7 +450,7 @@ class getID3 'group' => 'audio', 'module' => 'ac3', 'mime_type' => 'audio/ac3', - ), + ), // AAC - audio - Advanced Audio Coding (AAC) - ADIF format 'adif' => array( @@ -446,7 +460,7 @@ class getID3 'option' => 'adif', 'mime_type' => 'application/octet-stream', 'fail_ape' => 'WARNING', - ), + ), // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3) @@ -457,7 +471,7 @@ class getID3 'option' => 'adts', 'mime_type' => 'application/octet-stream', 'fail_ape' => 'WARNING', - ), + ), // AU - audio - NeXT/Sun AUdio (AU) @@ -466,7 +480,7 @@ class getID3 'group' => 'audio', 'module' => 'au', 'mime_type' => 'audio/basic', - ), + ), // AVR - audio - Audio Visual Research 'avr' => array( @@ -474,7 +488,7 @@ class getID3 'group' => 'audio', 'module' => 'avr', 'mime_type' => 'application/octet-stream', - ), + ), // BONK - audio - Bonk v0.9+ 'bonk' => array( @@ -482,7 +496,7 @@ class getID3 'group' => 'audio', 'module' => 'bonk', 'mime_type' => 'audio/xmms-bonk', - ), + ), // FLAC - audio - Free Lossless Audio Codec 'flac' => array( @@ -490,7 +504,7 @@ class getID3 'group' => 'audio', 'module' => 'flac', 'mime_type' => 'audio/x-flac', - ), + ), // LA - audio - Lossless Audio (LA) 'la' => array( @@ -498,7 +512,7 @@ class getID3 'group' => 'audio', 'module' => 'la', 'mime_type' => 'application/octet-stream', - ), + ), // LPAC - audio - Lossless Predictive Audio Compression (LPAC) 'lpac' => array( @@ -506,7 +520,7 @@ class getID3 'group' => 'audio', 'module' => 'lpac', 'mime_type' => 'application/octet-stream', - ), + ), // MIDI - audio - MIDI (Musical Instrument Digital Interface) 'midi' => array( @@ -514,7 +528,7 @@ class getID3 'group' => 'audio', 'module' => 'midi', 'mime_type' => 'audio/midi', - ), + ), // MAC - audio - Monkey's Audio Compressor 'mac' => array( @@ -522,7 +536,7 @@ class getID3 'group' => 'audio', 'module' => 'monkey', 'mime_type' => 'application/octet-stream', - ), + ), // MOD - audio - MODule (assorted sub-formats) 'mod' => array( @@ -531,7 +545,7 @@ class getID3 'module' => 'mod', 'option' => 'mod', 'mime_type' => 'audio/mod', - ), + ), // MOD - audio - MODule (Impulse Tracker) 'it' => array( @@ -540,7 +554,7 @@ class getID3 'module' => 'mod', 'option' => 'it', 'mime_type' => 'audio/it', - ), + ), // MOD - audio - MODule (eXtended Module, various sub-formats) 'xm' => array( @@ -549,7 +563,7 @@ class getID3 'module' => 'mod', 'option' => 'xm', 'mime_type' => 'audio/xm', - ), + ), // MOD - audio - MODule (ScreamTracker) 's3m' => array( @@ -558,7 +572,7 @@ class getID3 'module' => 'mod', 'option' => 's3m', 'mime_type' => 'audio/s3m', - ), + ), // MPC - audio - Musepack / MPEGplus 'mpc' => array( @@ -566,7 +580,7 @@ class getID3 'group' => 'audio', 'module' => 'mpc', 'mime_type' => 'application/octet-stream', - ), + ), // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS) 'mp3' => array( @@ -574,7 +588,7 @@ class getID3 'group' => 'audio', 'module' => 'mp3', 'mime_type' => 'audio/mpeg', - ), + ), // OFR - audio - OptimFROG 'ofr' => array( @@ -582,7 +596,7 @@ class getID3 'group' => 'audio', 'module' => 'optimfrog', 'mime_type' => 'application/octet-stream', - ), + ), // RKAU - audio - RKive AUdio compressor 'rkau' => array( @@ -590,7 +604,7 @@ class getID3 'group' => 'audio', 'module' => 'rkau', 'mime_type' => 'application/octet-stream', - ), + ), // SHN - audio - Shorten 'shn' => array( @@ -600,7 +614,7 @@ class getID3 'mime_type' => 'audio/xmms-shn', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org) 'tta' => array( @@ -608,7 +622,7 @@ class getID3 'group' => 'audio', 'module' => 'tta', 'mime_type' => 'application/octet-stream', - ), + ), // VOC - audio - Creative Voice (VOC) 'voc' => array( @@ -616,7 +630,7 @@ class getID3 'group' => 'audio', 'module' => 'voc', 'mime_type' => 'audio/voc', - ), + ), // VQF - audio - transform-domain weighted interleave Vector Quantization Format (VQF) 'vqf' => array( @@ -624,7 +638,7 @@ class getID3 'group' => 'audio', 'module' => 'vqf', 'mime_type' => 'application/octet-stream', - ), + ), // WV - audio - WavPack (v4.0+) 'wv' => array( @@ -632,7 +646,7 @@ class getID3 'group' => 'audio', 'module' => 'wavpack', 'mime_type' => 'application/octet-stream', - ), + ), // Audio-Video formats @@ -644,15 +658,23 @@ class getID3 'module' => 'asf', 'mime_type' => 'video/x-ms-asf', 'iconv_req' => false, - ), + ), - // BINK - audio/video - Bink / Smacker + // BINK - audio/video - Bink / Smacker 'bink' => array( 'pattern' => '^(BIK|SMK)', 'group' => 'audio-video', 'module' => 'bink', 'mime_type' => 'application/octet-stream', - ), + ), + + // FLV - audio/video - FLash Video + 'flv' => array(
+ 'pattern' => '^FLV\x01',
+ 'group' => 'audio-video',
+ 'module' => 'flv',
+ 'mime_type' => 'video/x-flv',
+ ),
// MKAV - audio/video - Mastroka 'matroska' => array( @@ -660,7 +682,7 @@ class getID3 'group' => 'audio-video', 'module' => 'matroska', 'mime_type' => 'application/octet-stream', - ), + ), // MPEG - audio/video - MPEG (Moving Pictures Experts Group) 'mpeg' => array( @@ -668,7 +690,7 @@ class getID3 'group' => 'audio-video', 'module' => 'mpeg', 'mime_type' => 'video/mpeg', - ), + ), // NSV - audio/video - Nullsoft Streaming Video (NSV) 'nsv' => array( @@ -676,7 +698,7 @@ class getID3 'group' => 'audio-video', 'module' => 'nsv', 'mime_type' => 'application/octet-stream', - ), + ), // Ogg - audio/video - Ogg (Ogg-Vorbis, Ogg-FLAC, Speex, Ogg-Theora(*), Ogg-Tarkin(*)) 'ogg' => array( @@ -686,7 +708,7 @@ class getID3 'mime_type' => 'application/ogg', 'fail_id3' => 'WARNING', 'fail_ape' => 'WARNING', - ), + ), // QT - audio/video - Quicktime 'quicktime' => array( @@ -694,7 +716,7 @@ class getID3 'group' => 'audio-video', 'module' => 'quicktime', 'mime_type' => 'video/quicktime', - ), + ), // RIFF - audio/video - Resource Interchange File Format (RIFF) / WAV / AVI / CD-audio / SDSS = renamed variant used by SmartSound QuickTracks (www.smartsound.com) / FORM = Audio Interchange File Format (AIFF) 'riff' => array( @@ -703,7 +725,7 @@ class getID3 'module' => 'riff', 'mime_type' => 'audio/x-wave', 'fail_ape' => 'WARNING', - ), + ), // Real - audio/video - RealAudio, RealVideo 'real' => array( @@ -711,7 +733,7 @@ class getID3 'group' => 'audio-video', 'module' => 'real', 'mime_type' => 'audio/x-realaudio', - ), + ), // SWF - audio/video - ShockWave Flash 'swf' => array( @@ -719,7 +741,7 @@ class getID3 'group' => 'audio-video', 'module' => 'swf', 'mime_type' => 'application/x-shockwave-flash', - ), + ), // Still-Image formats @@ -732,7 +754,7 @@ class getID3 'mime_type' => 'image/bmp', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // GIF - still image - Graphics Interchange Format 'gif' => array( @@ -742,7 +764,7 @@ class getID3 'mime_type' => 'image/gif', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // JPEG - still image - Joint Photographic Experts Group (JPEG) 'jpg' => array( @@ -752,7 +774,7 @@ class getID3 'mime_type' => 'image/jpeg', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // PCD - still image - Kodak Photo CD 'pcd' => array( @@ -762,7 +784,7 @@ class getID3 'mime_type' => 'image/x-photo-cd', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // PNG - still image - Portable Network Graphics (PNG) @@ -773,7 +795,7 @@ class getID3 'mime_type' => 'image/png', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // TIFF - still image - Tagged Information File Format (TIFF) @@ -784,7 +806,7 @@ class getID3 'mime_type' => 'image/tiff', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // Data formats @@ -798,7 +820,7 @@ class getID3 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', 'iconv_req' => false, - ), + ), // RAR - data - RAR compressed data 'rar' => array( @@ -808,7 +830,7 @@ class getID3 'mime_type' => 'application/octet-stream', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // SZIP - audio - SZIP compressed data 'szip' => array( @@ -818,7 +840,7 @@ class getID3 'mime_type' => 'application/octet-stream', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // TAR - data - TAR compressed data 'tar' => array( @@ -828,7 +850,7 @@ class getID3 'mime_type' => 'application/x-tar', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // GZIP - data - GZIP compressed data 'gz' => array( @@ -838,7 +860,7 @@ class getID3 'mime_type' => 'application/x-gzip', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // ZIP - data - ZIP compressed data 'zip' => array( diff --git a/modules/id3/getid3/module.audio-video.asf.php b/modules/id3/getid3/module.audio-video.asf.php index c11a04b2..c7e5aa1b 100644 --- a/modules/id3/getid3/module.audio-video.asf.php +++ b/modules/id3/getid3/module.audio-video.asf.php @@ -754,6 +754,11 @@ class getid3_asf $thisfile_asf_comments['year'] = array( $this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); break; + case 'wm/lyrics': + case 'lyrics': + $thisfile_asf_comments['lyrics'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + break; + case 'isvbr': if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']) { $thisfile_audio['bitrate_mode'] = 'vbr'; @@ -769,12 +774,12 @@ class getid3_asf $tempThisfileInfo = array('encoding'=>$ThisFileInfo['encoding']); fwrite($tempfilehandle, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); fclose($tempfilehandle); - + $tempfilehandle = fopen($tempfile, "rb"); $id3 = new getid3_id3v2($tempfilehandle, $tempThisfileInfo); fclose($tempfilehandle); unlink($tempfile); - + $ThisFileInfo['id3v2'] = $tempThisfileInfo['id3v2']; } break; diff --git a/modules/id3/getid3/module.audio-video.flv.php b/modules/id3/getid3/module.audio-video.flv.php new file mode 100644 index 00000000..54666bd2 --- /dev/null +++ b/modules/id3/getid3/module.audio-video.flv.php @@ -0,0 +1,210 @@ +<?php +///////////////////////////////////////////////////////////////// +/// getID3() by James Heinrich <info@getid3.org> // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +// // +// FLV module by Seth Kaufman <seth@whirl-i-gig.com> // +// * version 0.1 (26 June 2005) // +// minor modifications by James Heinrich <info@getid3.org> // +// * version 0.1.1 (15 July 2005) // +///////////////////////////////////////////////////////////////// +// // +// module.audio-video.flv.php // +// module for analyzing Shockwave Flash Video files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + + +class getid3_flv +{ + + function getid3_flv(&$fd, &$ThisFileInfo, $ReturnAllTagData=false) { + fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); + + $FLVfileData = fread($fd, $ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']); + + $FLVmagic = substr($FLVfileData, 0, 3); + if ($FLVmagic != 'FLV') { + $ThisFileInfo['error'][] = 'Expecting "FLV" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$ThisFileInfo['flv']['header']['signature'].'"'; + unset($ThisFileInfo['flv']); + unset($ThisFileInfo['fileformat']); + return false; + } + $ThisFileInfo['flv']['header']['signature'] = $FLVmagic; + $ThisFileInfo['flv']['header']['version'] = ord($FLVfileData{3}); + $ThisFileInfo['fileformat'] = 'flv'; + + $TypeFlags = ord($FLVfileData{4}); + $ThisFileInfo['flv']['header']['hasAudio'] = (bool) ($TypeFlags & 4); + $ThisFileInfo['flv']['header']['hasVideo'] = (bool) ($TypeFlags & 1); + + $FrameSizeDataLength = getid3_lib::BigEndian2Int(substr($FLVfileData, 5, 4)); + + // FLV tags + $CurrentOffset = $FrameSizeDataLength; + $FLVdataLength = strlen($FLVfileData); + + $Duration = 0; + + $SoundFormat = null; + $VideoFormat = null; + while ($CurrentOffset < $FLVdataLength) { + // previous tag size + $PreviousTagLength = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset, 4)); + $CurrentOffset += 4; + + $TagType = ord(substr($FLVfileData, $CurrentOffset, 1)); + $DataLength = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 1, 3)); + $Timestamp = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 4, 3)); + + switch ($TagType) { + case 8: + if (is_null($SoundFormat)) { + $SoundInfo = ord(substr($FLVfileData, $CurrentOffset + 11, 1)); + $SoundFormat = $SoundInfo & 0x07; + $ThisFileInfo['flv']['audio']['audioFormat'] = $SoundFormat; + $ThisFileInfo['flv']['audio']['audioRate'] = ($SoundInfo & 0x30) / 0x10; + $ThisFileInfo['flv']['audio']['audioSampleSize'] = ($SoundInfo & 0x40) / 0x40; + $ThisFileInfo['flv']['audio']['audioType'] = ($SoundInfo & 0x80) / 0x80; + } + break; + + case 9: + if (is_null($VideoFormat)) { + $VideoInfo = ord(substr($FLVfileData, $CurrentOffset + 11, 1)); + $VideoFormat = $VideoInfo & 0x07; + $ThisFileInfo['flv']['video']['videoCodec'] = $VideoFormat; + + $PictureSizeType = (getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 15, 2))) >> 7; + $PictureSizeType = $PictureSizeType & 0x0007; + $ThisFileInfo['flv']['header']['videoSizeType'] = $PictureSizeType; + switch ($PictureSizeType) { + case 0: + $PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 16, 2)); + $PictureSizeEnc <<= 1; + $ThisFileInfo['video']['resolution_x'] = ($PictureSizeEnc & 0xFF00) >> 8; + $PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 17, 2)); + $PictureSizeEnc <<= 1; + $ThisFileInfo['video']['resolution_y'] = ($PictureSizeEnc & 0xFF00) >> 8; + break; + + case 1: + $PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 16, 4)); + $PictureSizeEnc <<= 1; + $ThisFileInfo['video']['resolution_x'] = ($PictureSizeEnc & 0xFFFF0000) >> 16; + + $PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 18, 4)); + $PictureSizeEnc <<= 1; + $ThisFileInfo['video']['resolution_y'] = ($PictureSizeEnc & 0xFFFF0000) >> 16; + break; + + case 2: + $ThisFileInfo['video']['resolution_x'] = 352; + $ThisFileInfo['video']['resolution_y'] = 288; + break; + + case 3: + $ThisFileInfo['video']['resolution_x'] = 176; + $ThisFileInfo['video']['resolution_y'] = 144; + break; + + case 4: + $ThisFileInfo['video']['resolution_x'] = 128; + $ThisFileInfo['video']['resolution_y'] = 96; + break; + + case 5: + $ThisFileInfo['video']['resolution_x'] = 320; + $ThisFileInfo['video']['resolution_y'] = 240; + break; + + case 6: + $ThisFileInfo['video']['resolution_x'] = 160; + $ThisFileInfo['video']['resolution_y'] = 120; + break; + + default: + $ThisFileInfo['video']['resolution_x'] = 0; + $ThisFileInfo['video']['resolution_y'] = 0; + break; + + } + } + break; + + default: + // noop + break; + } + + if ($Timestamp > $Duration) { + $Duration = $Timestamp; + } + + $CurrentOffset += ($DataLength + 11); + } + + $ThisFileInfo['playtime_seconds'] = $Duration / 1000; + $ThisFileInfo['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds']; + + if ($ThisFileInfo['flv']['header']['hasAudio']) { + $ThisFileInfo['audio']['codec'] = $this->FLVaudioFormat($ThisFileInfo['flv']['audio']['audioFormat']); + $ThisFileInfo['audio']['sample_rate'] = $this->FLVaudioRate($ThisFileInfo['flv']['audio']['audioRate']); + $ThisFileInfo['audio']['bits_per_sample'] = $this->FLVaudioBitDepth($ThisFileInfo['flv']['audio']['audioSampleSize']); + + $ThisFileInfo['audio']['channels'] = $ThisFileInfo['flv']['audio']['audioType'] + 1; // 0=mono,1=stereo + $ThisFileInfo['audio']['lossless'] = ($ThisFileInfo['flv']['audio']['audioFormat'] ? false : true); // 0=uncompressed + $ThisFileInfo['audio']['dataformat'] = 'flv'; + } + if (@$ThisFileInfo['flv']['header']['hasVideo']) { + $ThisFileInfo['video']['codec'] = $this->FLVvideoCodec($ThisFileInfo['flv']['video']['videoCodec']); + $ThisFileInfo['video']['dataformat'] = 'flv'; + $ThisFileInfo['video']['lossless'] = false; + } + + return true; + } + + + function FLVaudioFormat($id) { + $FLVaudioFormat = array( + 0 => 'uncompressed', + 1 => 'ADPCM', + 2 => 'mp3', + 5 => 'Nellymoser 8kHz mono', + 6 => 'Nellymoser', + ); + return (@$FLVaudioFormat[$id] ? @$FLVaudioFormat[$id] : false); + } + + function FLVaudioRate($id) { + $FLVaudioRate = array( + 0 => 5500, + 1 => 11025, + 2 => 22050, + 3 => 44100, + ); + return (@$FLVaudioRate[$id] ? @$FLVaudioRate[$id] : false); + } + + function FLVaudioBitDepth($id) { + $FLVaudioBitDepth = array( + 0 => 8, + 1 => 16, + ); + return (@$FLVaudioBitDepth[$id] ? @$FLVaudioBitDepth[$id] : false); + } + + function FLVvideoCodec($id) { + $FLVaudioBitDepth = array( + 2 => 'Sorenson H.263', + 3 => 'Screen video', + ); + return (@$FLVaudioBitDepth[$id] ? @$FLVaudioBitDepth[$id] : false); + } + +} + +?>
\ No newline at end of file diff --git a/modules/id3/getid3/module.audio-video.riff.php b/modules/id3/getid3/module.audio-video.riff.php index ebe3ee77..b2225a28 100644 --- a/modules/id3/getid3/module.audio-video.riff.php +++ b/modules/id3/getid3/module.audio-video.riff.php @@ -1953,8 +1953,6 @@ class getid3_riff XMPG Xing MPEG (I-Frame only) XVID XviD MPEG-4 (www.xvid.org) XXAN ?XXAN? - Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera - Y800 Simple, single Y plane for monochrome images YU92 Intel YUV (YU92) YUNV Nvidia Uncompressed YUV 4:2:2 YUVP Extended PAL format YUV palette (www.riff.org) @@ -1965,6 +1963,8 @@ class getid3_riff Y41T Brooktree PC1 YUV 4:1:1 with transparency Y42B Weitek YUV 4:2:2 Planar Y42T Brooktree UYUV 4:2:2 with transparency + Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera + Y800 Simple, single Y plane for monochrome images Y8 Grayscale video YC12 Intel YUV 12 codec YUV8 Winnov Caviar YUV8 diff --git a/modules/id3/getid3/module.audio.mp3.php b/modules/id3/getid3/module.audio.mp3.php index d7b0b77a..5fb6110c 100644 --- a/modules/id3/getid3/module.audio.mp3.php +++ b/modules/id3/getid3/module.audio.mp3.php @@ -320,8 +320,9 @@ class getid3_mp3 'fast standard|19000' => 19000, 'r3mix|19500' => 19500, // 3.90, 3.90.1, 3.92 'r3mix|19600' => 19600, // 3.90.2, 3.90.3, 3.91 - 'r3mix|18000' => 18000); // 3.94, 3.95 - if (!isset($ExpectedLowpass[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio_lame['lowpass_frequency']])) { + 'r3mix|18000' => 18000, // 3.94, 3.95 + ); + if (!isset($ExpectedLowpass[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio_lame['lowpass_frequency']]) && ($thisfile_mpeg_audio_lame['lowpass_frequency'] < 22050) && (round($thisfile_mpeg_audio_lame['lowpass_frequency'] / 1000) < round($thisfile_mpeg_audio['sample_rate'] / 2000))) { $encoder_options .= ' --lowpass '.$thisfile_mpeg_audio_lame['lowpass_frequency']; } break; @@ -1636,23 +1637,17 @@ class getid3_mp3 if (isset($MPEGaudioVersionLookup[$rawarray['version']])) { $decodedVersion = $MPEGaudioVersionLookup[$rawarray['version']]; } else { - if ($echoerrors) { - echo "\n".'invalid Version ('.$rawarray['version'].')'; - } + echo ($echoerrors ? "\n".'invalid Version ('.$rawarray['version'].')' : ''); return false; } if (isset($MPEGaudioLayerLookup[$rawarray['layer']])) { $decodedLayer = $MPEGaudioLayerLookup[$rawarray['layer']]; } else { - if ($echoerrors) { - echo "\n".'invalid Layer ('.$rawarray['layer'].')'; - } + echo ($echoerrors ? "\n".'invalid Layer ('.$rawarray['layer'].')' : ''); return false; } if (!isset($MPEGaudioBitrateLookup[$decodedVersion][$decodedLayer][$rawarray['bitrate']])) { - if ($echoerrors) { - echo "\n".'invalid Bitrate ('.$rawarray['bitrate'].')'; - } + echo ($echoerrors ? "\n".'invalid Bitrate ('.$rawarray['bitrate'].')' : ''); if ($rawarray['bitrate'] == 15) { // known issue in LAME 3.90 - 3.93.1 where free-format has bitrate ID of 15 instead of 0 // let it go through here otherwise file will not be identified @@ -1664,27 +1659,19 @@ class getid3_mp3 } } if (!isset($MPEGaudioFrequencyLookup[$decodedVersion][$rawarray['sample_rate']])) { - if ($echoerrors) { - echo "\n".'invalid Frequency ('.$rawarray['sample_rate'].')'; - } + echo ($echoerrors ? "\n".'invalid Frequency ('.$rawarray['sample_rate'].')' : ''); return false; } if (!isset($MPEGaudioChannelModeLookup[$rawarray['channelmode']])) { - if ($echoerrors) { - echo "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')'; - } + echo ($echoerrors ? "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')' : ''); return false; } if (!isset($MPEGaudioModeExtensionLookup[$decodedLayer][$rawarray['modeextension']])) { - if ($echoerrors) { - echo "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')'; - } + echo ($echoerrors ? "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')' : ''); return false; } if (!isset($MPEGaudioEmphasisLookup[$rawarray['emphasis']])) { - if ($echoerrors) { - echo "\n".'invalid Emphasis ('.$rawarray['emphasis'].')'; - } + echo ($echoerrors ? "\n".'invalid Emphasis ('.$rawarray['emphasis'].')' : ''); return false; } // These are just either set or not set, you can't mess that up :) diff --git a/modules/id3/getid3/module.tag.id3v2.php b/modules/id3/getid3/module.tag.id3v2.php index c855bf21..8bb6c3cb 100644 --- a/modules/id3/getid3/module.tag.id3v2.php +++ b/modules/id3/getid3/module.tag.id3v2.php @@ -101,47 +101,51 @@ class getid3_id3v2 $thisfile_id3v2['tag_offset_start'] = $StartingOffset; $thisfile_id3v2['tag_offset_end'] = $thisfile_id3v2['tag_offset_start'] + $thisfile_id3v2['headerlength']; - // Extended Header + // Extended Header if (isset($thisfile_id3v2_flags['exthead']) && $thisfile_id3v2_flags['exthead']) { - // Extended header size 4 * %0xxxxxxx - // Number of flag bytes $01 - // Extended Flags $xx - // Where the 'Extended header size' is the size of the whole extended header, stored as a 32 bit synchsafe integer. - $extheader = fread ($fd, 4); - $thisfile_id3v2['extheaderlength'] = getid3_lib::BigEndian2Int($extheader, 1); - - // The extended flags field, with its size described by 'number of flag bytes', is defined as: - // %0bcd0000 - // b - Tag is an update - // Flag data length $00 - // c - CRC data present - // Flag data length $05 - // Total frame CRC 5 * %0xxxxxxx - // d - Tag restrictions - // Flag data length $01 - $extheaderflagbytes = fread ($fd, 1); - $extheaderflags = fread ($fd, $extheaderflagbytes); - $id3_exthead_flags = getid3_lib::BigEndian2Bin(substr($header, 5, 1)); - $thisfile_id3v2['exthead_flags']['update'] = substr($id3_exthead_flags, 1, 1); - $thisfile_id3v2['exthead_flags']['CRC'] = substr($id3_exthead_flags, 2, 1); - if ($thisfile_id3v2['exthead_flags']['CRC']) { - $extheaderrawCRC = fread ($fd, 5); - $thisfile_id3v2['exthead_flags']['CRC'] = getid3_lib::BigEndian2Int($extheaderrawCRC, 1); - } - $thisfile_id3v2['exthead_flags']['restrictions'] = substr($id3_exthead_flags, 3, 1); - if ($thisfile_id3v2['exthead_flags']['restrictions']) { - // Restrictions %ppqrrstt - $extheaderrawrestrictions = fread ($fd, 1); - $thisfile_id3v2['exthead_flags']['restrictions_tagsize'] = (bindec('11000000') & ord($extheaderrawrestrictions)) >> 6; // p - Tag size restrictions - $thisfile_id3v2['exthead_flags']['restrictions_textenc'] = (bindec('00100000') & ord($extheaderrawrestrictions)) >> 5; // q - Text encoding restrictions - $thisfile_id3v2['exthead_flags']['restrictions_textsize'] = (bindec('00011000') & ord($extheaderrawrestrictions)) >> 3; // r - Text fields size restrictions - $thisfile_id3v2['exthead_flags']['restrictions_imgenc'] = (bindec('00000100') & ord($extheaderrawrestrictions)) >> 2; // s - Image encoding restrictions - $thisfile_id3v2['exthead_flags']['restrictions_imgsize'] = (bindec('00000011') & ord($extheaderrawrestrictions)) >> 0; // t - Image size restrictions + // Extended header size 4 * %0xxxxxxx + // Number of flag bytes $01 + // Extended Flags $xx + // Where the 'Extended header size' is the size of the whole extended header, stored as a 32 bit synchsafe integer. + $thisfile_id3v2['exthead_length'] = getid3_lib::BigEndian2Int(fread($fd, 4), 1); + + $thisfile_id3v2['exthead_flag_bytes'] = ord(fread($fd, 1)); + if ($thisfile_id3v2['exthead_flag_bytes'] == 1) { + // The extended flags field, with its size described by 'number of flag bytes', is defined as: + // %0bcd0000 + // b - Tag is an update + // Flag data length $00 + // c - CRC data present + // Flag data length $05 + // Total frame CRC 5 * %0xxxxxxx + // d - Tag restrictions + // Flag data length $01 + $extheaderflags = fread($fd, $thisfile_id3v2['exthead_flag_bytes']); + $id3_exthead_flags = getid3_lib::BigEndian2Bin(substr($header, 5, 1)); + $thisfile_id3v2['exthead_flags']['update'] = substr($id3_exthead_flags, 1, 1); + $thisfile_id3v2['exthead_flags']['CRC'] = substr($id3_exthead_flags, 2, 1); + if ($thisfile_id3v2['exthead_flags']['CRC']) { + $extheaderrawCRC = fread($fd, 5); + $thisfile_id3v2['exthead_flags']['CRC'] = getid3_lib::BigEndian2Int($extheaderrawCRC, 1); + } + $thisfile_id3v2['exthead_flags']['restrictions'] = substr($id3_exthead_flags, 3, 1); + if ($thisfile_id3v2['exthead_flags']['restrictions']) { + // Restrictions %ppqrrstt + $extheaderrawrestrictions = fread($fd, 1); + $thisfile_id3v2['exthead_flags']['restrictions_tagsize'] = (bindec('11000000') & ord($extheaderrawrestrictions)) >> 6; // p - Tag size restrictions + $thisfile_id3v2['exthead_flags']['restrictions_textenc'] = (bindec('00100000') & ord($extheaderrawrestrictions)) >> 5; // q - Text encoding restrictions + $thisfile_id3v2['exthead_flags']['restrictions_textsize'] = (bindec('00011000') & ord($extheaderrawrestrictions)) >> 3; // r - Text fields size restrictions + $thisfile_id3v2['exthead_flags']['restrictions_imgenc'] = (bindec('00000100') & ord($extheaderrawrestrictions)) >> 2; // s - Image encoding restrictions + $thisfile_id3v2['exthead_flags']['restrictions_imgsize'] = (bindec('00000011') & ord($extheaderrawrestrictions)) >> 0; // t - Image size restrictions + } + } else { + $ThisFileInfo['warning'][] = '$thisfile_id3v2[exthead_flag_bytes] = "'.$thisfile_id3v2['exthead_flag_bytes'].'" (expecting "1")'; + fseek($fd, $thisfile_id3v2['exthead_length'] - 1, SEEK_CUR); + //return false; } } // end extended header - // create 'encoding' key - used by getid3::HandleAllTags() // in ID3v2 every field can have it's own encoding type // so force everything to UTF-8 so it can be handled consistantly @@ -159,10 +163,10 @@ class getid3_id3v2 // Flags $xx xx $sizeofframes = $thisfile_id3v2['headerlength'] - 10; // not including 10-byte initial header - if (isset($thisfile_id3v2['extheaderlength'])) { - $sizeofframes -= $thisfile_id3v2['extheaderlength']; + if (@$thisfile_id3v2['exthead_length']) { + $sizeofframes -= ($thisfile_id3v2['exthead_length'] + 4); } - if (isset($thisfile_id3v2_flags['isfooter']) && $thisfile_id3v2_flags['isfooter']) { + if (@$thisfile_id3v2_flags['isfooter']) { $sizeofframes -= 10; // footer takes last 10 bytes of ID3v2 header, after frame data, before audio } if ($sizeofframes > 0) { @@ -170,7 +174,7 @@ class getid3_id3v2 $framedata = fread($fd, $sizeofframes); // read all frames from file into $framedata variable // if entire frame data is unsynched, de-unsynch it now (ID3v2.3.x) - if (isset($thisfile_id3v2_flags['unsynch']) && $thisfile_id3v2_flags['unsynch'] && ($id3v2_majorversion <= 3)) { + if (@$thisfile_id3v2_flags['unsynch'] && ($id3v2_majorversion <= 3)) { $framedata = $this->DeUnsynchronise($framedata); } // [in ID3v2.4.0] Unsynchronisation [S:6.1] is done on frame level, instead @@ -179,7 +183,7 @@ class getid3_id3v2 // there exists an unsynchronised frame, while the new unsynchronisation flag in // the frame header [S:4.1.2] indicates unsynchronisation. - $framedataoffset = 10; // how many bytes into the stream - start from after the 10-byte header + $framedataoffset = 10 + (@$thisfile_id3v2['exthead_length'] ? $thisfile_id3v2['exthead_length'] + 4 : 0); // how many bytes into the stream - start from after the 10-byte header (and extended header length+4, if present) while (isset($framedata) && (strlen($framedata) > 0)) { // cycle through until no more frame data is left to parse if (strlen($framedata) <= $this->ID3v2HeaderLength($id3v2_majorversion)) { // insufficient room left in ID3v2 header for actual data - must be padding @@ -350,7 +354,7 @@ class getid3_id3v2 // ID3v2 size 4 * %0xxxxxxx if (isset($thisfile_id3v2_flags['isfooter']) && $thisfile_id3v2_flags['isfooter']) { - $footer = fread ($fd, 10); + $footer = fread($fd, 10); if (substr($footer, 0, 3) == '3DI') { $thisfile_id3v2['footer'] = true; $thisfile_id3v2['majorversion_footer'] = ord($footer{3}); diff --git a/modules/id3/getid3/write.id3v2.php b/modules/id3/getid3/write.id3v2.php index a575f20b..9d47e708 100644 --- a/modules/id3/getid3/write.id3v2.php +++ b/modules/id3/getid3/write.id3v2.php @@ -101,6 +101,7 @@ class getid3_write_id3v2 fclose($fp_source); copy($tempfilename, $this->filename); unlink($tempfilename); + ob_end_clean(); return true; } else { diff --git a/modules/id3/getid3/write.php b/modules/id3/getid3/write.php index 40a79e9e..db09decd 100644 --- a/modules/id3/getid3/write.php +++ b/modules/id3/getid3/write.php @@ -394,6 +394,14 @@ class getid3_writetags } break; + case 'real': + $real_writer = new getid3_write_real; + $real_writer->filename = $this->filename; + if (($success = $real_writer->RemoveReal()) === false) { + $this->errors[] = 'RemoveReal() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $real_writer->errors)).'</LI></UL></PRE>'; + } + break; + default: $this->errors[] = 'Invalid tag format to delete: "'.$tagformat.'"'; return false; diff --git a/modules/id3/getid3/write.real.php b/modules/id3/getid3/write.real.php index 5ede28d1..1e0240cc 100644 --- a/modules/id3/getid3/write.real.php +++ b/modules/id3/getid3/write.real.php @@ -16,7 +16,7 @@ class getid3_write_real { var $filename; - var $tag_data; + var $tag_data = array(); var $warnings = array(); // any non-critical errors will be stored here var $errors = array(); // any critical errors will be stored here var $paddedlength = 512; // minimum length of CONT tag in bytes @@ -33,50 +33,98 @@ class getid3_write_real // Initialize getID3 engine $getID3 = new getID3; $OldThisFileInfo = $getID3->analyze($this->filename); - if (empty($OldThisFileInfo['chunks']) && !empty($OldThisFileInfo['old_ra_header'])) { + if (empty($OldThisFileInfo['real']['chunks']) && !empty($OldThisFileInfo['real']['old_ra_header'])) { $this->errors[] = 'Cannot write Real tags on old-style file format'; + fclose($fp_source); return false; } - $OldPROPinfo = false; - $StartOfDATA = false; - foreach ($OldThisFileInfo['chunks'] as $chunknumber => $chunkarray) { - if ($chunkarray['name'] == 'PROP') { - $OldPROPinfo = $chunkarray; - } elseif ($chunkarray['name'] = 'DATA') { - $StartOfDATA = $chunkarray['offset']; - } + if (empty($OldThisFileInfo['real']['chunks'])) { + $this->errors[] = 'Cannot write Real tags because cannot find DATA chunk in file'; + fclose($fp_source); + return false; + } + foreach ($OldThisFileInfo['real']['chunks'] as $chunknumber => $chunkarray) { + $oldChunkInfo[$chunkarray['name']] = $chunkarray; + } + if (!empty($oldChunkInfo['CONT']['length'])) { + $this->paddedlength = max($oldChunkInfo['CONT']['length'], $this->paddedlength); } - if (!empty($OldPROPinfo['length'])) { - $this->paddedlength = max($OldPROPinfo['length'], $this->paddedlength); + $new_CONT_tag_data = $this->GenerateCONTchunk(); + $new_PROP_tag_data = $this->GeneratePROPchunk($OldThisFileInfo['real']['chunks'], $new_CONT_tag_data); + $new__RMF_tag_data = $this->GenerateRMFchunk($OldThisFileInfo['real']['chunks']); + + if (@$oldChunkInfo['.RMF']['length'] == strlen($new__RMF_tag_data)) { + fseek($fp_source, $oldChunkInfo['.RMF']['offset'], SEEK_SET); + fwrite($fp_source, $new__RMF_tag_data); + } else { + $this->errors[] = 'new .RMF tag ('.strlen($new__RMF_tag_data).' bytes) different length than old .RMF tag ('.$oldChunkInfo['.RMF']['length'].' bytes)'; + fclose($fp_source); + return false; } - $new_real_tag_data = GenerateRealTag(); + if (@$oldChunkInfo['PROP']['length'] == strlen($new_PROP_tag_data)) { + fseek($fp_source, $oldChunkInfo['PROP']['offset'], SEEK_SET); + fwrite($fp_source, $new_PROP_tag_data); + } else { + $this->errors[] = 'new PROP tag ('.strlen($new_PROP_tag_data).' bytes) different length than old PROP tag ('.$oldChunkInfo['PROP']['length'].' bytes)'; + fclose($fp_source); + return false; + } - if (@$OldPROPinfo['length'] == $new_real_tag_data) { + if (@$oldChunkInfo['CONT']['length'] == strlen($new_CONT_tag_data)) { // new data length is same as old data length - just overwrite - fseek($fp_source, $OldPROPinfo['offset'], SEEK_SET); - fwrite($fp_source, $new_real_tag_data); + fseek($fp_source, $oldChunkInfo['CONT']['offset'], SEEK_SET); + fwrite($fp_source, $new_CONT_tag_data); + fclose($fp_source); + return true; } else { - if (empty($OldPROPinfo)) { - // no existing PROP chunk - $BeforeOffset = $StartOfDATA; - $AfterOffset = $StartOfDATA; + if (empty($oldChunkInfo['CONT'])) { + // no existing CONT chunk + $BeforeOffset = $oldChunkInfo['DATA']['offset']; + $AfterOffset = $oldChunkInfo['DATA']['offset']; } else { // new data is longer than old data - $BeforeOffset = $OldPROPinfo['offset']; - $AfterOffset = $OldPROPinfo['offset'] + $OldPROPinfo['length']; + $BeforeOffset = $oldChunkInfo['CONT']['offset']; + $AfterOffset = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length']; } + if ($tempfilename = tempnam('*', 'getID3')) { + ob_start(); + if ($fp_temp = fopen($tempfilename, 'wb')) { + + rewind($fp_source); + fwrite($fp_temp, fread($fp_source, $BeforeOffset)); + fwrite($fp_temp, $new_CONT_tag_data); + fseek($fp_source, $AfterOffset, SEEK_SET); + while ($buffer = fread($fp_source, GETID3_FREAD_BUFFER_SIZE)) { + fwrite($fp_temp, $buffer, strlen($buffer)); + } + fclose($fp_temp); + + if (copy($tempfilename, $this->filename)) { + unlink($tempfilename); + fclose($fp_source); + return true; + } + unlink($tempfilename); + $this->errors[] = 'FAILED: copy('.$tempfilename.', '.$this->filename.') - '.strip_tags(ob_get_contents()); + } else { + + $this->errors[] = 'Could not open '.$tempfilename.' mode "wb" - '.strip_tags(ob_get_contents()); + + } + ob_end_clean(); + } + fclose($fp_source); + return false; } - fclose($fp_source); - return true; } else { $this->errors[] = 'Could not open '.$this->filename.' mode "r+b"'; @@ -87,28 +135,88 @@ class getid3_write_real return false; } - function GenerateRealTag() { - $RealCONT = "\x00\x00"; // object version + function GenerateRMFchunk(&$chunks) { + $oldCONTexists = false; + foreach ($chunks as $key => $chunk) { + $chunkNameKeys[$chunk['name']] = $key; + if ($chunk['name'] == 'CONT') { + $oldCONTexists = true; + } + } + $newHeadersCount = $chunks[$chunkNameKeys['.RMF']]['headers_count'] + ($oldCONTexists ? 0 : 1); - $RealCONT .= BigEndian2String(strlen(@$this->tag_data['title']), 4); - $RealCONT .= @$this->tag_data['title']; + $RMFchunk = "\x00\x00"; // object version + $RMFchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['.RMF']]['file_version'], 4); + $RMFchunk .= getid3_lib::BigEndian2String($newHeadersCount, 4); - $RealCONT .= BigEndian2String(strlen(@$this->tag_data['artist']), 4); - $RealCONT .= @$this->tag_data['artist']; + $RMFchunk = '.RMF'.getid3_lib::BigEndian2String(strlen($RMFchunk) + 8, 4).$RMFchunk; // .RMF chunk identifier + chunk length + return $RMFchunk; + } + + function GeneratePROPchunk(&$chunks, &$new_CONT_tag_data) { + $old_CONT_length = 0; + $old_DATA_offset = 0; + $old_INDX_offset = 0; + foreach ($chunks as $key => $chunk) { + $chunkNameKeys[$chunk['name']] = $key; + if ($chunk['name'] == 'CONT') { + $old_CONT_length = $chunk['length']; + } elseif ($chunk['name'] == 'DATA') { + if (!$old_DATA_offset) { + $old_DATA_offset = $chunk['offset']; + } + } elseif ($chunk['name'] == 'INDX') { + if (!$old_INDX_offset) { + $old_INDX_offset = $chunk['offset']; + } + } + } + $CONTdelta = strlen($new_CONT_tag_data) - $old_CONT_length; - $RealCONT .= BigEndian2String(strlen(@$this->tag_data['copyright']), 4); - $RealCONT .= @$this->tag_data['copyright']; + $PROPchunk = "\x00\x00"; // object version + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['max_bit_rate'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['avg_bit_rate'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['max_packet_size'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['avg_packet_size'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['num_packets'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['duration'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['preroll'], 4); + $PROPchunk .= getid3_lib::BigEndian2String(max(0, $old_INDX_offset + $CONTdelta), 4); + $PROPchunk .= getid3_lib::BigEndian2String(max(0, $old_DATA_offset + $CONTdelta), 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['num_streams'], 2); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['flags_raw'], 2); - $RealCONT .= BigEndian2String(strlen(@$this->tag_data['comment']), 4); - $RealCONT .= @$this->tag_data['comment']; + $PROPchunk = 'PROP'.getid3_lib::BigEndian2String(strlen($PROPchunk) + 8, 4).$PROPchunk; // PROP chunk identifier + chunk length + return $PROPchunk; + } - if ($this->paddedlength > (strlen($RealCONT) + 8)) { - $RealCONT .= str_repeat("\x00", $this->paddedlength - strlen($RealCONT) - 8); + function GenerateCONTchunk() { + foreach ($this->tag_data as $key => $value) { + // limit each value to 0xFFFF bytes + $this->tag_data[$key] = substr($value, 0, 65535); } - $RealCONT = 'CONT'.BigEndian2String(strlen($RealCONT) + 8, 4).$RealCONT; // CONT chunk identifier + chunk length + $CONTchunk = "\x00\x00"; // object version + + $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['title']), 2); + $CONTchunk .= @$this->tag_data['title']; + + $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['artist']), 2); + $CONTchunk .= @$this->tag_data['artist']; + + $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['copyright']), 2); + $CONTchunk .= @$this->tag_data['copyright']; - return $RealCONT; + $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['comment']), 2); + $CONTchunk .= @$this->tag_data['comment']; + + if ($this->paddedlength > (strlen($CONTchunk) + 8)) { + $CONTchunk .= str_repeat("\x00", $this->paddedlength - strlen($CONTchunk) - 8); + } + + $CONTchunk = 'CONT'.getid3_lib::BigEndian2String(strlen($CONTchunk) + 8, 4).$CONTchunk; // CONT chunk identifier + chunk length + + return $CONTchunk; } function RemoveReal() { @@ -116,22 +224,69 @@ class getid3_write_real if (is_writeable($this->filename)) { if ($fp_source = @fopen($this->filename, 'r+b')) { -return false; - //fseek($fp_source, -128, SEEK_END); - //if (fread($fp_source, 3) == 'TAG') { - // ftruncate($fp_source, filesize($this->filename) - 128); - //} else { - // // no real tag to begin with - do nothing - //} + // Initialize getID3 engine + $getID3 = new getID3; + $OldThisFileInfo = $getID3->analyze($this->filename); + if (empty($OldThisFileInfo['real']['chunks']) && !empty($OldThisFileInfo['real']['old_ra_header'])) { + $this->errors[] = 'Cannot remove Real tags from old-style file format'; + fclose($fp_source); + return false; + } + + if (empty($OldThisFileInfo['real']['chunks'])) { + $this->errors[] = 'Cannot remove Real tags because cannot find DATA chunk in file'; + fclose($fp_source); + return false; + } + foreach ($OldThisFileInfo['real']['chunks'] as $chunknumber => $chunkarray) { + $oldChunkInfo[$chunkarray['name']] = $chunkarray; + } + + if (empty($oldChunkInfo['CONT'])) { + // no existing CONT chunk + fclose($fp_source); + return true; + } + + $BeforeOffset = $oldChunkInfo['CONT']['offset']; + $AfterOffset = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length']; + if ($tempfilename = tempnam('*', 'getID3')) { + ob_start(); + if ($fp_temp = fopen($tempfilename, 'wb')) { + + rewind($fp_source); + fwrite($fp_temp, fread($fp_source, $BeforeOffset)); + fseek($fp_source, $AfterOffset, SEEK_SET); + while ($buffer = fread($fp_source, GETID3_FREAD_BUFFER_SIZE)) { + fwrite($fp_temp, $buffer, strlen($buffer)); + } + fclose($fp_temp); + + if (copy($tempfilename, $this->filename)) { + unlink($tempfilename); + fclose($fp_source); + return true; + } + unlink($tempfilename); + $this->errors[] = 'FAILED: copy('.$tempfilename.', '.$this->filename.') - '.strip_tags(ob_get_contents()); + + } else { + + $this->errors[] = 'Could not open '.$tempfilename.' mode "wb" - '.strip_tags(ob_get_contents()); + + } + ob_end_clean(); + } fclose($fp_source); - return true; + return false; + } else { $this->errors[] = 'Could not open '.$this->filename.' mode "r+b"'; + return false; } - } else { - $this->errors[] = $this->filename.' is not writeable'; } + $this->errors[] = 'File is not writeable: '.$this->filename; return false; } |