Esempio n. 1
0
        /*
         * ID3			Tag identifier
         * 04 00		2 bytes version
         * xx			Tag flags
         * xx xx xx xx	Tag size excluding header and footer as syncsafe int
         * [Extended header]
         * {Frames}
         * [Padding]
         * [Footer]
         */
        private static void EncodeID3v2_4Tag(Stream s, ID3v2Tag tag)
        {
            byte flagByte = 0;
            long paddingLen, size;

            const long TagHeaderSize = 10L;

            if ((tag.Flags & ID3v2TagFlags.Unsync) == ID3v2TagFlags.Unsync) {
                flagByte |= 0x80;
            }
            if (tag.ExtendedHeader != null) {
                flagByte |= 0x40;
            }
            if ((tag.Flags & ID3v2TagFlags.Experimental) == ID3v2TagFlags.Experimental) {
                flagByte |= 0x20;
            }
            if ((tag.Flags & ID3v2TagFlags.Footer) == ID3v2TagFlags.Footer) {
                flagByte |= 0x10;
            }

            StringEncoder.WriteLatin1String(s, "ID3", 3);
            s.WriteByte(0x04);
            s.WriteByte(0x00);
            s.WriteByte(flagByte);

            /* skip size */
            s.Position += 4;

            if (tag.ExtendedHeader != null) {
                byte[] frameData = GetFrameRawData(tag);
                long crc = -1L;

                if ((tag.ExtendedHeader.Flags & ExtendedHeaderFlags.CrcPresent) == ExtendedHeaderFlags.CrcPresent) {
                    /* CRC is calculated on frame data and padding */
                    Crc32 crcCalc = new Crc32();
                    crcCalc.UpdateCrc(frameData);
                    crcCalc.UpdateCrcWithZero(ComputePaddingSize(frameData.Length + TagHeaderSize, tag));
                    crc = crcCalc.Crc;
                }
                EncodeID3v2_4ExtendedHeader(s, tag.ExtendedHeader, crc);
                s.Write(frameData, 0, frameData.Length);

            } else {
                foreach (Frame f in tag.Frames) {
                    FrameEncoder.EncodeFrame(s, f, tag);
                }
            }

            paddingLen = ComputePaddingSize(s.Length, tag);
            s.SetLength(s.Length + paddingLen);
            size = s.Length - TagHeaderSize;

            if ((tag.Flags & ID3v2TagFlags.Footer) == ID3v2TagFlags.Footer) {
                s.Position = s.Length - 1L;
                StringEncoder.WriteLatin1String(s, "3DI", 3);
                s.WriteByte(0x04);
                s.WriteByte(0x00);
                s.WriteByte(flagByte);
                NumberConverter.WriteInt(size, s, 4, true);
            }

            s.Position = 6L;
            NumberConverter.WriteInt(size, s, 4, true);
        }
Esempio n. 2
0
        /*
         * xx xx xx xx		Extended Header size, excluding itself; currently 6 or 10 bytes; not sync safe.
         * xx xx			Flags
         * xx xx xx xx		Size of padding; not sync safe
         * [xx xx xx xx]	4 bytes of CRC Data; not sync safe
         *
         */
        private static int DecodeID3v2_3ExtendedHeader(byte[] tagContent, ExtendedHeader extHeader)
        {
            int extHeaderSize, paddingSize;

            CheckLength(tagContent, 10);
            extHeaderSize = NumberConverter.ReadInt32(tagContent, 0, 4, false);
            paddingSize = NumberConverter.ReadInt32(tagContent, 6, 4, false);

            if ((tagContent[4] & 0x7F) != 0 || tagContent[5] != 0x00) {
                throw new ID3ParseException("Unknown extended header flag set.");
            }

            if (tagContent[4] == 0x80) {
                extHeader.Flags = ExtendedHeaderFlags.CrcPresent;
                if (extHeaderSize != 10) {
                    throw new ID3ParseException("Invalid extended header size.");
                }
                CheckLength(tagContent, 14);

                long savedCrc = NumberConverter.ReadInt64(tagContent, 10, 4, false);
                int dataLength = tagContent.Length - 14 - paddingSize;
                Crc32 crcCalculator = new Crc32();

                if (dataLength < 0) {
                    throw new ID3ParseException("Padding size mismatch in extended header.");
                }
                crcCalculator.UpdateCrc(tagContent, 14, dataLength);
                if (savedCrc != crcCalculator.Crc) {
                    throw new ID3CrcMismatchException(savedCrc, crcCalculator.Crc);
                }
                extHeader.CrcChecksum = savedCrc;

            } else {
                extHeader.Flags = ExtendedHeaderFlags.None;
                if (extHeaderSize != 6) {
                    throw new ID3ParseException("Invalid extended header size.");
                }
            }

            return extHeaderSize;
        }
