function getLyrics3Data(&$ThisFileInfo, &$fd, $endoffset, $version, $length) { // http://www.volweb.cz/str/tags.htm fseek($fd, $endoffset, SEEK_SET); $rawdata = fread($fd, $length); if (substr($rawdata, 0, 11) != 'LYRICSBEGIN') { if (strpos($rawdata, 'LYRICSBEGIN') !== false) { $ThisFileInfo['warning'] .= "\n" . '"LYRICSBEGIN" expected at ' . $endoffset . ' but actually found at ' . ($endoffset + strpos($rawdata, 'LYRICSBEGIN')) . ' - this is invalid for Lyrics3 v' . $version; $rawdata = substr($rawdata, strpos($rawdata, 'LYRICSBEGIN')); $length = strlen($rawdata); } else { $ThisFileInfo['error'] .= "\n" . '"LYRICSBEGIN" expected at ' . $endoffset . ' but found "' . substr($rawdata, 0, 11) . '" instead'; return false; } } switch ($version) { case 1: if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICSEND') { $ThisFileInfo['lyrics3']['raw']['lyrics3version'] = $version; $ThisFileInfo['lyrics3']['raw']['lyrics3tagsize'] = $length; $ThisFileInfo['lyrics3']['raw']['LYR'] = trim(substr($rawdata, 11, strlen($rawdata) - 11 - 9)); Lyrics3LyricsTimestampParse($ThisFileInfo); } else { $ThisFileInfo['error'] .= "\n" . '"LYRICSEND" expected at ' . (ftell($fd) - 11 + $length - 9) . ' but found "' . substr($rawdata, strlen($rawdata) - 9, 9) . '" instead'; } break; case 2: if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICS200') { $ThisFileInfo['lyrics3']['raw']['lyrics3version'] = $version; $ThisFileInfo['lyrics3']['raw']['lyrics3tagsize'] = $length; $ThisFileInfo['lyrics3']['raw']['unparsed'] = substr($rawdata, 11, strlen($rawdata) - 11 - 9 - 6); // LYRICSBEGIN + LYRICS200 + LSZ $rawdata = $ThisFileInfo['lyrics3']['raw']['unparsed']; while (strlen($rawdata) > 0) { $fieldname = substr($rawdata, 0, 3); $fieldsize = (int) substr($rawdata, 3, 5); $ThisFileInfo['lyrics3']['raw']["{$fieldname}"] = substr($rawdata, 8, $fieldsize); $rawdata = substr($rawdata, 3 + 5 + $fieldsize); } if (isset($ThisFileInfo['lyrics3']['raw']['IND'])) { $i = 0; $flagnames = array('lyrics', 'timestamps', 'inhibitrandom'); foreach ($flagnames as $flagname) { if (strlen($ThisFileInfo['lyrics3']['raw']['IND']) > ++$i) { $ThisFileInfo['lyrics3']['flags']["{$flagname}"] = IntString2Bool(substr($ThisFileInfo['lyrics3']['raw']['IND'], $i, 1)); } } } $fieldnametranslation = array('ETT' => 'title', 'EAR' => 'artist', 'EAL' => 'album', 'INF' => 'comment', 'AUT' => 'author'); foreach ($fieldnametranslation as $key => $value) { if (isset($ThisFileInfo['lyrics3']['raw']["{$key}"])) { $ThisFileInfo['lyrics3']['comments']["{$value}"] = $ThisFileInfo['lyrics3']['raw']["{$key}"]; } } if (!empty($ThisFileInfo['lyrics3']['comments'])) { CopyFormatCommentsToRootComments($ThisFileInfo['lyrics3']['comments'], $ThisFileInfo, true, false, false); } if (isset($ThisFileInfo['lyrics3']['raw']['IMG'])) { $imagestrings = explode("\r\n", $ThisFileInfo['lyrics3']['raw']['IMG']); foreach ($imagestrings as $key => $imagestring) { if (strpos($imagestring, '||') !== false) { $imagearray = explode('||', $imagestring); $ThisFileInfo['lyrics3']['images']["{$key}"]['filename'] = $imagearray[0]; $ThisFileInfo['lyrics3']['images']["{$key}"]['description'] = $imagearray[1]; $ThisFileInfo['lyrics3']['images']["{$key}"]['timestamp'] = Lyrics3Timestamp2Seconds($imagearray[2]); } } } if (isset($ThisFileInfo['lyrics3']['raw']['LYR'])) { Lyrics3LyricsTimestampParse($ThisFileInfo); } } else { $ThisFileInfo['error'] .= "\n" . '"LYRICS200" expected at ' . (ftell($fd) - 11 + $length - 9) . ' but found "' . substr($rawdata, strlen($rawdata) - 9, 9) . '" instead'; } break; default: $ThisFileInfo['error'] .= "\n" . 'Cannot process Lyrics3 version ' . $version . ' (only v1 and v2)'; break; } if (isset($ThisFileInfo['lyrics3'])) { $ThisFileInfo['tags'][] = 'lyrics3'; } return true; }
function ParseOggPageHeader(&$fd) { // http://xiph.org/ogg/vorbis/doc/framing.html $basefileoffset = ftell($fd); // where we started from in the file $filedata = fread($fd, FREAD_BUFFER_SIZE); $filedataoffset = 0; while (substr($filedata, $filedataoffset++, 4) != 'OggS') { if (ftell($fd) - $basefileoffset >= 10000) { // should be found before here return FALSE; } if (strlen($filedata) < 1024) { if (feof($fd) || ($filedata .= fread($fd, FREAD_BUFFER_SIZE)) === FALSE) { // get some more data, unless eof, in which case fail return FALSE; } } } $filedataoffset += strlen('OggS') - 1; // page, delimited by 'OggS' $stream_structure_version = ord(substr($filedata, $filedataoffset++, 1)); $header_type_flag = BigEndian2Bin(substr($filedata, $filedataoffset++, 1)); $header_type_flag_fresh = IntString2Bool($header_type_flag[5]); // fresh packet $header_type_flag_bos = IntString2Bool($header_type_flag[6]); // first page of logical bitstream (bos) $header_type_flag_eos = IntString2Bool($header_type_flag[7]); // last page of logical bitstream (eos) $pcm_absolute_position = LittleEndian2Int(substr($filedata, $filedataoffset, 8)); $filedataoffset += 8; $stream_serial_number = LittleEndian2Int(substr($filedata, $filedataoffset, 4)); $filedataoffset += 4; $page_seq_no = LittleEndian2Int(substr($filedata, $filedataoffset, 4)); $filedataoffset += 4; $page_checksum = LittleEndian2Int(substr($filedata, $filedataoffset, 4)); $filedataoffset += 4; $page_segments = LittleEndian2Int(substr($filedata, $filedataoffset, 1)); $filedataoffset += 1; for ($i = 0; $i < $page_segments; $i++) { $segment_table["{$i}"] = LittleEndian2Int(substr($filedata, $filedataoffset++, 1)); } $packettype = ord(substr($filedata, $filedataoffset, 1)); $filedataoffset += 1; $streamtype = substr($filedata, $filedataoffset, 6); // hard-coded to 'vorbis' $filedataoffset += 6; fseek($fd, $filedataoffset + $basefileoffset, SEEK_SET); $oggheader['packet_type'] = $packettype; $oggheader['stream_type'] = $streamtype; $oggheader['stream_structver'] = $stream_structure_version; $oggheader['flag']['fresh'] = $header_type_flag_fresh; $oggheader['flag']['bos'] = $header_type_flag_fresh; $oggheader['flag']['eos'] = $header_type_flag_fresh; $oggheader['pcm_abs_position'] = $pcm_absolute_position; $oggheader['stream_serialno'] = $stream_serial_number; $oggheader['page_seqno'] = $page_seq_no; $oggheader['page_checksum'] = $page_checksum; $oggheader['page_segments'] = $page_segments; $oggheader['segment_table'] = $segment_table; return $oggheader; }