Beispiel #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);
        }
Beispiel #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));
                }
            }
        }
Beispiel #3
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);
        }
Beispiel #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]);
                            }
                        }
                    }
                }
        }