예제 #1
0
        public static ExthHeader FromBinary(ArraySegment <byte> bytes)
        {
            if (bytes.Array == null)
            {
                throw new ArgumentException("bytes array cannot be null");
            }

            var header = new ExthHeader();

            try
            {
                if (bytes.Count < MinimalHeaderSize)
                {
                    throw new Exception("bytes not long enough");
                }

                using (var stream = new MemoryStream(bytes.Array, bytes.Offset, bytes.Count))
                    using (var reader = new BinaryReader(stream))
                    {
                        ////seek in stream
                        //reader.BaseStream.Seek(offset, SeekOrigin.Begin);

                        //grab identifier
                        var identifier = reader.ReadUInt32(Endian.BigEndian);
                        if (ExthIdentifier != identifier)
                        {
                            throw new NotSupportedException("identifier not supported");
                        }

                        //grab header length
                        header._length = reader.ReadUInt32(Endian.BigEndian);

                        //grab record count
                        var recordCount = reader.ReadUInt32(Endian.BigEndian);

                        //grab records
                        for (int recordIndex = 0; recordIndex < recordCount; recordIndex++)
                        {
                            uint recordType = reader.ReadUInt32(Endian.BigEndian);

                            //substract 8 for 8 bytes alread red
                            uint recordDataLength = reader.ReadUInt32(Endian.BigEndian) - 8;

                            byte[] recordData = new byte[recordDataLength];

                            checked { reader.Read(recordData, 0, (int)recordDataLength); }

                            header.Records.Add(new ExthRecord(recordType, recordData));
                        }

                        //additional zero padding
                    }

                return(header);
            }
            catch (Exception e)
            {
                throw new Exception("Exception caught when parsing exth header", e);
            }
        }
예제 #2
0
        public static ExthHeader FromBinary(ArraySegment<byte> bytes)
        {
            if(bytes.Array == null)
                throw new ArgumentException("bytes array cannot be null");

            var header = new ExthHeader();

            try
            {
                if (bytes.Count < MinimalHeaderSize)
                    throw new Exception("bytes not long enough");

                using(var stream = new MemoryStream(bytes.Array, bytes.Offset, bytes.Count))
                using (var reader = new BinaryReader(stream))
                {
                    ////seek in stream
                    //reader.BaseStream.Seek(offset, SeekOrigin.Begin);

                    //grab identifier
                    var identifier = reader.ReadUInt32(Endian.BigEndian);
                    if (ExthIdentifier != identifier)
                        throw new NotSupportedException("identifier not supported");

                    //grab header length
                    header._length = reader.ReadUInt32(Endian.BigEndian);

                    //grab record count
                    var recordCount = reader.ReadUInt32(Endian.BigEndian);

                    //grab records
                    for (int recordIndex = 0; recordIndex < recordCount; recordIndex++)
                    {
                        uint recordType = reader.ReadUInt32(Endian.BigEndian);

                        //substract 8 for 8 bytes alread red
                        uint recordDataLength = reader.ReadUInt32(Endian.BigEndian) - 8;

                        byte[] recordData = new byte[recordDataLength];

                        checked { reader.Read(recordData, 0, (int)recordDataLength); }

                        header.Records.Add(new ExthRecord(recordType, recordData));
                    }

                    //additional zero padding
                }

                return header;
            }
            catch (Exception e)
            {
                throw new Exception("Exception caught when parsing exth header", e);
            }
        }
