Пример #1
0
        public static IEnumerable <WZProperty> DirectoryChildren(WZProperty self)
        {
            using (WZReader reader = self.FileContainer.GetContentReader(null, self))
            {
                reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin);
                int          count    = reader.ReadWZInt();
                WZProperty[] children = new WZProperty[count];
                string       name     = null;
                for (int i = 0; i < count; ++i)
                {
                    byte type = reader.ReadByte();
                    switch (type)
                    {
                    case 1:
                        reader.ReadBytes(10);
                        continue;

                    case 2:
                        int dedupedAt = (int)(reader.ReadInt32() + reader.ContentsStart);
                        reader.PeekFor(() => {
                            reader.BaseStream.Position = dedupedAt;
                            type = reader.ReadByte();
                            name = reader.ReadWZString(false, self.Encrypted | self.Container.Encrypted);
                        });
                        break;

                    case 3:
                    case 4:
                        name = reader.ReadWZString(false, self.Encrypted | self.Container.Encrypted);
                        break;

                    default:
                        throw new Exception("Unknown child type");
                    }
                    if (name == null)
                    {
                        throw new InvalidOperationException("Found a property without a name, this shouldn't be possible.");
                    }

                    uint       size          = (uint)reader.ReadWZInt();
                    int        checksum      = reader.ReadWZInt();
                    uint       offset        = reader.ReadWZOffset();
                    WZProperty childProperty = new WZProperty(
                        name,
                        self != null ? Path.Combine(self.Path, name) : name,
                        reader.Package,
                        type == 3 ? PropertyType.Directory : type == 4 ? PropertyType.Image : throw new InvalidOperationException("Not sure what this is, but I don't handle it"),
                        self,
                        size,
                        checksum,
                        offset
                        );
                    // These can be lazy loaded
                    yield return(Resolve(reader.Package, childProperty));
                }
            }
        }
Пример #2
0
        public void Image(BinaryWriter writer, WZProperty self)
        {
            if (!imgLocations.ContainsKey(self))
            {
                imgLocations.Add(self, (uint)writer.BaseStream.Position);
            }
            else
            {
                imgLocations[self] = (uint)writer.BaseStream.Position; // Pretty sure this should never happen
            }
            using (WZReader reader = self.FileContainer.GetContentReader(null, self))
            {
                reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin);
                writer.Write(reader.ReadBytes((int)self.Size));
            }

            //writer.Write((byte)0x73); // Regular img
            //GetWZStringBytes(writer, "Property");
            //writer.Write((short)0);
            //PropertyList(writer, self.Children);
        }
Пример #3
0
        public static WZProperty Audio(WZReader reader, WZProperty self)
        {
            byte unk      = reader.ReadByte();
            int  length   = reader.ReadWZInt();
            int  duration = reader.ReadWZInt();

            WZProperty result = new WZPropertyWeak <byte[]>(
                () => {
                Package.Logging($"{self.Path} (Audio) - {unk}");
                using (reader = self.FileContainer.GetContentReader(null, self))
                {
                    reader.BaseStream.Seek(self.Offset + 1, SeekOrigin.Begin);
                    if (length > sbyte.MaxValue || length <= sbyte.MinValue)
                    {
                        reader.BaseStream.Seek(5, SeekOrigin.Current);
                    }
                    else
                    {
                        reader.BaseStream.Seek(1, SeekOrigin.Current);
                    }
                    if (duration > sbyte.MaxValue || duration <= sbyte.MinValue)
                    {
                        reader.BaseStream.Seek(5, SeekOrigin.Current);
                    }
                    else
                    {
                        reader.BaseStream.Seek(1, SeekOrigin.Current);
                    }
                    return(reader.ReadBytes(length));
                }
            }, self
                );

            result.Size = (uint)length;
            result.Meta.Add("duration", duration);
            result.Meta.Add("unk", unk);

            return(result);
        }
Пример #4
0
        public static byte[] ResolveHash(WZProperty prop)
        {
            using (WZReader reader = prop.FileContainer.GetContentReader(null, prop))
                using (SHA1 sha = SHA1.Create())
                {
                    reader.BaseStream.Position = prop.Offset;
                    switch (prop.Type)
                    {
                    case PropertyType.Image:
                        reader.BaseStream.Position = prop.ContainerStartLocation;
                        byte imgType = reader.ReadByte();
                        if (imgType == 1)
                        {
                            byte unk = reader.ReadByte();
                            return(reader.GetLuaScriptBytes().ToArray());
                        }
                        else
                        {
                            return(new byte[0]);
                        }

                    case PropertyType.Directory: return(new byte[0]);

                    case PropertyType.SubProperty: return(new byte[0]);

                    case PropertyType.Convex: return(new byte[0]);

                    case PropertyType.Vector2: return(sha.ComputeHash(reader.GetWZIntBytes().Concat(reader.GetWZIntBytes()).ToArray()));

                    case PropertyType.UOL: return(sha.ComputeHash(reader.GetWZStringBlockBytes(prop.Encrypted | prop.Container.Encrypted)));

                    case PropertyType.Audio:
                        using (Stream sub = new SubStream(reader.BaseStream, (int)reader.BaseStream.Position, prop.Size))
                            return(sha.ComputeHash(sub));

                    case PropertyType.Canvas:
                        reader.BaseStream.Seek(1, SeekOrigin.Current);
                        byte[][] childHashes;
                        if (reader.ReadByte() == 1)
                        {
                            reader.BaseStream.Seek(2, SeekOrigin.Current);
                            childHashes = PropertyList(reader, prop).ToArray().Select(c => ResolveHash(c)).ToArray();
                        }
                        else
                        {
                            childHashes = new byte[0][];
                        }
                        int  width   = reader.ReadWZInt(); // width
                        int  height  = reader.ReadWZInt(); // height
                        int  format1 = reader.ReadWZInt(); // format 1
                        byte format2 = reader.ReadByte();  // format 2
                        reader.BaseStream.Seek(4, SeekOrigin.Current);
                        uint   blockLen  = (uint)reader.ReadInt32();
                        ushort header    = reader.PeekFor(() => reader.ReadUInt16());
                        byte[] imageHash = new byte[0];
                        using (Stream sub = new SubStream(reader.BaseStream, reader.BaseStream.Position, blockLen - 1))
                            imageHash = sha.ComputeHash(sub);

                        if (childHashes.Length > 0)
                        {
                            return(calcAggregateHash(sha, childHashes.Prepend(imageHash).ToArray()));
                        }
                        else
                        {
                            return(imageHash);
                        }

                    default:
                        byte[] nameHash = sha.ComputeHash(reader.GetWZStringBlockBytes(prop.Encrypted | prop.Container.Encrypted));
                        byte   type     = reader.ReadByte();
                        switch (type)
                        {
                        case 0: return(nameHash);

                        case 0x10: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(1))));

                        case 0x11: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(1))));

                        case 0x0B:
                        case 2:
                        case 0x12: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(2))));

                        case 3: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZIntBytes())));

                        case 19: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZIntBytes())));

                        case 4: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZSingleBytes())));

                        case 5: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(8))));

                        case 8: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZStringBlockBytes(prop.Container.Encrypted))));

                        case 9: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(reader.ReadInt32()))));

                        case 20: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZLongBytes())));

                        case 21: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZLongBytes())));

                        default:
                            System.Diagnostics.Debugger.Break();
                            Console.WriteLine("Wow");
                            if (type > 100)
                            {
                                throw new Exception("Unknown property type at ParsePropertyList");
                            }
                            else
                            {
                                return(new byte[0]);
                            }
                        }
                    }
                }
        }