public _7z_parser(string filepath) { //opens xxx.7z passed in parameter Console.WriteLine("[7z-parser] specified file: " + filepath); archive_file_reader = new BinaryReader(File.Open(filepath, FileMode.Open)); Console.WriteLine("[7z-parser] reader opened"); //pretty much self-explanatory, covers "SignatureHeader" section in 7zFormat.txt (line 171~188) read_signature_and_archive_version(); read_StartHeader(); //Move position of archive_file_reader //will be a problem when _NextHeaderOffset is bigger than "long.MaxValue - 32" but.......... it requires a sinle 1EB .7z file if I do math correctly //So... this program will break if you have a 1EB .7z file and I don't want to fix this in... foreseeable future archive_file_reader.BaseStream.Position += (long)_NextHeaderOffset; Property_IDs flag = (Property_IDs)archive_file_reader.ReadByte(); if (flag == Property_IDs.kHeader) { read_Header(); } else if (flag == Property_IDs.kEncodedHeader) { _Encoded_Header = read_Streams_info(); } else { throw new ParseError("Expected kHeader or kEncodedHeader, but got 0x" + Util.Byte_to_hex_string((byte)flag) + "\n" + "Stream position = " + archive_file_reader.BaseStream.Position); } }
/// <summary> /// covers "Header" section in 7zFormat.txt (line 435~457) /// </summary> private void read_Header() { Console.WriteLine("[7z-parser] read Header"); Property_IDs flag = (Property_IDs)archive_file_reader.ReadByte(); //optional ArchiveProperties if (flag == Property_IDs.kArchiveProperties) { _Archive_Properties = read_Archive_Properties(); flag = (Property_IDs)archive_file_reader.ReadByte(); } //optional AdditionalStreamsInfo if (flag == Property_IDs.kAdditionalStreamsInfo) { _Additional_Streams_Info = read_Streams_info(); flag = (Property_IDs)archive_file_reader.ReadByte(); } //optional MainStreamsInfo if (flag == Property_IDs.kMainStreamsInfo) { _Main_Streams_Info = read_Streams_info(); flag = (Property_IDs)archive_file_reader.ReadByte(); } //Check kEnd assert(flag == Property_IDs.kEnd, "Expected kEnd (0x00), but got 0x" + Util.Byte_to_hex_string((byte)flag) + "\n" + "Stream position (decimal) = " + archive_file_reader.BaseStream.Position); Console.WriteLine("[7z-parser] read Header complete"); }
/// <summary> /// covers "PackInfo" section in 7zFormat.txt (line 218~234) /// </summary> private PackInfo read_Pack_Info() { Console.WriteLine("[7z-parser] read Pack Info"); PackInfo pack_info = new PackInfo(); pack_info.PackPos = read_7z_UInt64(); Console.WriteLine("PackPos = " + pack_info.PackPos); pack_info.NumPackStreams = read_7z_UInt64(); Console.WriteLine("NumPackStreams = " + pack_info.NumPackStreams); Property_IDs flag = (Property_IDs)archive_file_reader.ReadByte(); //handles optional PackSizes if (flag == Property_IDs.kSize) { Console.WriteLine("read KSize"); pack_info.PackSizes = new ulong[pack_info.NumPackStreams]; for (ulong i = 0; i < pack_info.NumPackStreams; i++) { pack_info.PackSizes[i] = read_7z_UInt64(); Console.WriteLine("PackSizes[" + i + "] = " + pack_info.PackSizes[i]); } flag = (Property_IDs)archive_file_reader.ReadByte(); } else { pack_info.PackSizes = null; } //handles optional PackStreamDigests if (flag == Property_IDs.kCRC) { pack_info.PackStreamDigests = new string[pack_info.NumPackStreams]; byte[] CRC_in_bytes; for (ulong i = 0; i < pack_info.NumPackStreams; i++) { CRC_in_bytes = archive_file_reader.ReadBytes(4); Array.Reverse(CRC_in_bytes); pack_info.PackStreamDigests[i] = Util.Bytes_to_CRC_string(CRC_in_bytes); } flag = (Property_IDs)archive_file_reader.ReadByte(); } else { pack_info.PackSizes = null; } //Check kEnd assert(flag == Property_IDs.kEnd, "Expected kEnd (0x00), but got 0x" + Util.Byte_to_hex_string((byte)flag) + "\n" + "Stream position (decimal) = " + archive_file_reader.BaseStream.Position); Console.WriteLine("[7z-parser] read Pack Info complete"); return(pack_info); }
/// <summary> /// covers "Streams Info" section in 7zFormat.txt (line 341~358) /// </summary> private StreamsInfo read_Streams_info() { Console.WriteLine("[7z-parser] read Streams Info"); StreamsInfo streams_info = new StreamsInfo(); Property_IDs flag = (Property_IDs)archive_file_reader.ReadByte(); //handles optional PackInfo if (flag == Property_IDs.kPackInfo) { streams_info.packInfo = read_Pack_Info(); flag = (Property_IDs)archive_file_reader.ReadByte(); } else { streams_info.packInfo = null; } //handles optional CodersInfo if (flag == Property_IDs.kUnPackInfo) { streams_info.codersInfo = read_Coders_Info(); flag = (Property_IDs)archive_file_reader.ReadByte(); } else { streams_info.codersInfo = null; } //handles optional PackInfo if (flag == Property_IDs.kSubStreamsInfo) { streams_info.subStreamsInfo = read_SubStreams_info(); flag = (Property_IDs)archive_file_reader.ReadByte(); } else { streams_info.subStreamsInfo = null; } //Check kEnd assert(flag == Property_IDs.kEnd, "Expected kEnd (0x00), but got 0x" + Util.Byte_to_hex_string((byte)flag) + "\n" + "Stream position (decimal) = " + archive_file_reader.BaseStream.Position); Console.WriteLine("[7z-parser] read Header complete"); return(streams_info); }
/// <summary> /// covers "ArchiveProperties" section in 7zFormat.txt (line 194~204) /// </summary> private List <ArchiveProperty> read_Archive_Properties() { List <ArchiveProperty> list = new List <ArchiveProperty>(); while (true) { Property_IDs PropertyType = (Property_IDs)archive_file_reader.ReadByte(); if (PropertyType == Property_IDs.kEnd) { return(list); } ArchiveProperty entry = new ArchiveProperty(); entry.PropertyType = PropertyType; entry.PropertyData = archive_file_reader.ReadBytes((int)read_7z_UInt64()); //might crash with big PropertySize Array.Reverse(entry.PropertyData); list.Add(entry); //debug message Console.WriteLine("[7z-parser] archive property type = " + Util.Byte_to_hex_string((byte)entry.PropertyType) + ", PropertySize = " + entry.PropertyData.Length + ", PropertyData = " + Util.Bytes_to_hex_string(entry.PropertyData)); } }
private SubStreamsInfo read_SubStreams_info() { Console.WriteLine("[7z-parser] read Sub streams info"); Console.WriteLine("position = 0x" + archive_file_reader.BaseStream.Position.ToString("X")); SubStreamsInfo sub_streams_info = new SubStreamsInfo(); Property_IDs flag = (Property_IDs)archive_file_reader.ReadByte(); //handles optional NumUnPackStream if (flag == Property_IDs.kNumUnPackStream) { sub_streams_info.NumUnPackStreamsInFolders = new ulong[_Additional_Streams_Info.codersInfo.NumFolders]; for (ulong i = 0; i < _Additional_Streams_Info.codersInfo.NumFolders; i++) { sub_streams_info.NumUnPackStreamsInFolders[i] = read_7z_UInt64(); } flag = (Property_IDs)archive_file_reader.ReadByte(); } if (flag == Property_IDs.kSize) { } throw new ParseError("read_SubStreams_info() is not yet implemented"); }
/// <summary> /// covers "Coders Info" section in 7zFormat.txt (line 281~312) /// </summary> private CodersInfo read_Coders_Info() { Console.WriteLine("[7z-parser] read Coders Info"); CodersInfo coders_info = new CodersInfo(); Property_IDs flag = (Property_IDs)archive_file_reader.ReadByte(); assert(flag == Property_IDs.kFolder, "Expected kFolder (0x0B), but got 0x" + Util.Byte_to_hex_string((byte)flag) + "\n" + "Stream position (decimal) = " + archive_file_reader.BaseStream.Position); //read NumFolders (line 288 in 7zFormat.txt) coders_info.NumFolders = read_7z_UInt64(); //read External (line 289~296 in 7zFormat.txt) coders_info.External = archive_file_reader.ReadBoolean(); Console.WriteLine("External = " + coders_info.External.ToString()); if (!coders_info.External) { coders_info.Folders = new Folder[coders_info.NumFolders]; Console.WriteLine("position = 0x" + archive_file_reader.BaseStream.Position.ToString("X")); for (ulong i = 0; i < coders_info.NumFolders; i++) { coders_info.Folders[i] = read_Folder(); } Console.WriteLine("position = 0x" + archive_file_reader.BaseStream.Position.ToString("X")); } else { coders_info.Folders = new Folder[0]; coders_info.DataStreamIndex = read_7z_UInt64(); } //kCodersUnPackSize (line 299 in 7zFormat.txt) flag = (Property_IDs)archive_file_reader.ReadByte(); assert(flag == Property_IDs.kCodersUnPackSize, "Expected kCodersUnPackSize (0x0C), but got 0x" + Util.Byte_to_hex_string((byte)flag) + "\n" + "Stream position (decimal) = " + archive_file_reader.BaseStream.Position); //read UnPackSize (line 300~302 in 7zFormat.txt) coders_info.UnPackSizes = new List <ulong>(); foreach (Folder f in coders_info.Folders) { for (ulong i = 0; i < f.NumOutStreams; i++) { coders_info.UnPackSizes.Add(read_7z_UInt64()); Console.WriteLine("UnPackSizes: " + coders_info.UnPackSizes.Last()); } } //kCRC (line 306 in 7zFormat.txt) flag = (Property_IDs)archive_file_reader.ReadByte(); if (flag == Property_IDs.kCRC) { coders_info.UnPackDigests = new string[coders_info.NumFolders]; byte[] CRCbytes; for (ulong i = 0; i < coders_info.NumFolders; i++) { CRCbytes = archive_file_reader.ReadBytes(4); Array.Reverse(CRCbytes); coders_info.UnPackDigests[i] = Util.Bytes_to_CRC_string(CRCbytes); } flag = (Property_IDs)archive_file_reader.ReadByte(); } else { coders_info.UnPackDigests = null; } //Check kEnd assert(flag == Property_IDs.kEnd, "Expected kEnd (0x00), but got 0x" + Util.Byte_to_hex_string((byte)flag) + "\n" + "Stream position (decimal) = " + archive_file_reader.BaseStream.Position); Console.WriteLine("[7z-parser] read Coders Info complete"); return(coders_info); }