Пример #1
0
        private bool DepthFirstImageSearch(out long offset)
        {
            bool success = false;

            offset = -1;
            int count = _r.ReadWZInt();

            for (int i = 0; i < count; i++)
            {
                byte type = _r.ReadByte();
                Logging(type.ToString());
                switch (type)
                {
                case 1:
                    _r.BaseStream.Seek(10, SeekOrigin.Current);
                    continue;

                case 2:
                    int x = _r.ReadInt32();
                    type = _r.PeekFor(() => {
                        _r.BaseStream.Seek(x + _r.ContentsStart, SeekOrigin.Begin);
                        return(_r.ReadByte());
                    });
                    break;

                case 3:
                case 4:
                    _r.ReadWZString();
                    break;

                default:
                    throw new Exception("Unknown object type in WzDirectory.");
                }

                _r.ReadWZInt();
                _r.ReadWZInt();
                offset = _r.BaseStream.Position;
                if (type == 4)
                {
                    success = true;
                    break;
                }

                if (type == 3)
                {
                    try {
                        offset = _r.PeekFor(() => {
                            _r.BaseStream.Seek(_r.ReadWZOffset(), SeekOrigin.Begin);
                            long o;
                            success = DepthFirstImageSearch(out o);
                            return(o);
                        });
                        break;
                    } catch {}
                }
                _r.BaseStream.Seek(4, SeekOrigin.Current);
            }
            return(success);
        }
Пример #2
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));
                }
            }
        }
Пример #3
0
        public static IEnumerable <WZProperty> ImageChildren(WZProperty self)
        {
            using (WZReader reader = self.FileContainer.GetContentReader(null, self))
            {
                if (self.Offset >= reader.BaseStream.Length)
                {
                    yield break;
                }
                reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin);

                if (reader.ReadByte() != 0x73)
                {
                    throw new InvalidOperationException("Image should have header of 0x73");
                }
                long oldPosition = reader.BaseStream.Position;
                if (!reader.ReadWZString(false, self.Encrypted).Equals("Property"))
                {
                    reader.BaseStream.Position = oldPosition;
                    if (!reader.ReadWZStringExpecting(out self.Encrypted, "Property", false))
                    {
                        throw new InvalidOperationException("Unknown encryption method");
                    }
                }
                if (reader.ReadInt16() != 0)
                {
                    throw new InvalidOperationException("Image needs to have 0 as part of header");
                }

                foreach (WZProperty prop in PropertyList(reader, self).ToArray())
                {
                    yield return(prop);
                }
            }
        }
Пример #4
0
        static WZProperty Canvas(WZReader reader, WZProperty self)
        {
            // Define the variables ahead of time that way we can come back to them
            int  width = 0, height = 0, format1 = 0, format2 = 0;
            uint blockLen = 0, position = 0;

            // Define what well be doing once we come back
            WZProperty result = new WZPropertyWeak <Image <Rgba32> >(
                () => {
                using (reader = self.FileContainer.GetContentReader(null, self))
                {
                    reader.BaseStream.Seek(position + 1, SeekOrigin.Begin);
                    ushort header = reader.PeekFor(() => reader.ReadUInt16());
                    return(reader.ParsePNG(
                               width,
                               height,
                               format1 + format2,
                               header != 0x9C78 && header != 0xDA78,
                               blockLen - 1
                               ));
                }
            }, self
                );

            reader.BaseStream.Seek(1, SeekOrigin.Current);
            if (reader.ReadByte() == 1) // Has children
            {
                reader.BaseStream.Seek(2, SeekOrigin.Current);
                result.Children = PropertyList(reader, result).ToArray();
            }
            else
            {
                result.Children = new WZProperty[0];
            }
            width   = reader.ReadWZInt(); // width
            height  = reader.ReadWZInt(); // height
            format1 = reader.ReadWZInt(); // format 1
            format2 = reader.ReadByte();  // format 2
            reader.BaseStream.Seek(4, SeekOrigin.Current);
            blockLen    = (uint)reader.ReadInt32();
            result.Size = (uint)blockLen;
            position    = (uint)reader.BaseStream.Position;

            return(result);
        }