예제 #3
0
        /// <summary>
        /// Creates new instance of mobipocket header from provided bytes
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static MobipocketHeader FromBinary(ArraySegment <byte> bytes)
        {
            if (bytes.Array == null)
            {
                throw new ArgumentException("bytes array cannot be null");
            }

            var header = new MobipocketHeader();

            try
            {
                using (var stream = new MemoryStream(bytes.Array, bytes.Offset, bytes.Count))
                    using (var reader = new BinaryReader(stream))
                    {
                        if (bytes.Count < 0x80)
                        {
                            throw new Exception("header is to small");
                        }

                        //palmdoc header start

                        //Get compression
                        header.Compression = (MobipocketCompression)Enum.ToObject(typeof(MobipocketCompression), reader.ReadUInt16(Endian.BigEndian));

                        //usnused zeroes
                        reader.BaseStream.Seek(2, SeekOrigin.Current);

                        //length of text
                        header.TotalTextLength = reader.ReadUInt32(Endian.BigEndian);

                        //count of dpb records that contain text
                        header.TextRecordCount = reader.ReadUInt16(Endian.BigEndian);

                        //maximum record size, always 4096
                        header.MaxRecordSize = reader.ReadUInt16(Endian.BigEndian);

                        //read mobipocket encryption
                        header.Encryption = (MobipocketEncryption)Enum.ToObject(typeof(MobipocketEncryption), reader.ReadUInt16(Endian.BigEndian));

                        //skip two zeroes
                        reader.BaseStream.Seek(2, SeekOrigin.Current);

                        //palmdoc header end

                        //mobi header start

                        //read identifier "MOBI"
                        var identifier = reader.ReadUInt32(Endian.BigEndian);
                        if (MobiIdentifier != identifier)
                        {
                            throw new Exception("unsupported identifier: " + identifier);
                        }

                        //read byte length of header
                        var length = reader.ReadUInt32(Endian.BigEndian);

                        //read the type of document
                        header.Type = (MobipocketType)Enum.ToObject(typeof(MobipocketType), reader.ReadUInt32(Endian.BigEndian));

                        //read encoding of document
                        header.Encoding = (MobipocketEncoding)Enum.ToObject(typeof(MobipocketEncoding), reader.ReadUInt32(Endian.BigEndian));

                        //read uid
                        header.UniqueId = reader.ReadUInt32(Endian.BigEndian);

                        //read version
                        header.Version = reader.ReadUInt32(Endian.BigEndian);

                        //40 0xff bytes
                        reader.BaseStream.Seek(40, SeekOrigin.Current);

                        //first no book record
                        header.FirstNonTextRecord = reader.ReadUInt32(Endian.BigEndian);

                        //offset in header of full name data
                        header._fullNameOffset = reader.ReadUInt32(Endian.BigEndian);

                        //length of full name data
                        header._fullNameLength = reader.ReadUInt32(Endian.BigEndian);

                        //locale of mobipocket file
                        header.Locale = reader.ReadUInt32(Endian.BigEndian);

                        //dictionary input language
                        header.DictionaryInfo.InputLanguage = reader.ReadUInt32(Endian.BigEndian);

                        //dictionary output language
                        header.DictionaryInfo.OutputLanguage = reader.ReadUInt32(Endian.BigEndian);

                        //minimal mobi pocket reader version
                        header.MinReaderVersion = reader.ReadUInt32(Endian.BigEndian);

                        //index of first image in pdb database
                        header.FirtImageRecord = reader.ReadUInt32(Endian.BigEndian);

                        //offset of huffman data
                        header.HuffmanInfo.RecordOffset = reader.ReadUInt32(Endian.BigEndian);

                        //count of huffman data
                        header.HuffmanInfo.RecordCount = reader.ReadUInt32(Endian.BigEndian);

                        //Skip 8 bytes, often zeroes
                        reader.BaseStream.Seek(8, SeekOrigin.Current);

                        //Check if we have exth record
                        var exthBitField = reader.ReadUInt32(Endian.BigEndian);
                        header._exthEnabled = ((exthBitField & 0x40) == 0x40);

                        if (length > 0x80)
                        {
                            byte[] data = new byte[32];

                            reader.Read(data, 0, 32);

                            // DRM Offset
                            var drmOffset = reader.ReadUInt32(Endian.BigEndian);
                            //	DRM Count
                            var drmCount = reader.ReadUInt32(Endian.BigEndian);
                            //	DRM Size
                            var drmSize = reader.ReadUInt32(Endian.BigEndian);
                            //	DRM Flags
                            var drmFlags = reader.ReadUInt32(Endian.BigEndian);

                            header.Drm = new MobipocketDrm(drmOffset, drmCount, drmSize, drmFlags);
                            header.Drm.Parse(bytes);
                        }

                        //read trailing byte flags if present
                        if (length > 228)
                        {
                            reader.BaseStream.Seek(0xf2, SeekOrigin.Begin);

                            header.TrailingEntries = reader.ReadUInt16(Endian.BigEndian);
                        }

                        //read full name
                        reader.BaseStream.Seek(header._fullNameOffset, SeekOrigin.Begin);

                        var nameBuffer = new byte[header._fullNameLength];
                        checked { reader.Read(nameBuffer, 0, (int)header._fullNameLength); }
                        header.FullName = header.GetString(nameBuffer);


                        //mobi header end

                        if (header._exthEnabled)
                        {
                            //exth header start
                            //header.Data, length + 16
                            checked
                            {
                                Exth = ExthHeader.FromBinary(new ArraySegment <byte>(bytes.Array,
                                                                                     bytes.Offset + (int)length + 16,
                                                                                     bytes.Count - (int)length - 16));
                            }
                            //exth headet end
                        }
                    }

                return(header);
            }
            catch (Exception e)
            {
                throw new Exception("cannot parse mobipocket header from binary", e);
            }
        }