public void ReadStream(Stream stream) { if (Utils.ReadString(EncodingType.ISO88591, stream, 3) == "ID3") { int num2; int num3; this.m_ID3v2Header = new ID3v2Header(stream, false); TagReadingInfo info1 = new TagReadingInfo(this.m_ID3v2Header.TagVersion); if (this.m_ID3v2Header.UsesUnsynchronization) { info1.TagVersionOptions = TagVersionOptions.Unsynchronized; } else { info1.TagVersionOptions = TagVersionOptions.None; } if (this.m_ID3v2Header.HasExtendedHeader) { this.m_ID3v2ExtendedHeader = new ID3v2ExtendedHeader(info1, stream); } int num1 = (info1.TagVersion == ID3v2TagVersion.ID3v22) ? 3 : 4; if (this.m_ID3v2Header.TagVersion != ID3v2TagVersion.ID3v24) { if (this.m_ID3v2Header.TagVersion == ID3v2TagVersion.ID3v22) { bool flag4 = true; num2 = 0; num3 = (this.m_ID3v2Header.TagSize - this.m_ID3v2ExtendedHeader.SizeIncludingSizeBytes) - num1; long num8 = stream.Position; Utils.Read(stream, num1); UnknownFrame frame1 = new UnknownFrame(null, info1, stream); num2 += frame1.FrameHeader.FrameSizeTotal; if (num2 < num3) { byte[] buffer2 = Utils.Read(stream, num1); if (((buffer2[0] < 0x30) || (buffer2[0] > 90)) && (((buffer2[1] >= 0x30) && (buffer2[1] <= 90)) && ((buffer2[2] >= 0x30) && (buffer2[2] <= 90)))) { Trace.WriteLine("ID3v2.2 frame size off by 1 byte"); flag4 = false; } } stream.Position = num8; if (!flag4) { info1.TagVersionOptions |= TagVersionOptions.AddOneByteToSize; } } } else { bool flag1 = true; num2 = 0; num3 = (this.m_ID3v2Header.TagSize - this.m_ID3v2ExtendedHeader.SizeIncludingSizeBytes) - num1; long num4 = stream.Position; while (num2 < num3) { byte[] buffer1 = Utils.Read(stream, num1); if ((((buffer1[0] < 0x30) || (buffer1[0] > 90)) || ((buffer1[1] < 0x30) || (buffer1[1] > 90))) || (((buffer1[2] < 0x30) || (buffer1[2] > 90)) || ((buffer1[3] < 0x30) || (buffer1[3] > 90)))) { if ((buffer1[0] != 0) && (buffer1[0] != 0xff)) { } break; } int num5 = Utils.ReadInt32(stream); if (num5 > 0xff) { if ((num5 & 0x80) == 0x80) { flag1 = false; break; } if ((num5 & 0x8000) == 0x8000) { flag1 = false; break; } if ((num5 & 0x800000) == 0x800000) { flag1 = false; break; } if (((num2 + num5) + 10) == this.m_ID3v2Header.TagSize) { flag1 = false; break; } stream.Seek((long) (-4), SeekOrigin.Current); int num6 = Utils.ReadInt32SyncSafe(stream); long num7 = stream.Position; bool flag2 = true; bool flag3 = true; if (((num7 + num5) + 2) >= num3) { flag1 = true; break; } stream.Seek((num7 + num5) + 2, SeekOrigin.Begin); buffer1 = Utils.Read(stream, num1); if ((((buffer1[0] < 0x30) || (buffer1[0] > 90)) || ((buffer1[1] < 0x30) || (buffer1[1] > 90))) || (((buffer1[2] < 0x30) || (buffer1[2] > 90)) || ((buffer1[3] < 0x30) || (buffer1[3] > 90)))) { flag3 = false; } stream.Seek((num7 + num6) + 2, SeekOrigin.Begin); buffer1 = Utils.Read(stream, num1); if ((((buffer1[0] < 0x30) || (buffer1[0] > 90)) || ((buffer1[1] < 0x30) || (buffer1[1] > 90))) || (((buffer1[2] < 0x30) || (buffer1[2] > 90)) || ((buffer1[3] < 0x30) || (buffer1[3] > 90)))) { flag2 = false; } if (flag3 != flag2) { flag1 = flag2; } break; } stream.Seek((long) (num5 + 2), SeekOrigin.Current); num2 += num5 + 10; } stream.Position = num4; if (!flag1) { info1.TagVersionOptions |= TagVersionOptions.UseNonSyncSafeFrameSizeID3v24; } } num3 = (this.m_ID3v2Header.TagSize - this.m_ID3v2ExtendedHeader.SizeIncludingSizeBytes) - num1; base.Read(stream, this.m_ID3v2Header.TagVersion, info1, num3, num1); } }
internal void Read(Stream stream, ID3v2TagVersion tagVersion, TagReadingInfo tagReadingInfo, int readUntil, int frameIDSize) { Dictionary<string, IBindingList> multipleOccurrenceFrames = GetMultipleOccurrenceFrames(tagVersion); Dictionary<string, IFrame> singleOccurrenceFrames = GetSingleOccurrenceFrames(tagVersion); int bytesRead = 0; while (bytesRead < readUntil) { byte[] frameIDBytes = stream.Read(frameIDSize); // If character is not a letter or number, padding reached, audio began, // or otherwise the frame is not readable if (frameIDSize == 4) { if (frameIDBytes[0] < 0x30 || frameIDBytes[0] > 0x5A || frameIDBytes[1] < 0x30 || frameIDBytes[1] > 0x5A || frameIDBytes[2] < 0x30 || frameIDBytes[2] > 0x5A || frameIDBytes[3] < 0x30 || frameIDBytes[3] > 0x5A) { // TODO: Try to keep reading and look for a valid frame if (frameIDBytes[0] != 0 && frameIDBytes[0] != 0xFF) { string msg = string.Format("Out of range FrameID - 0x{0:X}|0x{1:X}|0x{2:X}|0x{3:X}", frameIDBytes[0], frameIDBytes[1], frameIDBytes[2], frameIDBytes[3]); if (ByteUtils.ISO88591GetString(frameIDBytes) != "MP3e") { string tmpBadFrameID = ByteUtils.ISO88591GetString(frameIDBytes).TrimEnd('\0'); Trace.WriteLine(msg + " - " + tmpBadFrameID); } } break; } } else if (frameIDSize == 3) { if (frameIDBytes[0] < 0x30 || frameIDBytes[0] > 0x5A || frameIDBytes[1] < 0x30 || frameIDBytes[1] > 0x5A || frameIDBytes[2] < 0x30 || frameIDBytes[2] > 0x5A) { // TODO: Try to keep reading and look for a valid frame if (frameIDBytes[0] != 0 && frameIDBytes[0] != 0xFF) { string msg = string.Format("Out of range FrameID - 0x{0:X}|0x{1:X}|0x{2:X}", frameIDBytes[0], frameIDBytes[1], frameIDBytes[2]); Trace.WriteLine(msg); Trace.WriteLine(ByteUtils.ISO88591GetString(frameIDBytes)); } break; } } string frameID = ByteUtils.ISO88591GetString(frameIDBytes); // TODO: Take out //Console.WriteLine(tmpFrameID); // TODO: take out /* COMM Frames: SoundJam_CDDB_TrackNumber SoundJam_CDDB_1 iTunNORM iTunSMPB iTunes_CDDB_IDs iTunes_CDDB_1 iTunes_CDDB_TrackNumber */ IFrame frame; do { IBindingList bindingList; if (singleOccurrenceFrames.TryGetValue(frameID, out frame)) { frame.Read(tagReadingInfo, stream); bytesRead += frame.FrameHeader.FrameSizeTotal; //m_ReadFrames.Add(tmpFrame); } else if (multipleOccurrenceFrames.TryGetValue(frameID, out bindingList)) { frame = (IFrame)bindingList.AddNew(); frame.Read(tagReadingInfo, stream); //m_ReadFrames.Add(tmpFrame); bytesRead += frame.FrameHeader.FrameSizeTotal; } else { if (tagVersion == ID3v2TagVersion.ID3v24) { string newFrameID; if (_id3v24FrameAliases.TryGetValue(frameID, out newFrameID)) frameID = newFrameID; else break; } else if (tagVersion == ID3v2TagVersion.ID3v23) { string newFrameID; if (_id3v23FrameAliases.TryGetValue(frameID, out newFrameID)) frameID = newFrameID; else break; } else { break; } } } while (frame == null); // Frame is unknown if (frame == null) { if (frameID != "NCON" && // non standard (old music match) frameID != "MJMD" && // Non standard frame (Music Match XML) frameID != "TT22" && // 000.00 - maybe meant to be 3 letter TT2 frame, and value be 2000.00? still makes no sense frameID != "PCST" && // null data frameID != "TCAT" && // category (ie, comedy) (distorted view) frameID != "TKWD" && // looks like blog tags "comedy funny weird", etc (distorted view) frameID != "TDES" && // xml file - used by distortedview.com frameID != "TGID" && // url (from distortedview) frameID != "WFED" && // url (thanks distortedview) frameID != "CM1" && // some kind of comment, seen in ID3v2.2 frameID != "TMB" && // ripped by something other, not in spec frameID != "RTNG" && frameID != "XDOR" && // year frameID != "XSOP" && // looks like artist, "Allman Brothers Band, The" frameID != "TENK") // itunes encoder (todo: add alias?) { /*String msg = String.Format("Unrecognized FrameID '{0}' (not critical)", tmpFrameID); Trace.WriteLine(msg);*/ } UnknownFrame unknownFrame = new UnknownFrame(frameID, tagReadingInfo, stream); _unknownFrames.Add(unknownFrame); //m_ReadFrames.Add(tmpUNKN); bytesRead += unknownFrame.FrameHeader.FrameSizeTotal; } } // Process iTunes comments foreach (var comment in new List<IComments>(m_CommentsList)) { if (comment.Description != null && comment.Description.StartsWith("iTun")) { m_CommentsList.Remove(comment); m_iTunesCommentsList.Add(comment); } } // Process genre // TODO: may need cleanup if (!string.IsNullOrEmpty(m_Genre.Value)) { if (m_Genre.Value.StartsWith("(")) { int closeIndex = m_Genre.Value.IndexOf(')'); if (closeIndex != -1) { if (closeIndex != m_Genre.Value.Length - 1) { // Take text description m_Genre.Value = m_Genre.Value.Substring(closeIndex + 1, m_Genre.Value.Length - (closeIndex + 1)); } else { // Lookup genre value string innerValue = m_Genre.Value.Substring(1, closeIndex - 1); int innerValueResult; if (int.TryParse(innerValue, out innerValueResult)) { if (GenreHelper.GenreByIndex.Length > innerValueResult && innerValueResult >= 0) { m_Genre.Value = GenreHelper.GenreByIndex[innerValueResult]; } else { Trace.WriteLine("Unrecognized genre"); } } else { Trace.WriteLine("Unrecognized genre"); } } } } } }