/// <summary> /// Reads the specified file and shows it in an ASCII format. /// </summary> /// <param name="file">The file.</param> internal static void ShowAsAscii(FileInfo file) { Console.WriteLine("Converting to ASCII..."); var cachedFile = new CachedFileReader(file); // Dump 16 bytes per line var len = cachedFile.Length; for (var i = 0; i < len; i += 16) { var cnt = Math.Min(16, len - i); var line = new byte[cnt]; Array.Copy(cachedFile.Buffer, i, line, 0, cnt); // Write address + hex + ascii Console.Write("{0:X6} ", i); Console.Write(BitConverter.ToString(line)); Console.Write(" "); // Convert non-ascii characters to "." for (var j = 0; j < cnt; ++j) { if (line[j] < 0x20 || line[j] > 0x7f) { line[j] = (byte)'.'; } } Console.WriteLine(Encoding.ASCII.GetString(line)); } }
/// <summary> /// Parses the specified data. /// </summary> /// <param name="data">The data.</param> /// <returns></returns> internal static object Parse(byte[] data) { var reader = new CachedFileReader(data); var parser = new CachedFileParser(reader); parser.Parse(); return(parser.m_stream.Members.Select(member => member.ToObject()).ToList()); }
/// <summary> /// Initializes a new instance of the <see cref="CachedFileReader"/> class. /// </summary> /// <param name="source">The source.</param> /// <param name="length">The length.</param> internal CachedFileReader(CachedFileReader source, int length) { Buffer = new byte[length]; Array.Copy(source.Buffer, source.Position, Buffer, 0, length); Filename = source.Filename; Fullname = source.Fullname; SecurityCheck(); EndOfObjectsData = length - m_shareSkip; }
/// <summary> /// Parses the specified file. /// </summary> /// <param name="file">The file.</param> /// <returns></returns> internal static KeyValuePair <object, object> Parse(FileInfo file) { Console.WriteLine("Parsing..."); SType.Reset(); var cachedFile = new CachedFileReader(file); var parser = new CachedFileParser(cachedFile); parser.Parse(); return(!s_dumpStructure?parser.ToObjects() : new KeyValuePair <object, object>()); }
/// <summary> /// Parses a sub stream. /// </summary> /// <returns></returns> SType ParseSubStream() { SType subStream = new SStreamType(StreamType.SubStream); var length = m_reader.ReadLength(); if (s_dumpStructure) { var subReader = new CachedFileReader(m_reader, length); var subParser = new CachedFileParser(subReader); subParser.Parse(); subStream.AddMember(subParser.m_stream.Clone()); } if (s_cachedObject) { return(new SStringType(m_reader.ReadString(length))); } m_reader.Seek(length); return(subStream); }
/// <summary> /// Initializes a new instance of the <see cref="CachedFileParser"/> class. /// </summary> /// <param name="reader">The reader.</param> CachedFileParser(CachedFileReader reader) { m_reader = reader; m_stream = new SStreamType(StreamType.StreamStart); }
/// <summary> /// Parses a database row. /// </summary> /// <returns></returns> SType ParseDBRow() { var header = GetObject() as SObjectType; if (header == null) { throw new ParserException("DBRow header not found"); } if (!header.IsDBRowDescriptor) { throw new ParserException("Bad DBRow descriptor name"); } var fields = header.Members.First().Members.First( member => member is STupleType).Members.First().Members.Cast <STupleType>().ToList(); if (!fields.Any()) { return(new SNoneType()); } // Check for double marker in stream (usually found in a file with one DBRow) var length = m_reader.ReadLength(); if (m_reader.IsDoubleMarker(length)) { length = m_reader.ReadLength(); } var unpackedDataSize = GetUnpackedDataSize(fields); var compressedData = m_reader.ReadBytes(length); var uncompressedData = Rle_Unpack(compressedData, unpackedDataSize); var reader = new CachedFileReader(uncompressedData, false); // Find the maximum number of elements for each field member var maxElements = fields.Select(field => field.Members.Count).Concat(new[] { 0 }).Max(); // The size of SDict must be the ammount of entries stored, // multiplied by the max elements of each field member var dict = new SDictType((uint)(fields.Count() * maxElements)); var pass = 1; while (pass < 7) { // The pattern for what data to read on each pass is: // 1: 64 bit (Int64, Double) // 2: 32 bit (Int32, Single) // 3: 16 bit (Int16) // 4: 8 bit (Byte) // 5: 1 bit (Boolean) // 6: strings foreach (var field in fields) { var fieldName = field.Members.First(); var fieldType = (SLongType)field.Members.Last(); var dbType = (DbTypes)fieldType.Value; byte boolCount = 0; var boolBuffer = false; SType obj = null; switch (dbType) { case DbTypes.Short: case DbTypes.UShort: if (pass == 3) { obj = new SShortType(reader.ReadShort()); } break; case DbTypes.Int: case DbTypes.UInt: if (pass == 2) { obj = new SIntType(reader.ReadInt()); } break; case DbTypes.Float: if (pass == 2) { obj = new SDoubleType(reader.ReadFloat()); } break; case DbTypes.Double: if (pass == 1) { obj = new SDoubleType(reader.ReadDouble()); } break; case DbTypes.Currency: if (pass == 1) { obj = new SDoubleType(reader.ReadLong() / 10000.0); } break; case DbTypes.Long: case DbTypes.ULong: case DbTypes.Filetime: // Timestamp case DbTypes.DBTimestamp: if (pass == 1) { obj = new SLongType(reader.ReadLong()); } break; case DbTypes.Bool: if (pass == 5) { if (boolCount == 0) { boolBuffer = Convert.ToBoolean(reader.ReadByte()); boolCount++; } obj = boolBuffer && boolCount != 0 ? new SBooleanType(1) : new SBooleanType(0); } break; case DbTypes.Byte: case DbTypes.UByte: if (pass == 4) { obj = new SByteType(reader.ReadByte()); } break; case DbTypes.Bytes: // String types case DbTypes.String: case DbTypes.WideString: if (pass == 6) { obj = GetObject(); } break; default: throw new ParserException("Unhandled db column type: " + dbType); } if (obj == null) { continue; } dict.AddMember(obj); dict.AddMember(fieldName.Clone()); } pass++; } var parsedDBRow = new STupleType(2); parsedDBRow.AddMember(header); parsedDBRow.AddMember(dict); return(parsedDBRow); }