示例#1
0
 private void DecryptEntry(byte[] data, uint key1, uint key2, DpkEntry entry)
 {
     for (uint i = 0; i < data.Length; ++i)
     {
         data[i] ^= (byte)(key1 + (key1 >> 8));
         data[i] -= (byte)entry.Hash;
         key1    += key2;
     }
 }
示例#2
0
        public override ArcFile TryOpen(ArcView file)
        {
            var header = new byte[8];

            if (8 != file.View.Read(8, header, 0, 8))
            {
                return(null);
            }
            byte last = header[7];

            for (int i = 0; i < 8; i++)
            {
                header[i] ^= (byte)(i - 8);
            }
            int data_offset = LittleEndian.ToInt32(header, 0);

            if (data_offset <= 16 || data_offset >= file.MaxOffset)
            {
                return(null);
            }
            int index_length = data_offset - 16;
            var index        = new byte[index_length];

            if (index_length != file.View.Read(16, index, 0, (uint)index_length))
            {
                return(null);
            }
            DecryptIndex(index, 16, index_length, last);
            int count = LittleEndian.ToInt32(index, 0);

            if (count <= 0 || count > 0xfffff)
            {
                return(null);
            }

            var options     = Query <DpkOptions> (arcStrings.ArcEncryptedNotice);
            var name_bytes  = new byte[0x20];
            var dir         = new List <Entry> (count);
            int base_offset = 4 + count * 4;

            for (int i = 0; i < count; ++i)
            {
                var index_offset = base_offset + LittleEndian.ToInt32(index, 4 + i * 4);
                int name_begin   = index_offset + 0x0c;
                int name_end     = Array.IndexOf(index, (byte)0, name_begin);
                if (-1 == name_end)
                {
                    name_end = index.Length;
                }
                if (name_end == name_begin)
                {
                    continue;
                }
                if ('z' == index[name_end - 1])
                {
                    --name_end; // strip 'z' from file extensions
                }
                int name_length = name_end - name_begin;
                var name        = Encodings.cp932.GetString(index, name_begin, name_length);
                if (name_length > name_bytes.Length)
                {
                    name_bytes = new byte[name_length];
                }
                // shift-jis characters sequence may contain '\\' that is not a path delimiter
                string name_base = Path.GetFileName(name);
                name_length = Encodings.cp932.GetBytes(name_base, 0, name_base.Length, name_bytes, 0);

                uint size  = LittleEndian.ToUInt32(index, index_offset + 4);
                var  entry = new DpkEntry
                {
                    Name   = name,
                    Type   = FormatCatalog.Instance.GetTypeFromName(name),
                    Hash   = GetNameHash(name_bytes, 0, name_length, options.Key1, options.Key2, size),
                    Offset = data_offset + LittleEndian.ToUInt32(index, index_offset),
                    Size   = size,
                };
                if (!entry.CheckPlacement(file.MaxOffset))
                {
                    return(null);
                }
                dir.Add(entry);
            }
            if (0 == dir.Count)
            {
                return(null);
            }
            return(new DpkArchive(file, this, dir, options));
        }