public function Analyze() { $info =& $this->getid3->info; // http://www.volweb.cz/str/tags.htm if (!getid3_lib::intValueSupported($info['filesize'])) { $info['warning'][] = 'Unable to check for Lyrics3 because file is larger than ' . round(PHP_INT_MAX / 1073741824) . 'GB'; return false; } $this->fseek(0 - 128 - 9 - 6, SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size] $lyrics3_id3v1 = $this->fread(128 + 9 + 6); $lyrics3lsz = substr($lyrics3_id3v1, 0, 6); // Lyrics3size $lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200 $id3v1tag = substr($lyrics3_id3v1, 15, 128); // ID3v1 if ($lyrics3end == 'LYRICSEND') { // Lyrics3v1, ID3v1, no APE $lyrics3size = 5100; $lyrics3offset = $info['filesize'] - 128 - $lyrics3size; $lyrics3version = 1; } elseif ($lyrics3end == 'LYRICS200') { // Lyrics3v2, ID3v1, no APE // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); $lyrics3offset = $info['filesize'] - 128 - $lyrics3size; $lyrics3version = 2; } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICSEND')) { // Lyrics3v1, no ID3v1, no APE $lyrics3size = 5100; $lyrics3offset = $info['filesize'] - $lyrics3size; $lyrics3version = 1; $lyrics3offset = $info['filesize'] - $lyrics3size; } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICS200')) { // Lyrics3v2, no ID3v1, no APE $lyrics3size = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' $lyrics3offset = $info['filesize'] - $lyrics3size; $lyrics3version = 2; } else { if (isset($info['ape']['tag_offset_start']) && $info['ape']['tag_offset_start'] > 15) { $this->fseek($info['ape']['tag_offset_start'] - 15); $lyrics3lsz = $this->fread(6); $lyrics3end = $this->fread(9); if ($lyrics3end == 'LYRICSEND') { // Lyrics3v1, APE, maybe ID3v1 $lyrics3size = 5100; $lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size; $info['avdataend'] = $lyrics3offset; $lyrics3version = 1; $info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability'; } elseif ($lyrics3end == 'LYRICS200') { // Lyrics3v2, APE, maybe ID3v1 $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' $lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size; $lyrics3version = 2; $info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability'; } } } if (isset($lyrics3offset)) { $info['avdataend'] = $lyrics3offset; $this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size); if (!isset($info['ape'])) { $GETID3_ERRORARRAY =& $info['warning']; getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.apetag.php', __FILE__, true); $getid3_temp = new getID3(); $getid3_temp->openfile($this->getid3->filename); $getid3_apetag = new getid3_apetag($getid3_temp); $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start']; $getid3_apetag->Analyze(); if (!empty($getid3_temp->info['ape'])) { $info['ape'] = $getid3_temp->info['ape']; } if (!empty($getid3_temp->info['replay_gain'])) { $info['replay_gain'] = $getid3_temp->info['replay_gain']; } unset($getid3_temp, $getid3_apetag); } } return true; }
protected function ParseAPEtagFlags($raw_flag_int) { // "Note: APE Tags 1.0 do not use any of the APE Tag flags. // All are set to zero on creation and ignored on reading." // http://www.uni-jena.de/~pfk/mpp/sv8/apetagflags.html $target['header'] = (bool) ($raw_flag_int & 2147483648.0); $target['footer'] = (bool) ($raw_flag_int & 0x40000000); $target['this_is_header'] = (bool) ($raw_flag_int & 0x20000000); $target['item_contents_raw'] = ($raw_flag_int & 0x6) >> 1; $target['read_only'] = (bool) ($raw_flag_int & 0x1); $target['item_contents'] = getid3_apetag::APEcontentTypeFlagLookup($target['item_contents_raw']); return $target; }
public function Analyze() { $getid3 = $this->getid3; fseek($getid3->fp, 0 - 128 - 9 - 6, SEEK_END); // end - ID3v1 - LYRICSEND - [Lyrics3size] $lyrics3_id3v1 = fread($getid3->fp, 128 + 9 + 6); $lyrics3_lsz = substr($lyrics3_id3v1, 0, 6); // Lyrics3size $lyrics3_end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200 $id3v1_tag = substr($lyrics3_id3v1, 15, 128); // ID3v1 // Lyrics3v1, ID3v1, no APE if ($lyrics3_end == 'LYRICSEND') { $lyrics3_size = 5100; $lyrics3_offset = filesize($getid3->filename) - 128 - $lyrics3_size; $lyrics3_version = 1; } elseif ($lyrics3_end == 'LYRICS200') { // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' $lyrics3_size = $lyrics3_lsz + 6 + strlen('LYRICS200'); $lyrics3_offset = filesize($getid3->filename) - 128 - $lyrics3_size; $lyrics3_version = 2; } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == 'DNESCIRYL') { // strrev('LYRICSEND') = 'DNESCIRYL' $lyrics3_size = 5100; $lyrics3_offset = filesize($getid3->filename) - $lyrics3_size; $lyrics3_version = 1; $lyrics3_offset = filesize($getid3->filename) - $lyrics3_size; } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == '002SCIRYL') { // strrev('LYRICS200') = '002SCIRYL' $lyrics3_size = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 15; // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' // 15 = 6 + strlen('LYRICS200') $lyrics3_offset = filesize($getid3->filename) - $lyrics3_size; $lyrics3_version = 2; } elseif (isset($getid3->info['ape']['tag_offset_start']) && $getid3->info['ape']['tag_offset_start'] > 15) { fseek($getid3->fp, $getid3->info['ape']['tag_offset_start'] - 15, SEEK_SET); $lyrics3_lsz = fread($getid3->fp, 6); $lyrics3_end = fread($getid3->fp, 9); // Lyrics3v1, APE, maybe ID3v1 if ($lyrics3_end == 'LYRICSEND') { $lyrics3_size = 5100; $lyrics3_offset = $getid3->info['ape']['tag_offset_start'] - $lyrics3_size; $getid3->info['avdataend'] = $lyrics3_offset; $lyrics3_version = 1; $getid3->warning('APE tag located after Lyrics3, will probably break Lyrics3 compatability'); } elseif ($lyrics3_end == 'LYRICS200') { $lyrics3_size = $lyrics3_lsz + 15; // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' $lyrics3_offset = $getid3->info['ape']['tag_offset_start'] - $lyrics3_size; $lyrics3_version = 2; $getid3->warning('APE tag located after Lyrics3, will probably break Lyrics3 compatability'); } } //// GetLyrics3Data() if (isset($lyrics3_offset)) { $getid3->info['avdataend'] = $lyrics3_offset; if ($lyrics3_size <= 0) { return false; } fseek($getid3->fp, $lyrics3_offset, SEEK_SET); $raw_data = fread($getid3->fp, $lyrics3_size); if (substr($raw_data, 0, 11) != 'LYRICSBEGIN') { if (strpos($raw_data, 'LYRICSBEGIN') !== false) { $getid3->warning('"LYRICSBEGIN" expected at ' . $lyrics3_offset . ' but actually found at ' . ($lyrics3_offset + strpos($raw_data, 'LYRICSBEGIN')) . ' - this is invalid for Lyrics3 v' . $lyrics3_version); $getid3->info['avdataend'] = $lyrics3_offset + strpos($raw_data, 'LYRICSBEGIN'); $parsed_lyrics3['tag_offset_start'] = $getid3->info['avdataend']; $raw_data = substr($raw_data, strpos($raw_data, 'LYRICSBEGIN')); $lyrics3_size = strlen($raw_data); } else { throw new getid3_exception('"LYRICSBEGIN" expected at ' . $lyrics3_offset . ' but found "' . substr($raw_data, 0, 11) . '" instead.'); } } $parsed_lyrics3['raw']['lyrics3version'] = $lyrics3_version; $parsed_lyrics3['raw']['lyrics3tagsize'] = $lyrics3_size; $parsed_lyrics3['tag_offset_start'] = $lyrics3_offset; $parsed_lyrics3['tag_offset_end'] = $lyrics3_offset + $lyrics3_size; switch ($lyrics3_version) { case 1: if (substr($raw_data, strlen($raw_data) - 9, 9) == 'LYRICSEND') { $parsed_lyrics3['raw']['LYR'] = trim(substr($raw_data, 11, strlen($raw_data) - 11 - 9)); getid3_lyrics3::Lyrics3LyricsTimestampParse($parsed_lyrics3); } else { throw new getid3_exception('"LYRICSEND" expected at ' . (ftell($getid3->fp) - 11 + $lyrics3_size - 9) . ' but found "' . substr($raw_data, strlen($raw_data) - 9, 9) . '" instead.'); } break; case 2: if (substr($raw_data, strlen($raw_data) - 9, 9) == 'LYRICS200') { $parsed_lyrics3['raw']['unparsed'] = substr($raw_data, 11, strlen($raw_data) - 11 - 9 - 6); // LYRICSBEGIN + LYRICS200 + LSZ $raw_data = $parsed_lyrics3['raw']['unparsed']; while (strlen($raw_data) > 0) { $fieldname = substr($raw_data, 0, 3); $fieldsize = (int) substr($raw_data, 3, 5); $parsed_lyrics3['raw'][$fieldname] = substr($raw_data, 8, $fieldsize); $raw_data = substr($raw_data, 3 + 5 + $fieldsize); } if (isset($parsed_lyrics3['raw']['IND'])) { $i = 0; foreach (array('lyrics', 'timestamps', 'inhibitrandom') as $flagname) { if (strlen($parsed_lyrics3['raw']['IND']) > ++$i) { $parsed_lyrics3['flags'][$flagname] = getid3_lyrics3::IntString2Bool(substr($parsed_lyrics3['raw']['IND'], $i, 1)); } } } foreach (array('ETT' => 'title', 'EAR' => 'artist', 'EAL' => 'album', 'INF' => 'comment', 'AUT' => 'author') as $key => $value) { if (isset($parsed_lyrics3['raw'][$key])) { $parsed_lyrics3['comments'][$value][] = trim($parsed_lyrics3['raw'][$key]); } } if (isset($parsed_lyrics3['raw']['IMG'])) { foreach (explode("\r\n", $parsed_lyrics3['raw']['IMG']) as $key => $image_string) { if (strpos($image_string, '||') !== false) { $imagearray = explode('||', $image_string); $parsed_lyrics3['images'][$key]['filename'] = @$imagearray[0]; $parsed_lyrics3['images'][$key]['description'] = @$imagearray[1]; $parsed_lyrics3['images'][$key]['timestamp'] = getid3_lyrics3::Lyrics3Timestamp2Seconds(@$imagearray[2]); } } } if (isset($parsed_lyrics3['raw']['LYR'])) { getid3_lyrics3::Lyrics3LyricsTimestampParse($parsed_lyrics3); } } else { throw new getid3_exception('"LYRICS200" expected at ' . (ftell($getid3->fp) - 11 + $lyrics3_size - 9) . ' but found "' . substr($raw_data, strlen($raw_data) - 9, 9) . '" instead.'); } break; default: throw new getid3_exception('Cannot process Lyrics3 version ' . $lyrics3_version . ' (only v1 and v2)'); } if (isset($getid3->info['id3v1']['tag_offset_start']) && $getid3->info['id3v1']['tag_offset_start'] < $parsed_lyrics3['tag_offset_end']) { $getid3->warning('ID3v1 tag information ignored since it appears to be a false synch in Lyrics3 tag data'); unset($getid3->info['id3v1']); } $getid3->info['lyrics3'] = $parsed_lyrics3; // Check for APE tag after lyrics3 if (!@$getid3->info['ape'] && $getid3->option_tag_apetag && class_exists('getid3_apetag')) { $apetag = new getid3_apetag($getid3); $apetag->option_override_end_offset = $getid3->info['lyrics3']['tag_offset_start']; $apetag->Analyze(); } } return true; }
public function remove() { $engine = new getid3(); $engine->filename = $this->filename; $engine->fp = fopen($this->filename, 'rb'); $engine->include_module('tag.apetag'); $tag = new getid3_apetag($engine); $tag->Analyze(); if (isset($engine->info['ape']['tag_offset_start']) && isset($engine->info['ape']['tag_offset_end'])) { if (!($fp = @fopen($this->filename, 'a+b'))) { throw new getid3_exception('Could not open a+b: ' . $this->filename); } // get data after apetag if (filesize($this->filename) > $engine->info['ape']['tag_offset_end']) { fseek($fp, $engine->info['ape']['tag_offset_end'], SEEK_SET); $data_after_ape = fread($fp, filesize($this->filename) - $engine->info['ape']['tag_offset_end']); } // truncate file before start of apetag ftruncate($fp, $engine->info['ape']['tag_offset_start']); // rewrite data after apetag if (isset($data_after_ape)) { fseek($fp, $engine->info['ape']['tag_offset_start'], SEEK_SET); fwrite($fp, $data_after_ape, strlen($data_after_ape)); } fclose($fp); clearstatcache(); } // success when removing non-existant tag return true; }