uint GetContentKey(ArcView file, List<Entry> dir, EncryptionScheme scheme) { if (null != scheme.ContentKey) return scheme.ContentKey.Value; if ("system.arc".Equals (Path.GetFileName (file.Name), StringComparison.InvariantCultureIgnoreCase)) { return ReadSysenvSeed (file, dir, scheme.IndexKey); } else { var system_arc = VFS.CombinePath (VFS.GetDirectoryName (file.Name), "system.arc"); using (var arc = VFS.OpenView (system_arc)) { var header = arc.View.ReadBytes (0, 0x30); Decrypt (header, 0, scheme.IndexKey); using (var arc_file = ReadIndex (arc, header, scheme)) { return ReadSysenvSeed (arc, arc_file.Dir, scheme.IndexKey); } } } }
AzArchive ReadIndex(ArcView file, byte[] header, EncryptionScheme scheme) { int ext_count = LittleEndian.ToInt32 (header, 4); int count = LittleEndian.ToInt32 (header, 8); uint index_length = LittleEndian.ToUInt32 (header, 12); if (ext_count < 1 || ext_count > 8 || !IsSaneCount (count) || index_length >= file.MaxOffset) return null; var packed_index = file.View.ReadBytes (header.Length, index_length); if (packed_index.Length != index_length) return null; Decrypt (packed_index, header.Length, scheme.IndexKey); uint checksum = LittleEndian.ToUInt32 (packed_index, 0); if (checksum != Adler32.Compute (packed_index, 4, packed_index.Length-4)) { if (checksum != Crc32.Compute (packed_index, 4, packed_index.Length-4)) throw new InvalidFormatException ("Index checksum mismatch"); } using (var input = new MemoryStream (packed_index, 4, packed_index.Length-4)) { var dir = ParseIndex (input, count, header.Length + index_length, file.MaxOffset); if (null == dir) return null; uint content_key = GetContentKey (file, dir, scheme); return new AzArchive (file, this, dir, scheme.IndexKey, content_key); } }
public override ArcFile TryOpen(ArcView file) { byte[] header_encrypted = file.View.ReadBytes (0, 0x30); if (header_encrypted.Length < 0x30) return null; byte[] header = new byte[header_encrypted.Length]; if (CurrentScheme != null) { try { Buffer.BlockCopy (header_encrypted, 0, header, 0, header.Length); Decrypt (header, 0, CurrentScheme.IndexKey); if (Binary.AsciiEqual (header, 0, "ARC\0")) { var arc = ReadIndex (file, header, CurrentScheme); if (null != arc) return arc; } } catch { /* ignore parse errors */ } } foreach (var scheme in KnownSchemes.Values) { Buffer.BlockCopy (header_encrypted, 0, header, 0, header.Length); Decrypt (header, 0, scheme.IndexKey); if (Binary.AsciiEqual (header, 0, "ARC\0")) { var arc = ReadIndex (file, header, scheme); if (null != arc) CurrentScheme = new EncryptionScheme (arc.SysenvKey, arc.RegularKey); return arc; } } return null; }