public MobiFile(PalmFile pf) : base() { this.m_AppInfoID = pf.AppInfoID; this.m_Attributes = pf.m_Attributes; this.m_Compression = pf.Compression; this.m_CreationDate = pf.CreationDate; this.m_Creator = pf.Creator; this.m_CurrentPosition = pf.CurrentPosition; this.m_FileName = pf.FileName; this.m_LastBackupDate = pf.LastBackupDate; this.m_ModificationDate = pf.ModificationDate; this.m_ModificationNumber = pf.ModificationNumber; this.m_Name = pf.Name; this.m_NextRecordListID = pf.NextRecordListID; this.m_NumberOfRecords = pf.NumberOfRecords; this.m_RecordList = pf.RecordList; this.m_SortInfoID = pf.SortInfoID; this.m_TextLength = pf.TextLength; this.m_TextRecordCount = pf.TextRecordCount; this.m_TextRecordSize = pf.TextRecordSize; this.m_Type = pf.Type; this.m_UniqueIDSeed = pf.UniqueIDSeed; this.m_Version = pf.Version; this.m_RecordInfoList = pf.m_RecordInfoList; }
public new static MobiFile LoadFile(String fileName) { MobiFile retval = new MobiFile(PalmFile.LoadFile(fileName)); List <Byte> empty2 = new List <Byte> (); List <Byte> temp = new List <Byte> (); empty2.Add(0); empty2.Add(0); List <Byte> headerdata = new List <Byte> (); headerdata.AddRange(retval.m_RecordList [0].Data); temp.AddRange(empty2); temp.AddRange(headerdata.GetRange(12, 2)); retval.m_EncryptionType = BytesToUint(temp.ToArray()); if (retval.Compression == 2) { StringBuilder sb = new StringBuilder(); Int32 pos = 0; Int32 a = 1; List <Byte> datatemp = null; while (a < retval.m_TextRecordCount + 1) { List <Byte> blockbuilder = new List <Byte> (); datatemp = new List <byte> (retval.m_RecordList [a++].Data); datatemp.Add(0); pos = 0; List <Byte> temps = new List <Byte> (); while (pos < datatemp.Count && blockbuilder.Count < 4096) { Byte ab = (byte)(datatemp[pos++]); if (ab == 0x00 || (ab > 0x08 && ab <= 0x7f)) { blockbuilder.Add(ab); //blockbuilder.Add (0); } else if (ab > 0x00 && ab <= 0x08) { temps.Clear(); temps.Add(0); temps.Add(0); temps.Add(0); temps.Add(ab); UInt32 value = BytesToUint(temps.ToArray()); for (uint i = 0; i < value; i++) { blockbuilder.Add((byte)(datatemp [pos++])); // blockbuilder.Add (0); } } else if (ab > 0x7f && ab <= 0xbf) { temps.Clear(); temps.Add(0); temps.Add(0); Byte bb = (Byte)((ab & 63)); // do this to drop the first 2 bits temps.Add(bb); if (pos < datatemp.Count) { temps.Add((byte)(datatemp [pos++])); } else { temps.Add(0); } UInt32 b = BytesToUint(temps.ToArray()); UInt32 dist = (b >> 3) * 1; UInt32 len = ((b << 29) >> 29); Int32 uncompressedpos = blockbuilder.Count - ((Int32)dist); for (int i = 0; i < (len + 3) * 1; i++) { try { blockbuilder.Add(blockbuilder[uncompressedpos + i]); } catch (Exception) { } } } else if (ab > 0xbf && ab <= 0xff) { blockbuilder.Add(32); //blockbuilder.Add (0); blockbuilder.Add((byte)(ab ^ 0x80)); //blockbuilder.Add (0); } } sb.Append(Encoding.UTF8.GetString(blockbuilder.ToArray())); } retval.m_BookText = sb.ToString(); } else if (retval.Compression == 17480) { temp.Clear(); temp.AddRange(headerdata.GetRange(112, 4)); retval.m_HuffOffset = BytesToUint(temp.ToArray()); temp.Clear(); temp.AddRange(headerdata.GetRange(116, 4)); retval.m_HuffCount = BytesToUint(temp.ToArray()); if (headerdata.Count >= 244) { temp.Clear(); temp.AddRange(headerdata.GetRange(240, 4)); retval.m_Extra_flags = BytesToUint(temp.ToArray()); } UInt32 off1; UInt32 off2; UInt32 entrybits; List <Byte> huffdata = new List <Byte> (); List <Byte> cdicdata = new List <Byte> (); huffdata.AddRange(retval.m_RecordList [retval.m_HuffOffset].Data); cdicdata.AddRange(retval.m_RecordList [retval.m_HuffOffset + 1].Data); temp.Clear(); temp.AddRange(huffdata.GetRange(16, 4)); off1 = BytesToUint(temp.ToArray()); temp.Clear(); temp.AddRange(huffdata.GetRange(20, 4)); off2 = BytesToUint(temp.ToArray()); temp.Clear(); temp.AddRange(cdicdata.GetRange(12, 4)); entrybits = BytesToUint(temp.ToArray()); List <UInt32> huffdict1 = new List <UInt32> (); List <UInt32> huffdict2 = new List <UInt32> (); List <List <Byte> > huffdicts = new List <List <Byte> > (); for (int i = 0; i < 256; i++) { temp.Clear(); temp.AddRange(huffdata.GetRange((int)(off1 + (i * 4)), 4)); huffdict1.Add(BitConverter.ToUInt32(temp.ToArray(), 0)); } for (int i = 0; i < 64; i++) { temp.Clear(); temp.AddRange(huffdata.GetRange((int)(off2 + (i * 4)), 4)); huffdict2.Add(BitConverter.ToUInt32(temp.ToArray(), 0)); } for (int i = 1; i < retval.m_HuffCount; i++) { huffdicts.Add(new List <byte> (retval.m_RecordList [retval.m_HuffOffset + i].Data)); } StringBuilder sb = new StringBuilder(); for (int i = 0; i < retval.m_TextRecordCount; i++) { // Remove Trailing Entries List <Byte> datatemp = new List <byte> (retval.m_RecordList [1 + i].Data); Int32 size = getSizeOfTrailingDataEntries(datatemp.ToArray(), datatemp.Count, retval.m_Extra_flags); sb.Append(unpack(new BitReader(datatemp.GetRange(0, datatemp.Count - size).ToArray()), huffdict1.ToArray(), huffdict2.ToArray(), huffdicts, (int)((long)entrybits))); } retval.m_BookText = sb.ToString(); } else { throw new Exception("Compression format is unsupported"); } return(retval); }
public static PalmFile LoadFile(String fileName) { PalmFile retval = new PalmFile(); retval.m_FileName = fileName; FileStream fs = null; StreamReader sr = null; UInt32 seconds = 0; DateTime startdate = new DateTime(1904, 1, 1); //startdate = new DateTime(1970, 1, 1); try { fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); sr = new StreamReader(fs); Char[] buffer = new char[32]; sr.Read(buffer, 0, 32); fs.Seek(32, SeekOrigin.Begin); retval.m_Name = new String(buffer); Byte[] bytebuffer = new Byte[4]; fs.Read(bytebuffer, 2, 2); retval.m_Attributes = BytesToUint(bytebuffer); bytebuffer = new Byte[4]; fs.Read(bytebuffer, 2, 2); retval.m_Version = BytesToUint(bytebuffer); bytebuffer = new Byte[4]; fs.Read(bytebuffer, 0, 4); seconds = BytesToUint(bytebuffer); TimeSpan ts = new TimeSpan(0, (int)(seconds / 60), 0); retval.m_CreationDate = startdate + ts; fs.Read(bytebuffer, 0, 4); seconds = BytesToUint(bytebuffer); ts = new TimeSpan(0, (int)(seconds / 60), 0); retval.m_ModificationDate = startdate + ts; fs.Read(bytebuffer, 0, 4); seconds = BytesToUint(bytebuffer); ts = new TimeSpan(0, (int)(seconds / 60), 0); retval.m_LastBackupDate = startdate + ts; fs.Read(bytebuffer, 0, 4); retval.m_ModificationNumber = BytesToUint(bytebuffer); fs.Read(bytebuffer, 0, 4); retval.m_AppInfoID = BytesToUint(bytebuffer); fs.Read(bytebuffer, 0, 4); retval.m_SortInfoID = BytesToUint(bytebuffer); buffer = new char[4]; sr.DiscardBufferedData(); sr.Read(buffer, 0, 4); retval.m_Type = new String(buffer); sr.Read(buffer, 0, 4); retval.m_Creator = new String(buffer); fs.Seek(68, SeekOrigin.Begin); fs.Read(bytebuffer, 0, 4); retval.m_UniqueIDSeed = BytesToUint(bytebuffer); fs.Read(bytebuffer, 0, 4); retval.m_NextRecordListID = BytesToUint(bytebuffer); bytebuffer = new Byte[4]; fs.Read(bytebuffer, 2, 2); // Load RecordInfo retval.m_NumberOfRecords = BytesToUint(bytebuffer); retval.m_RecordInfoList = new PalmRecordInfo[retval.m_NumberOfRecords]; retval.m_RecordList = new PalmRecord[retval.m_NumberOfRecords]; for (int i = 0; i < retval.m_NumberOfRecords; i++) { fs.Read(bytebuffer, 0, 4); retval.m_RecordInfoList [i].DataOffset = BytesToUint(bytebuffer); bytebuffer = new Byte[4]; fs.Read(bytebuffer, 3, 1); retval.m_RecordInfoList [i].Attributes = BytesToUint(bytebuffer); bytebuffer = new Byte[4]; fs.Read(bytebuffer, 1, 3); retval.m_RecordInfoList [i].UniqueID = BytesToUint(bytebuffer); } //Load Records UInt32 StartOffset; UInt32 EndOffset; Int32 RecordLength; for (int i = 0; i < retval.m_NumberOfRecords - 1; i++) { StartOffset = retval.m_RecordInfoList [i].DataOffset; EndOffset = retval.m_RecordInfoList [i + 1].DataOffset; RecordLength = ((Int32)((long)(EndOffset - StartOffset))); fs.Seek(StartOffset, SeekOrigin.Begin); retval.m_RecordList [i].Data = new Byte[RecordLength]; fs.Read(retval.m_RecordList [i].Data, 0, RecordLength); } StartOffset = retval.m_RecordInfoList [retval.m_NumberOfRecords - 1].DataOffset; RecordLength = (int)(fs.Length - ((Int32)((long)StartOffset))); fs.Seek(StartOffset, SeekOrigin.Begin); retval.m_RecordList [retval.m_NumberOfRecords - 1].Data = new Byte[RecordLength]; fs.Read(retval.m_RecordList [retval.m_NumberOfRecords - 1].Data, 0, RecordLength); // LoadHeader List <Byte> empty2 = new List <Byte> (); List <Byte> temp = new List <Byte> (); empty2.Add(0); empty2.Add(0); List <Byte> headerdata = new List <Byte> (); headerdata.AddRange(retval.m_RecordList [0].Data); temp.AddRange(empty2); temp.AddRange(headerdata.GetRange(0, 2)); retval.m_Compression = BytesToUint(temp.ToArray()); temp.Clear(); temp.AddRange(headerdata.GetRange(4, 4)); retval.m_TextLength = BytesToUint(temp.ToArray()); temp.Clear(); temp.AddRange(empty2); temp.AddRange(headerdata.GetRange(8, 2)); retval.m_TextRecordCount = BytesToUint(temp.ToArray()); temp.Clear(); temp.AddRange(empty2); temp.AddRange(headerdata.GetRange(10, 2)); retval.m_TextRecordSize = BytesToUint(temp.ToArray()); temp.Clear(); temp.AddRange(headerdata.GetRange(12, 4)); retval.m_CurrentPosition = BytesToUint(temp.ToArray()); ; } finally { if (sr != null) { sr.Close(); sr.Dispose(); } if (fs != null) { fs.Close(); fs.Dispose(); } } return(retval); }