Пример #5
0
        public static WZProperty Image(WZReader reader, WZProperty self)
        {
            if (self.Offset >= reader.BaseStream.Length)
            {
                return(self);
            }
            self.ContainerStartLocation = self.Offset;
            reader.Container            = self;
            byte imgType = reader.ReadByte();

            if (imgType == 1)
            {
                return(new WZPropertyWeak <string>(() =>
                {
                    using (reader = self.FileContainer.GetContentReader(null, self))
                    {
                        reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin);
                        reader.ReadByte();
                        return reader.ReadLuaScript();
                    }
                }, self.NameWithoutExtension, self.Path, self.FileContainer, PropertyType.Lua, self.Parent, self.Size, self.Checksum, self.Offset));
            }
            if (imgType != 0x73)
            {
                throw new InvalidOperationException("Unknown image type, not supported!");
            }
            long oldPosition = reader.BaseStream.Position;

            if (!reader.ReadWZString(false, self.Encrypted).Equals("Property"))
            {
                reader.BaseStream.Position = oldPosition;
                if (!reader.ReadWZStringExpecting(out self.Encrypted, "Property", false))
                {
                    throw new InvalidOperationException("Unknown encryption method");
                }
            }
            if (reader.ReadInt16() != 0)
            {
                throw new InvalidOperationException("Image needs to have 0 as part of header");
            }

            return(self);
        }
Пример #6
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);
        }
Пример #7
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]);
                            }
                        }
                    }
                }
        }
Пример #8
0
        public static IEnumerable <WZProperty> PropertyList(WZReader reader, WZProperty parent)
        {
            if (reader.BaseStream.Position + 4 >= reader.BaseStream.Length)
            {
                return(new WZProperty[0]);
            }
            return(Enumerable.Range(0, reader.ReadWZInt()).Select(i =>
            {
                uint position = (uint)reader.BaseStream.Position;
                if (position >= reader.BaseStream.Length)
                {
                    return null;
                }
                string name = reader.ReadWZStringBlock(parent.Encrypted | parent.Container.Encrypted);
                byte type = reader.ReadByte();
                switch (type)
                {
                case 0:
                    return new WZProperty(name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Null, parent, 0, 0, position);

                case 0x10:
                    return new WZPropertyVal <sbyte>(reader.ReadSByte(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.UInt16, parent, 1, 0, position);

                case 0x11:
                    return new WZPropertyVal <byte>(reader.ReadByte(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.UInt16, parent, 1, 0, position);

                case 0x0B:
                case 2:
                case 0x12:
                    return new WZPropertyVal <UInt16>(reader.ReadUInt16(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.UInt16, parent, 2, 0, position);

                case 3:
                    return new WZPropertyVal <Int32>(reader.ReadWZInt(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Int32, parent, 4, 0, position);

                case 19:
                    return new WZPropertyVal <Rgba32>(new Rgba32((uint)reader.ReadWZInt()), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Int32, parent, 4, 0, position);

                case 4:
                    return new WZPropertyVal <Single>(reader.ReadWZSingle(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Single, parent, 4, 0, position);

                case 5:
                    return new WZPropertyVal <Double>(reader.ReadDouble(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Double, parent, 8, 0, position);

                case 8:
                    return new WZPropertyVal <string>(reader.ReadWZStringBlock(parent.Encrypted | parent.Container.Encrypted), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.String, parent, 0, 0, position);

                case 9:
                    uint blockLen = reader.ReadUInt32();
                    WZProperty result = reader.PeekFor(() => ParseExtendedProperty(reader, parent, name));
                    reader.BaseStream.Seek(blockLen, SeekOrigin.Current);
                    return result;

                case 20:
                    return new WZPropertyVal <long>(reader.ReadWZLong(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Int64, parent, 8, 0, position);

                case 21:
                    return new WZPropertyVal <ulong>((ulong)reader.ReadWZLong(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Int64, parent, 8, 0, position);

                default:
                    throw new Exception("Unknown property type at ParsePropertyList");
                }
            }));
        }