Esempio n. 3
0
        /*
         * xx xx xx xx				Extended header size(min 6) as syncsafe int
         * xx						Number of flag bytes(currently 1)
         * xx						Flags
         * {sizeByte [flagdata]}	For every set bit in flag one entry
         *
         */
        private static int DecodeID3v2_4ExtendedHeader(byte[] tagContent, ExtendedHeader extHeader)
        {
            int extHeaderSize, index;

            CheckLength(tagContent, 6);
            extHeaderSize = NumberConverter.ReadInt32(tagContent, 0, 4, true);
            if (extHeaderSize < 6) {
                throw new ID3ParseException("Size mismatch in extended header.");
            }
            if (tagContent[4] != 0x01) {
                throw new ID3ParseException("Flag byte count in extended header does not match.");
            }
            CheckLength(tagContent, extHeaderSize);

            /* parse extended header flags */
            extHeader.Flags = ExtendedHeaderFlags.None;
            index = 6;
            if ((tagContent[5] & 0x40) != 0) {
                extHeader.Flags |= ExtendedHeaderFlags.UpdateTag;
                if (index >= extHeaderSize || tagContent[index] != 0x00) {
                    throw new ID3ParseException("Error while parsing extended header flag data.");
                }
                index += 1;
            }
            if ((tagContent[5] & 0x20) != 0) {
                extHeader.Flags |= ExtendedHeaderFlags.CrcPresent;
                if (index + 5 >= extHeaderSize || tagContent[index] != 0x05) {
                    throw new ID3ParseException("Error while parsing extended header flag data.");
                }

                long savedCrc = NumberConverter.ReadInt64(tagContent, index + 1, 5, true);
                Crc32 crcCalculator = new Crc32();

                crcCalculator.UpdateCrc(tagContent, extHeaderSize, tagContent.Length - extHeaderSize);
                if (savedCrc != crcCalculator.Crc) {
                    throw new ID3CrcMismatchException(savedCrc, crcCalculator.Crc);
                }
                extHeader.CrcChecksum = savedCrc;

                index += 6;
            }
            if ((tagContent[5] & 0x10) != 0) {
                extHeader.Flags |= ExtendedHeaderFlags.RestrictTag;
                if (index + 1 >= extHeaderSize || tagContent[index] != 0x01) {
                    throw new ID3ParseException("Error while parsing extended header flag data.");
                }
                index += 1;
                extHeader.TagSizeRestriction = (TagSizeRestriction)(tagContent[index] & 0xC0);
                extHeader.TextEncodingRestriction = (TextEncodingRestriction)(tagContent[index] & 0x20);
                extHeader.TextFieldSizeRestriction = (TextFieldSizeRestriction)(tagContent[index] & 0x18);
                extHeader.ImageEncodingRestriction = (ImageEncodingRestriction)(tagContent[index] & 0x4);
                extHeader.ImageSizeRestriction = (ImageSizeRestriction)(tagContent[index] & 0x3);
                index += 1;
            }
            if ((tagContent[5] & 0x8F) != 0) {
                throw new ID3ParseException("Invalid entended header flag set.");
            }
            if (index != extHeaderSize) {
                throw new ID3ParseException("Size mismatch in extended header.");
            }

            return extHeaderSize;
        }
Esempio n. 4
0
        public static long ComputeCrc(byte[] buffer, int offset, int count)
        {
            Crc32 tmp = new Crc32();

            tmp.UpdateCrc(buffer, offset, count);

            return tmp.Crc;
        }