Ejemplo n.º 1
0
        private static IPicture PictureFromData(ByteVector data)
        {
            if (data.Count < 9)
            {
                return(null);
            }
            int     offset = 0;
            Picture p      = new Picture();

            p.Type  = (PictureType)data[offset];
            offset += 1;
            int size = (int)data.Mid(offset, 4).ToUInt(false);

            offset += 4;
            int found = data.Find(ByteVector.TextDelimiter(StringType.UTF16LE), offset, 2);

            if (found < 0)
            {
                return(null);
            }
            p.MimeType = data.ToString(StringType.UTF16LE, offset, found - offset);
            offset     = found + 2;
            found      = data.Find(ByteVector.TextDelimiter(StringType.UTF16LE), offset, 2);
            if (found < 0)
            {
                return(null);
            }
            p.Description = data.ToString(StringType.UTF16LE, offset, found - offset);
            offset        = found + 2;
            p.Data        = data.Mid(offset, size);
            return(p);
        }
Ejemplo n.º 2
0
        /// <summary>
        ///    Populates the values in the current instance by parsing
        ///    its field data in a specified version.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the
        ///    extracted field data.
        /// </param>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is encoded in.
        /// </param>
        protected override void ParseFields(ByteVector data,
                                            byte version)
        {
            if (data.Count < 6)
            {
                throw new CorruptFileException(
                          "Not enough bytes in field.");
            }

            encoding         = (StringType)data [0];
            language         = data.ToString(StringType.Latin1, 1, 3);
            timestamp_format = (TimestampFormat)data [4];
            lyrics_type      = (SynchedTextType)data [5];

            ByteVector delim = ByteVector.TextDelimiter(
                encoding);
            int delim_index = data.Find(delim, 6, delim.Count);

            if (delim_index < 0)
            {
                throw new CorruptFileException(
                          "Text delimiter expected.");
            }

            description = data.ToString(encoding, 6,
                                        delim_index - 6);

            int offset           = delim_index + delim.Count;
            List <SynchedText> l = new List <SynchedText> ();

            while (offset + delim.Count + 4 < data.Count)
            {
                delim_index = data.Find(delim, offset,
                                        delim.Count);

                if (delim_index < offset)
                {
                    throw new CorruptFileException(
                              "Text delimiter expected.");
                }

                string text = data.ToString(encoding, offset,
                                            delim_index - offset);
                offset = delim_index + delim.Count;

                if (offset + 4 > data.Count)
                {
                    break;
                }

                l.Add(new SynchedText(data.Mid(offset, 4)
                                      .ToUInt(), text));
                offset += 4;
            }

            this.text = l.ToArray();
        }
        protected override void ParseFields(ByteVector data,
                                            byte version)
        {
            if (data.Count < 4)
            {
                throw new CorruptFileException(
                          "An object frame must contain at least 4 bytes.");
            }

            int start = 0;

            text_encoding = (StringType)data [start++];

            int end = data.Find(
                ByteVector.TextDelimiter(StringType.Latin1),
                start);

            if (end < start)
            {
                return;
            }

            mime_type = data.ToString(StringType.Latin1, start,
                                      end - start);

            ByteVector delim = ByteVector.TextDelimiter(
                text_encoding);

            start = end + 1;
            end   = data.Find(delim, start, delim.Count);

            if (end < start)
            {
                return;
            }

            file_name = data.ToString(text_encoding, start,
                                      end - start);
            start = end + delim.Count;
            end   = data.Find(delim, start, delim.Count);

            if (end < start)
            {
                return;
            }

            description = data.ToString(text_encoding, start,
                                        end - start);
            start = end + delim.Count;

            data.RemoveRange(0, start);
            this.data = data;
        }
Ejemplo n.º 4
0
        protected void ParseRawData()
        {
            if (raw_data == null)
            {
                return;
            }
            int pos = 0;
            int offset;

            text_encoding = (StringType)raw_data[pos++];
            if (raw_version > 2)
            {
                offset = raw_data.Find(ByteVector.TextDelimiter(StringType.Latin1), pos);
                if (offset < pos)
                {
                    return;
                }
                mime_type = raw_data.ToString(StringType.Latin1, pos, offset - pos);
                pos       = offset + 1;
            }
            else
            {
                ByteVector ext = raw_data.Mid(pos, 3);
                if (ext == "JPG")
                {
                    mime_type = "image/jpeg";
                }
                else if (ext == "PNG")
                {
                    mime_type = "image/png";
                }
                else
                {
                    mime_type = "image/unknown";
                }
                pos += 3;
            }
            ByteVector delim = ByteVector.TextDelimiter(text_encoding);

            type   = (PictureType)raw_data[pos++];
            offset = raw_data.Find(delim, pos, delim.Count);
            if (offset < pos)
            {
                return;
            }
            description = raw_data.ToString(text_encoding, pos, offset - pos);
            pos         = offset + delim.Count;
            raw_data.RemoveRange(0, pos);
            this.data     = raw_data;
            this.raw_data = null;
        }
		private void ParseRelativeVolumeFields(ByteVector data)
		{
			int pos = data.Find(TextDelimiter(StringType.Latin1));
			if (pos < 0)
				return;

			identification = data.Mid(0, pos).ToString(StringType.Latin1);
			pos += 1;

			// Each channel is at least 4 buffer.

			while (pos <= data.Count - 4)
			{
				Id3v2ChannelType type = (Id3v2ChannelType)data[pos];
				pos += 1;

				SetVolumeAdjustmentIndex(data.Mid(pos, 2).ToShort(), type);
				pos += 2;

				int bytes = BitsToBytes(data[pos]);
				pos += 1;

				SetPeakVolumeIndex(ParsePeakVolume(data.Mid(pos, bytes)), type);
				pos += bytes;
			}
		}
        /// <summary>
        ///    Populates the values in the current instance by parsing
        ///    its field data in a specified version.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the
        ///    extracted field data.
        /// </param>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is encoded in.
        /// </param>
        /// <exception cref="CorruptFileException">
        ///    <paramref name="data" /> contains less than 5 bytes.
        /// </exception>
        protected override void ParseFields(ByteVector data, byte version)
        {
            int pos = data.Find(ByteVector.TextDelimiter(StringType.Latin1));

            if (pos < 0)
            {
                return;
            }

            Identification = data.ToString(StringType.Latin1, 0, pos++);

            // Each channel is at least 4 bytes.

            while (pos <= data.Count - 4)
            {
                int type = data[pos++];

                unchecked {
                    channels[type].VolumeAdjustmentIndex = (short)data.Mid(pos, 2).ToUShort();
                }
                pos += 2;

                int bytes = BitsToBytes(data[pos++]);

                if (data.Count < pos + bytes)
                {
                    break;
                }

                channels[type].PeakVolumeIndex = data.Mid(pos, bytes).ToULong();
                pos += bytes;
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        ///    Reads a COM segment to find the JPEG comment.
        /// </summary>
        /// <param name="length">
        ///    The length of the segment that will be read.
        /// </param>
        private void ReadCOMSegment(int length)
        {
            if ((ImageTag.TagTypes & TagLib.TagTypes.JpegComment) != 0x00)
            {
                return;
            }

            long position = Tell;

            JpegCommentTag com_tag;

            if (length == 0)
            {
                com_tag = new JpegCommentTag();
            }
            else
            {
                ByteVector data = ReadBlock(length);

                int terminator = data.Find("\0", 0);

                if (terminator < 0)
                {
                    com_tag = new JpegCommentTag(data.ToString());
                }
                else
                {
                    com_tag = new JpegCommentTag(data.Mid(0, terminator).ToString());
                }
            }

            ImageTag.AddTag(com_tag);
            AddMetadataBlock(position - 4, length + 4);
        }
Ejemplo n.º 8
0
        /// <summary>
        ///     Populates the current instance by reading in a raw APEv2
        ///     item.
        /// </summary>
        /// <param name="data">
        ///     A <see cref="ByteVector" /> object containing the item to
        ///     read.
        /// </param>
        /// <param name="offset">
        ///     A <see cref="int" /> value specifying the offset in
        ///     <paramref name="data" /> at which the item data begins.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="data" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     <paramref name="offset" /> is less than zero.
        /// </exception>
        /// <exception cref="CorruptFileException">
        ///     A complete item could not be read.
        /// </exception>
        protected void Parse(ByteVector data, int offset)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            // 11 bytes is the minimum size for an APE item
            if (data.Count < offset + 11)
            {
                throw new CorruptFileException(
                          "Not enough data for APE Item");
            }

            var value_length = data.Mid(offset, 4)
                               .ToUInt(false);

            var flags = data.Mid(offset + 4, 4)
                        .ToUInt(false);

            ReadOnly = (flags & 1) == 1;
            Type     = (ItemType)((flags >> 1) & 3);

            var pos = data.Find(ByteVector.TextDelimiter(
                                    StringType.UTF8), offset + 8);

            Key = data.ToString(StringType.UTF8,
                                offset + 8, pos - offset - 8);

            if (value_length > data.Count - pos - 1)
            {
                throw new CorruptFileException(
                          "Invalid data length.");
            }

            Size = pos + 1 + (int)value_length - offset;

            if (Type == ItemType.Binary)
            {
                this.data = new ReadOnlyByteVector(
                    data.Mid(pos + 1, (int)value_length));
            }
            else
            {
                text = data.Mid(pos + 1,
                                (int)value_length)
                       .ToStrings(
                    StringType.UTF8, 0);
            }
        }
 protected override void ParseFields(ByteVector data, byte version)
 {
     ByteVector pattern = ByteVector.TextDelimiter(StringType.Latin1);
     int count = data.Find(pattern);
     if (count < 0)
     {
         throw new CorruptFileException("Popularimeter frame does not contain a text delimiter");
     }
     this.user = data.ToString(StringType.Latin1, 0, count);
     this.rating = data[count + 1];
     this.play_count = data.Mid(count + 2).ToULong();
 }
Ejemplo n.º 10
0
 private string ReadTerminatedString(ByteVector data, int start_index, out int terminator_index)
 {
     if (start_index >= data.Count)
     {
         throw new CorruptFileException("Unexpected End of Data");
     }
     terminator_index = data.Find("\0", start_index);
     if (terminator_index < 0)
     {
         throw new CorruptFileException("Cannot find string terminator");
     }
     return(data.Mid(start_index, terminator_index - start_index).ToString());
 }
Ejemplo n.º 11
0
        public UserCommentIFDEntry(ushort tag, ByteVector data, TagLib.File file)
        {
            Tag = tag;
            if (data.StartsWith(COMMENT_ASCII_CODE))
            {
                Value = TrimNull(data.ToString(StringType.Latin1, COMMENT_ASCII_CODE.Count, data.Count - COMMENT_ASCII_CODE.Count));
                return;
            }
            if (data.StartsWith(COMMENT_UNICODE_CODE))
            {
                Value = TrimNull(data.ToString(StringType.UTF8, COMMENT_UNICODE_CODE.Count, data.Count - COMMENT_UNICODE_CODE.Count));
                return;
            }
            var trimmed = data.ToString().Trim();

            if (trimmed.Length == 0 || trimmed == "\0")
            {
                Value = String.Empty;
                return;
            }
            if (data.StartsWith((byte)0x00) && data.Count >= 8)
            {
                int term = data.Find("\0", 8);
                if (term != -1)
                {
                    Value = data.ToString(StringType.Latin1, 8, term - 8);
                }
                else
                {
                    Value = data.ToString(StringType.Latin1, 8, data.Count - 8);
                }
                return;
            }
            if (data.Data.Length == 0)
            {
                Value = String.Empty;
                return;
            }
            int offset = 0;
            int length = data.Count - offset;

            if (data.StartsWith(COMMENT_BAD_UNICODE_CODE))
            {
                offset = COMMENT_BAD_UNICODE_CODE.Count;
                length = data.Count - offset;
            }
            file.MarkAsCorrupt("UserComment with other encoding than Latin1 or Unicode");
            Value = TrimNull(data.ToString(StringType.UTF8, offset, length));
        }
Ejemplo n.º 12
0
        protected override void ParseFields(ByteVector data, byte version)
        {
            ByteVector delim = ByteVector.TextDelimiter(StringType.Latin1);
            int        index = data.Find(delim);

            if (index < 0)
            {
                throw new CorruptFileException("Popularimeter frame does not contain a text delimiter");
            }
            if (index + 2 > data.Count)
            {
                throw new CorruptFileException("Popularimeter is too short");
            }
            user       = data.ToString(StringType.Latin1, 0, index);
            rating     = data[index + 1];
            play_count = data.Mid(index + 2).ToULong();
        }
Ejemplo n.º 13
0
        public IsoHandlerBox(BoxHeader header, TagLib.File file, IsoHandlerBox handler) :
            base(header, file, handler)
        {
            if (file == null)
            {
                throw new System.ArgumentNullException("file");
            }
            file.Seek(DataPosition + 4);
            ByteVector box_data = file.ReadBlock(DataSize - 4);

            handler_type = box_data.Mid(0, 4);
            int end = box_data.Find((byte)0, 16);

            if (end < 16)
            {
                end = box_data.Count;
            }
            name = box_data.ToString(StringType.UTF8, 16, end - 16);
        }
 protected override void ParseFields(ByteVector data, byte version)
 {
     if (data.Count < 4)
     {
         throw new CorruptFileException("An object frame must contain at least 4 bytes.");
     }
     int offset = 0;
     this.encoding = (StringType) data[offset++];
     int num2 = data.Find(ByteVector.TextDelimiter(StringType.Latin1), offset);
     if (num2 >= offset)
     {
         this.mime_type = data.ToString(StringType.Latin1, offset, num2 - offset);
         ByteVector pattern = ByteVector.TextDelimiter(this.encoding);
         offset = num2 + 1;
         num2 = data.Find(pattern, offset, pattern.Count);
         if (num2 >= offset)
         {
             this.file_name = data.ToString(this.encoding, offset, num2 - offset);
             offset = num2 + pattern.Count;
             num2 = data.Find(pattern, offset, pattern.Count);
             if (num2 >= offset)
             {
                 this.description = data.ToString(this.encoding, offset, num2 - offset);
                 offset = num2 + pattern.Count;
                 data.RemoveRange(0, offset);
                 this.data = data;
             }
         }
     }
 }
Ejemplo n.º 15
0
 public void Find()
 {
     Assert.AreEqual(17, TestVector.Find("RSTUV"));
     Assert.AreEqual(-1, TestVector.Find("NOOP"));
 }
        /// <summary>
        ///    Construcor.
        /// </summary>
        /// <param name="tag">
        ///    A <see cref="System.UInt16"/> with the tag ID of the entry this instance
        ///    represents
        /// </param>
        /// <param name="data">
        ///    A <see cref="ByteVector"/> to be stored
        /// </param>
        /// <param name="file">
        ///    The file that's currently being parsed, used for reporting corruptions.
        /// </param>
        public UserCommentIFDEntry(ushort tag, ByteVector data, TagLib.File file)
        {
            Tag = tag;

            if (data.StartsWith (COMMENT_ASCII_CODE)) {
                Value = TrimNull (data.ToString (StringType.Latin1, COMMENT_ASCII_CODE.Count, data.Count - COMMENT_ASCII_CODE.Count));
                return;
            }

            if (data.StartsWith (COMMENT_UNICODE_CODE)) {
                Value = TrimNull (data.ToString (StringType.UTF8, COMMENT_UNICODE_CODE.Count, data.Count - COMMENT_UNICODE_CODE.Count));
                return;
            }

            var trimmed = data.ToString ().Trim ();
            if (trimmed.Length == 0 || trimmed == "\0") {
                Value = String.Empty;
                return;
            }

            // Some programs like e.g. CanonZoomBrowser inserts just the first 0x00-byte
            // followed by 7-bytes of trash.
            if (data.StartsWith ((byte) 0x00) && data.Count >= 8) {

                // And CanonZoomBrowser fills some trailing bytes of the comment field
                // with '\0'. So we return only the characters before the first '\0'.
                int term = data.Find ("\0", 8);
                if (term != -1) {
                    Value = data.ToString (StringType.Latin1, 8, term - 8);
                } else {
                    Value = data.ToString (StringType.Latin1, 8, data.Count - 8);
                }
                return;
            }

            if (data.Data.Length == 0) {
                Value = String.Empty;
                return;
            }

            // Try to parse anyway
            int offset = 0;
            int length = data.Count - offset;

            // Corruption that starts with a Unicode header and a count byte.
            if (data.StartsWith (COMMENT_BAD_UNICODE_CODE)) {
                offset = COMMENT_BAD_UNICODE_CODE.Count;
                length = data.Count - offset;
            }

            file.MarkAsCorrupt ("UserComment with other encoding than Latin1 or Unicode");
            Value = TrimNull (data.ToString (StringType.UTF8, offset, length));
        }
Ejemplo n.º 17
0
		/// <summary>
		///    Populates the current instance by reading in a raw APEv2
		///    item.
		/// </summary>
		/// <param name="data">
		///    A <see cref="ByteVector" /> object containing the item to
		///    read.
		/// </param>
		/// <param name="offset">
		///    A <see cref="int" /> value specifying the offset in
		///    <paramref name="data" /> at which the item data begins.
		/// </param>
		/// <exception cref="ArgumentNullException">
		///    <paramref name="data" /> is <see langword="null" />.
		/// </exception>
		/// <exception cref="ArgumentOutOfRangeException">
		///    <paramref name="offset" /> is less than zero.
		/// </exception>
		/// <exception cref="CorruptFileException">
		///    A complete item could not be read.
		/// </exception>
		protected void Parse (ByteVector data, int offset)
		{
			if (data == null)
				throw new ArgumentNullException ("data");
			
			if (offset < 0)
				throw new ArgumentOutOfRangeException ("offset");
			
			
			// 11 bytes is the minimum size for an APE item
			if(data.Count < offset + 11)
				throw new CorruptFileException (
					"Not enough data for APE Item");
			
			uint value_length = data.Mid (offset, 4).ToUInt (false);
			uint flags = data.Mid (offset + 4, 4).ToUInt (false);
			
			ReadOnly = (flags & 1) == 1;
			Type = (ItemType) ((flags >> 1) & 3);
			
			int pos = data.Find (ByteVector.TextDelimiter (
				StringType.UTF8), offset + 8);
			
			key = data.ToString (StringType.UTF8,
				offset + 8, pos - offset - 8);
			
			if (value_length > data.Count - pos - 1)
				throw new CorruptFileException (
					"Invalid data length.");
			
			size_on_disk = pos + 1 + (int) value_length - offset;
			
			if (Type == ItemType.Binary)
				this.data = new ReadOnlyByteVector (
					data.Mid (pos + 1, (int) value_length));
			else
				this.text = data.Mid (pos + 1,
					(int) value_length).ToStrings (
						StringType.UTF8, 0);
		}
Ejemplo n.º 18
0
		/// <summary>
		///    Reads a null terminated string from the given data from given position.
		/// </summary>
		/// <param name="data">
		///    A <see cref="ByteVector"/> with teh data to read the string from
		/// </param>
		/// <param name="start_index">
		///    A <see cref="System.Int32"/> with the index to start reading
		/// </param>
		/// <param name="terminator_index">
		///    A <see cref="System.Int32"/> with the index of the null byte
		/// </param>
		/// <returns>
		///    A <see cref="System.String"/> with the read string. The null byte
		///    is not included.
		/// </returns>
		private string ReadTerminatedString (ByteVector data, int start_index, out int terminator_index)
		{
			if (start_index >= data.Count)
				throw new CorruptFileException ("Unexpected End of Data");

			terminator_index = data.Find ("\0", start_index);

			if (terminator_index < 0)
				throw new CorruptFileException ("Cannot find string terminator");

			return data.Mid (start_index, terminator_index - start_index).ToString ();
		}
        /// <summary>
        ///    Populates the values in the current instance by parsing
        ///    its field data in a specified version.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the
        ///    extracted field data.
        /// </param>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is encoded in.
        /// </param>
        /// <exception cref="CorruptFileException">
        ///    <paramref name="data" /> contains less than 5 bytes.
        /// </exception>
        protected override void ParseFields(ByteVector data,
            byte version)
        {
            int pos = data.Find (ByteVector.TextDelimiter (
                StringType.Latin1));
            if (pos < 0)
                return;

            identification = data.ToString (StringType.Latin1, 0,
                pos++);

            // Each channel is at least 4 bytes.

            while (pos <= data.Count - 4) {
                int type = data [pos++];

                unchecked {
                    channels [type].VolumeAdjustmentIndex =
                        (short) data.Mid (pos,
                            2).ToUShort ();
                }
                pos += 2;

                int bytes = BitsToBytes (data [pos++]);

                if (data.Count < pos + bytes)
                    break;

                channels [type].PeakVolumeIndex = data.Mid (pos,
                    bytes).ToULong ();
                pos += bytes;
            }
        }
 protected override void ParseFields(ByteVector data, byte version)
 {
     int startIndex = data.Find(ByteVector.TextDelimiter(StringType.Latin1));
     if (startIndex >= 0)
     {
         this.identification = data.ToString(StringType.Latin1, 0, startIndex++);
         while (startIndex <= (data.Count - 4))
         {
             int index = data[startIndex++];
             this.channels[index].VolumeAdjustmentIndex = (short) data.Mid(startIndex, 2).ToUShort();
             startIndex += 2;
             int length = BitsToBytes(data[startIndex++]);
             if (data.Count < (startIndex + length))
             {
                 break;
             }
             this.channels[index].PeakVolumeIndex = data.Mid(startIndex, length).ToULong();
             startIndex += length;
         }
     }
 }
        /// <summary>
        ///    Populates the values in the current instance by parsing
        ///    its field data in a specified version.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the
        ///    extracted field data.
        /// </param>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is encoded in.
        /// </param>
        protected override void ParseFields(ByteVector data,
            byte version)
        {
            if (data.Count < 6)
                throw new CorruptFileException (
                    "Not enough bytes in field.");

            encoding = (StringType) data [0];
            language = data.ToString (StringType.Latin1, 1, 3);
            timestamp_format = (TimestampFormat) data [4];
            lyrics_type = (SynchedTextType) data [5];

            ByteVector delim = ByteVector.TextDelimiter (
                encoding);
            int delim_index = data.Find (delim, 6, delim.Count);

            if (delim_index < 0)
                throw new CorruptFileException (
                    "Text delimiter expected.");

            description = data.ToString (encoding, 6,
                delim_index - 6);

            int offset = delim_index + delim.Count;
            List<SynchedText> l = new List<SynchedText> ();

            while (offset + delim.Count + 4 < data.Count) {
                delim_index = data.Find (delim, offset,
                    delim.Count);

                if (delim_index < offset)
                    throw new CorruptFileException (
                        "Text delimiter expected.");

                string text = data.ToString (encoding, offset,
                    delim_index - offset);
                offset = delim_index + delim.Count;

                if (offset + 4 > data.Count)
                    break;

                l.Add (new SynchedText (data.Mid (offset, 4)
                    .ToUInt (), text));
                offset += 4;
            }

            this.text = l.ToArray ();
        }
Ejemplo n.º 22
0
		/// <summary>
		///    Converts a raw ASF picture into an <see cref="IPicture"
		///    /> object.
		/// </summary>
		/// <param name="data">
		///    A <see cref="ByteVector" /> object containing raw ASF
		///    picture data.
		/// </param>
		/// <returns>
		///    A <see cref="IPicture" /> object to read from the raw
		///    data.
		/// </returns>
		private static IPicture PictureFromData (ByteVector data)
		{
			if (data.Count < 9)
				return null;
			
			int offset = 0;
			Picture p = new Picture ();
			
			// Get the picture type:
			
			p.Type = (PictureType) data [offset];
			offset += 1;
			
			// Get the picture size:
			
			int size = (int) data.Mid (offset, 4).ToUInt (false);
			offset += 4;
			
			// Get the mime-type:
			
			int found = data.Find (ByteVector.TextDelimiter (
				StringType.UTF16LE), offset, 2);
			if (found < 0)
				return null;
			
			p.MimeType = data.ToString (StringType.UTF16LE, offset,
				found - offset);
			offset = found + 2;
			
			// Get the description:
			
			found = data.Find (ByteVector.TextDelimiter (
				StringType.UTF16LE), offset, 2);
			if (found < 0)
				return null;
			
			p.Description = data.ToString (StringType.UTF16LE,
				offset, found - offset);
			offset = found + 2;
			
			p.Data = data.Mid (offset, size);
			
			return p;
		}
Ejemplo n.º 23
0
 protected void Parse(ByteVector data, int offset)
 {
     if (data == null)
     {
         throw new ArgumentNullException("data");
     }
     if (offset < 0)
     {
         throw new ArgumentOutOfRangeException("offset");
     }
     if (data.Count < (offset + 11))
     {
         throw new CorruptFileException("Not enough data for APE Item");
     }
     uint num = data.Mid(offset, 4).ToUInt(false);
     uint num2 = data.Mid(offset + 4, 4).ToUInt(false);
     this.ReadOnly = (num2 & 1) == 1;
     this.Type = ((ItemType) (num2 >> 1)) & (ItemType.Locator | ItemType.Binary);
     int num3 = data.Find(ByteVector.TextDelimiter(StringType.UTF8), offset + 8);
     this.key = data.ToString(StringType.UTF8, offset + 8, (num3 - offset) - 8);
     if (num > ((data.Count - num3) - 1))
     {
         throw new CorruptFileException("Invalid data length.");
     }
     this.size_on_disk = ((num3 + 1) + ((int) num)) - offset;
     if (this.Type == ItemType.Binary)
     {
         this.data = new ReadOnlyByteVector(data.Mid(num3 + 1, (int) num));
     }
     else
     {
         this.text = data.Mid(num3 + 1, (int) num).ToStrings(StringType.UTF8, 0);
     }
 }
 protected override void ParseFields(ByteVector data, byte version)
 {
     if (data.Count < 6)
     {
         throw new CorruptFileException("Not enough bytes in field.");
     }
     this.encoding = (StringType) data[0];
     this.language = data.ToString(StringType.Latin1, 1, 3);
     this.timestamp_format = (TimestampFormat) data[4];
     this.lyrics_type = (SynchedTextType) data[5];
     ByteVector pattern = ByteVector.TextDelimiter(this.encoding);
     int num = data.Find(pattern, 6, pattern.Count);
     if (num < 0)
     {
         throw new CorruptFileException("Text delimiter expected.");
     }
     this.description = data.ToString(this.encoding, 6, num - 6);
     int offset = num + pattern.Count;
     List<SynchedText> list = new List<SynchedText>();
     while (((offset + pattern.Count) + 4) < data.Count)
     {
         num = data.Find(pattern, offset, pattern.Count);
         if (num < offset)
         {
             throw new CorruptFileException("Text delimiter expected.");
         }
         string text = data.ToString(this.encoding, offset, num - offset);
         offset = num + pattern.Count;
         if ((offset + 4) > data.Count)
         {
             break;
         }
         list.Add(new SynchedText((long) data.Mid(offset, 4).ToUInt(), text));
         offset += 4;
     }
     this.text = list.ToArray();
 }
Ejemplo n.º 25
0
		public void Parse(ByteVector data)
		{
			if (data != null)
			{
				// 11 buffer is the minimum size for an APE item
				if (data.Count < 11)
				{
					TagLibDebugger.Debug("APE.Item.Parse() -- no data in item");
					return;
				}

				uint value_length = data.Mid(0, 4).ToUInt(false);
				uint flags = data.Mid(4, 4).ToUInt(false);

				int pos = data.Find(new ByteVector(1), 8);

				key = data.Mid(8, pos - 8).ToString(StringType.UTF8);
				value = data.Mid(pos + 1, (int)value_length);

				ReadOnly = (flags & 1) == 1;
				Type = (ApeItemType)((flags >> 1) & 3);

				if (Type != ApeItemType.Binary)
				{
					text.Clear();
					text = new StringCollection(ByteVectorCollection.Split(value, (byte)0), StringType.UTF8);
				}
			}
			else throw new ArgumentNullException("data");
		}
        /// <summary>
        ///    Populates the values in the current instance by parsing
        ///    its field data in a specified version.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the
        ///    extracted field data.
        /// </param>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is encoded in.
        /// </param>
        /// <exception cref="CorruptFileException">
        ///    <paramref name="data" /> contains less than 5 bytes.
        /// </exception>
        protected override void ParseFields(ByteVector data,
            byte version)
        {
            if (data.Count < 4)
                throw new CorruptFileException (
                    "An object frame must contain at least 4 bytes.");

            int start = 0;

            encoding =  (StringType) data [start++];

            int end = data.Find (
                ByteVector.TextDelimiter (StringType.Latin1),
                start);

            if (end < start)
                return;

            mime_type = data.ToString (StringType.Latin1, start,
                end - start);

            ByteVector delim = ByteVector.TextDelimiter (
                encoding);
            start = end + 1;
            end = data.Find (delim, start, delim.Count);

            if (end < start)
                return;

            file_name = data.ToString (encoding, start,
                end - start);
            start = end + delim.Count;
            end = data.Find (delim, start, delim.Count);

            if (end < start)
                return;

            description = data.ToString (encoding, start,
                end - start);
            start = end + delim.Count;

            data.RemoveRange (0, start);
            this.data = data;
        }
		private void ParseAttachedPictureFields(ByteVector data)
		{
			if (data != null)
			{
				if (data.Count < 5)
				{
					TagLibDebugger.Debug("A picture frame must contain at least 5 bytes.");
					return;
				}

				int pos = 0;

				textEncoding = (StringType)data[pos];
				pos += 1;

				int offset;

				if (Header.Version > 2)
				{
					offset = data.Find(TextDelimiter(StringType.Latin1), pos);

					if (offset < pos)
						return;

					mimeType = data.Mid(pos, offset - pos).ToString(StringType.Latin1);
					pos = offset + 1;
				}
				else
				{
					ByteVector ext = data.Mid(pos, 3);
					if (ext == "JPG")
						mimeType = "image/jpeg";
					else if (ext == "PNG")
						mimeType = "image/png";
					else
						mimeType = "image/unknown";

					pos += 3;
				}

				type = (PictureType)data[pos];
				pos += 1;

				offset = data.Find(TextDelimiter(textEncoding), pos);

				if (offset < pos)
					return;

				description = data.Mid(pos, offset - pos).ToString(textEncoding);
				pos = offset + 1;

				this.data = data.Mid(pos);			
			}
			else throw new ArgumentNullException("data");
		}
Ejemplo n.º 28
0
        /// <summary>
        ///    Performs the actual parsing of the raw data.
        /// </summary>
        /// <remarks>
        ///    Because of the high parsing cost and relatively low usage
        ///    of the class, <see cref="ParseFields" /> only stores the
        ///    field data so it can be parsed on demand. Whenever a
        ///    property or method is called which requires the data,
        ///    this method is called, and only on the first call does it
        ///    actually parse the data.
        /// </remarks>
        protected void ParseRawData()
        {
            if (file != null)
            {
                Load();
            }

            if (raw_data == null)
            {
                return;
            }

            data     = raw_data;
            raw_data = null;

            int pos = 0;
            int offset;

            encoding = (StringType)data[pos++];

            ByteVector delim = ByteVector.TextDelimiter(encoding);

            if (header.FrameId == FrameType.APIC)
            {
                // Retrieve an ID3v2 Attached Picture (APIC)

                if (raw_version > 2)
                {
                    offset = data.Find(ByteVector.TextDelimiter(StringType.Latin1), pos);

                    if (offset < pos)
                    {
                        return;
                    }

                    mime_type = data.ToString(StringType.Latin1, pos, offset - pos);
                    pos       = offset + 1;
                }
                else
                {
                    ByteVector ext = data.Mid(pos, 3);
                    mime_type = Picture.GetMimeFromExtension(ext.ToString());
                    pos      += 3;
                }

                Type = (PictureType)data[pos++];

                offset = data.Find(delim, pos, delim.Count);
            }
            else if (header.FrameId == FrameType.GEOB)
            {
                // Retrieve an ID3v2 General Encapsulated Object (GEOB)

                offset = data.Find(ByteVector.TextDelimiter(StringType.Latin1), pos);

                if (offset < pos)
                {
                    return;
                }

                mime_type = data.ToString(StringType.Latin1, pos, offset - pos);

                pos    = offset + 1;
                offset = data.Find(delim, pos, delim.Count);

                if (offset < pos)
                {
                    return;
                }

                filename = data.ToString(encoding, pos, offset - pos);
                pos      = offset + delim.Count;
                offset   = data.Find(delim, pos, delim.Count);

                Type = PictureType.NotAPicture;
            }
            else
            {
                throw new InvalidOperationException("Bad Frame type");
            }

            if (offset < pos)
            {
                return;
            }

            description = data.ToString(encoding, pos, offset - pos);
            pos         = offset + delim.Count;

            data.RemoveRange(0, pos);
        }
Ejemplo n.º 29
0
        /// <summary>
        ///    Construcor.
        /// </summary>
        /// <param name="tag">
        ///    A <see cref="System.UInt16"/> with the tag ID of the entry this instance
        ///    represents
        /// </param>
        /// <param name="data">
        ///    A <see cref="ByteVector"/> to be stored
        /// </param>
        /// <param name="file">
        ///    The file that's currently being parsed, used for reporting corruptions.
        /// </param>
        public UserCommentIFDEntry(ushort tag, ByteVector data, TagLib.File file)
        {
            Tag = tag;

            if (data.StartsWith(COMMENT_ASCII_CODE))
            {
                Value = TrimNull(data.ToString(StringType.Latin1, COMMENT_ASCII_CODE.Count, data.Count - COMMENT_ASCII_CODE.Count));
                return;
            }

            if (data.StartsWith(COMMENT_UNICODE_CODE))
            {
                Value = TrimNull(data.ToString(StringType.UTF8, COMMENT_UNICODE_CODE.Count, data.Count - COMMENT_UNICODE_CODE.Count));
                return;
            }

            var trimmed = data.ToString().Trim();

            if (trimmed.Length == 0 || trimmed == "\0")
            {
                Value = String.Empty;
                return;
            }

            // Some programs like e.g. CanonZoomBrowser inserts just the first 0x00-byte
            // followed by 7-bytes of trash.
            if (data.StartsWith((byte)0x00) && data.Count >= 8)
            {
                // And CanonZoomBrowser fills some trailing bytes of the comment field
                // with '\0'. So we return only the characters before the first '\0'.
                int term = data.Find("\0", 8);
                if (term != -1)
                {
                    Value = data.ToString(StringType.Latin1, 8, term - 8);
                }
                else
                {
                    Value = data.ToString(StringType.Latin1, 8, data.Count - 8);
                }
                return;
            }

            if (data.Data.Length == 0)
            {
                Value = String.Empty;
                return;
            }

            // Try to parse anyway
            int offset = 0;
            int length = data.Count - offset;

            // Corruption that starts with a Unicode header and a count byte.
            if (data.StartsWith(COMMENT_BAD_UNICODE_CODE))
            {
                offset = COMMENT_BAD_UNICODE_CODE.Count;
                length = data.Count - offset;
            }

            file.MarkAsCorrupt("UserComment with other encoding than Latin1 or Unicode");
            Value = TrimNull(data.ToString(StringType.UTF8, offset, length));
        }
Ejemplo n.º 30
0
		/// <summary>
		///    Populates the values in the current instance by parsing
		///    its field data in a specified version.
		/// </summary>
		/// <param name="data">
		///    A <see cref="ByteVector" /> object containing the
		///    extracted field data.
		/// </param>
		/// <param name="version">
		///    A <see cref="byte" /> indicating the ID3v2 version the
		///    field data is encoded in.
		/// </param>
		protected override void ParseFields (ByteVector data,
		                                     byte version)
		{
			ByteVector delim = ByteVector.TextDelimiter (
				StringType.Latin1);
			
			int index = data.Find (delim);
			if (index < 0)
				throw new CorruptFileException (
					"Popularimeter frame does not contain a text delimiter");
			
			user = data.ToString (StringType.Latin1, 0, index);
			rating = data [index + 1];
			play_count = data.Mid (index + 2).ToULong ();
		}
Ejemplo n.º 31
0
		/// <summary>
		///    Construcor.
		/// </summary>
		/// <param name="tag">
		///    A <see cref="System.UInt16"/> with the tag ID of the entry this instance
		///    represents
		/// </param>
		/// <param name="data">
		///    A <see cref="ByteVector"/> to be stored
		/// </param>
		public UserCommentIFDEntry (ushort tag, ByteVector data)
		{
			Tag = tag;

			if (data.StartsWith (COMMENT_ASCII_CODE)) {
				Value = data.ToString (StringType.Latin1, COMMENT_ASCII_CODE.Count, data.Count - COMMENT_ASCII_CODE.Count);
				return;
			}

			if (data.StartsWith (COMMENT_UNICODE_CODE)) {
				Value = data.ToString (StringType.UTF8, COMMENT_UNICODE_CODE.Count, data.Count - COMMENT_UNICODE_CODE.Count);
				return;
			}
				
			// Some programs like e.g. CanonZoomBrowser inserts just the first 0x00-byte
			// followed by 7-bytes of trash.
			if (data.StartsWith ((byte) 0x00) && data.Count >= 8) {
					
				// And CanonZoomBrowser fills some trailing bytes of the comment field
				// with '\0'. So we return only the characters before the first '\0'.
				int term = data.Find ("\0", 8);
				if (term != -1) {
					Value = data.ToString (StringType.Latin1, 8, term - 8);
				} else {
					Value = data.ToString (StringType.Latin1, 8, data.Count - 8);
				}
				return;
			}

			if (data.Data.Length == 0) {
				Value = String.Empty;
				return;
			}
			
			throw new NotImplementedException ("UserComment with other encoding than Latin1 or Unicode");
		}