Exemple #1
0
 def ReadFChunkPartGuid(self, reader: ConstBitStreamWrapper) -> str:
     hex_str = ''
     hex_str += SwapOrder(reader.read_bytes(4))
     hex_str += SwapOrder(reader.read_bytes(4))
     hex_str += SwapOrder(reader.read_bytes(4))
     hex_str += SwapOrder(reader.read_bytes(4))
     return hex_str.upper()
Exemple #2
0
    def __init__(self, reader: ConstBitStreamWrapper):
        StartPos = reader.bytepos
        DataSize = reader.read_uint32()
        DataVersion = reader.read_uint8()

        ElementCount = reader.read_int32()
        self.FileManifest = [FFileManifest() for _ in range(ElementCount)]

        # Serialise the ManifestMetaVersion::Original version variables.
        if (DataVersion >= EFileManifestListVersion.Original.value):
            for idx, _ in enumerate(self.FileManifest):
                self.FileManifest[idx].Filename = reader.read_string()

            for idx, _ in enumerate(self.FileManifest):
                self.FileManifest[idx].SymlinkTarget = reader.read_string()

            for idx, _ in enumerate(self.FileManifest):
                self.FileManifest[idx].FileHash = reader.read_bytes(20)

            for idx, _ in enumerate(self.FileManifest):
                self.FileManifest[idx].FileMetaFlags = reader.read_uint8()

            for idx, _ in enumerate(self.FileManifest):
                self.FileManifest[idx].InstallTags = reader.read_array(
                    reader.read_string)

            for idx, _ in enumerate(self.FileManifest):
                self.FileManifest[idx].ChunkParts = self.ReadChunkParts(reader)

        # We must always make sure to seek the archive to the correct end location.
        reader.bytepos = StartPos + DataSize
Exemple #3
0
    def __init__(self, reader: ConstBitStreamWrapper):
        StartPos = reader.bytepos
        DataSize = reader.read_uint32()
        DataVersion = reader.read_uint8()

        ElementCount = reader.read_int32()
        self.ChunkList = [FChunkInfo() for _ in range(ElementCount)]
        # For a struct list type of data, we serialise every variable as it's own flat list.
        # This makes it very simple to handle or skip, extra variables added to the struct later.

        # Serialise the ManifestMetaVersion::Original version variables.
        if (DataVersion >= EChunkDataListVersion.Original.value):
            for idx, _ in enumerate(self.ChunkList):
                self.ChunkList[idx].Guid = self.ReadFChunkInfoGuid(reader)

            for idx, _ in enumerate(self.ChunkList):
                self.ChunkList[idx].Hash = ULongToHexHash(reader.read_uint64())

            for idx, _ in enumerate(self.ChunkList):
                self.ChunkList[idx].ShaHash = reader.read_bytes(20)

            for idx, _ in enumerate(self.ChunkList):
                self.ChunkList[idx].GroupNumber = int(reader.read_uint8())

            for idx, _ in enumerate(self.ChunkList):
                self.ChunkList[idx].WindowSize = reader.read_int32()

            for idx, _ in enumerate(self.ChunkList):
                self.ChunkList[idx].FileSize = int(reader.read_uint8())

        # We must always make sure to seek the archive to the correct end location.
        reader.bytepos = StartPos + DataSize
Exemple #4
0
 def ReadChunkParts(self,
                    reader: ConstBitStreamWrapper) -> List[FChunkPart]:
     ChunkCount = reader.read_int32()
     FChunkParts = []
     for _ in range(ChunkCount):
         reader.skip(4)
         FChunkParts.append(
             FChunkPart(Guid=self.ReadFChunkPartGuid(reader),
                        Offset=reader.read_int32(),
                        Size=reader.read_int32()))
     return FChunkParts
class FManifestData():
    def __init__(self, data: bytes):
        self.reader = ConstBitStreamWrapper(data)
        self.start()

    def start(self):
        StartPos = self.reader.bytepos

        # Read the Manifest Header
        self.Header = FManifestHeader(self.reader)

        # If we are loading an old format, defer to the old code!
        if (self.Header.Version.value <
                EFeatureLevel.StoredAsBinaryData.value):
            FullDataSize = GetFullDataSize(Header)
            FullData = reader.read_bytes(FullDataSize)
            self.reader.bytepos = StartPos

            temp = FManifestData(self.reader.read_bytes(FullDataSize))
            self.Meta = temp.Meta
            self.ChunkDataList = temp.ChunkDataList
            self.FileManifestList = temp.FileManifestList
            self.CustomFields = temp.CustomFields
            return
        else:
            # Compression format selection - we only have one right now.
            # Fill the array with loaded data.
            # DataSizeCompressed always equals the size of the data following the header.
            if self.Header.StoredAs == EManifestStorageFlags.Compressed.value:
                Decompressed = zlib.decompress(
                    self.reader.read_bytes(self.Header.DataSizeCompressed))
                ManifestRawData = ConstBitStreamWrapper(Decompressed)
            elif self.Header.StoredAs == EManifestStorageFlags.Encrypted.value:
                raise Exception('Encrypted Manifests are not supported yet')

        # Read the Manifest Meta
        self.Meta = FManifestMeta(ManifestRawData)
        # Read the Manifest Chunk List
        self.ChunkDataList = FChunkDataList(ManifestRawData)
        # Read the Manifest File List
        self.FileManifestList = FFileManifestList(ManifestRawData)
        # Read the Custom Fields
        self.CustomFields = FCustomFields(ManifestRawData)

    def GetFullDataSize(self) -> int:
        bIsCompressed = self.Header.StoredAs == EManifestStorageFlags.Compressed
        return self.Header.HeaderSize + (bIsCompressed
                                         if Header.DataSizeCompressed else
                                         Header.DataSizeUncompressed)
    def __init__(self, reader: ConstBitStreamWrapper, StartPos: int = 0):
        self.Magic = reader.read_uint32()
        # The size of this header.
        self.HeaderSize = reader.read_uint32()
        # The size of this data uncompressed.
        self.DataSizeUncompressed = reader.read_uint32()
        # The size of this data compressed.
        self.DataSizeCompressed = reader.read_uint32()
        # The SHA1 hash for the manifest data that follows.
        self.SHAHash = reader.read_bytes(20)
        # How the chunk data is stored.
        self.StoredAs = reader.read_uint8()

        bSuccess = self.Magic == MANIFEST_HEADER_MAGIC
        ExpectedSerializedBytes = ManifestHeaderVersionSizes[
            EFeatureLevel.Original.value]

        # After the Original with no specific version serialized, the header size increased and we had a version to load.
        if (bSuccess and self.HeaderSize >
                ManifestHeaderVersionSizes[EFeatureLevel.Original.value]):
            # The version of this header and manifest data format, driven by the feature level.
            Version = reader.read_int32()
            self.Version = ([
                e for e in EFeatureLevel.__members__.values()
                if e.value == Version
            ])[0]
            ExpectedSerializedBytes = ManifestHeaderVersionSizes[
                self.Version.value]
        elif (bSuccess):
            # Otherwise, this header was at the version for a UObject class before this code refactor.
            self.Version = EFeatureLevel.StoredAsCompressedUClass

        # Make sure the expected number of bytes were serialized. In practice this will catch errors where type
# serialization operators changed their format and that will need investigating.
        bSuccess = bSuccess and (reader.bytepos -
                                 StartPos) == ExpectedSerializedBytes
        if (bSuccess):
            # Make sure the archive now points to data location.
            reader.bytepos = StartPos + self.HeaderSize
        else:
            # If we had a serialization error when loading, raise an error
            raise Exception('Failed to read the Manifest Header')
Exemple #7
0
    def __init__(self, reader: ConstBitStreamWrapper):
        StartPos = reader.bytepos
        DataSize = reader.read_uint32()
        DataVersion = reader.read_uint8()

        ElementCount = reader.read_int32()
        self.CustomFields = {}

        # Serialise the ManifestMetaVersion::Original version variables.
        if (DataVersion >= EChunkDataListVersion.Original.value):
            for _ in range(ElementCount):
                self.CustomFields[reader.read_string()] = None

            for key in self.CustomFields.keys():
                self.CustomFields[key] = reader.read_string()

        # We must always make sure to seek the archive to the correct end location.
        reader.bytepos = StartPos + DataSize
    def __init__(self, reader: ConstBitStreamWrapper):
        # Serialise the data header type values.
        StartPos = reader.bytepos

        DataSize = reader.read_uint32()
        DataVersion = reader.read_uint8()

        # Serialise the ManifestMetaVersion::Original version variables.
        if (DataVersion >= EManifestMetaVersion.Original.value):
            self.FeatureLevelInt = reader.read_uint32()
            # Whether this is a legacy 'nochunks' build.
            self.IsFileData = reader.read_byte() == 1
            # The app id provided at generation.
            self.AppID = reader.read_uint32()
            # The app name string provided at generation.
            self.AppName = reader.read_string()
            # The build version string provided at generation.
            self.BuildVersion = reader.read_string()
            # The file in this manifest designated the application executable of the build.
            self.LaunchExe = reader.read_string()
            # The command line required when launching the application executable.
            self.LaunchCommand = reader.read_string()
            # The set of prerequisite ids for dependencies that this build's prerequisite installer will apply.
            self.PrereqIds = reader.read_array(reader.read_string)
            # A display string for the prerequisite provided at generation.
            self.PrereqName = reader.read_string()
            # The file in this manifest designated the launch executable of the prerequisite installer.
            self.PrereqPath = reader.read_string()
            # The command line required when launching the prerequisite installer.
            self.PrereqArgs = reader.read_string()

        # Serialise the BuildId.
        if (DataVersion >= EManifestMetaVersion.SerialisesBuildId.value):
            self.BuildId = reader.read_string()
        # Otherwise, initialise with backwards compatible default when loading.
        else:
            self.BuildId = 'Not added yet'  # self.GetBackwardsCompatibleBuildId()

        # Chunk Sub Dir
        if (self.FeatureLevelInt < EFeatureLevel.DataFileRenames.value):
            self.ChunkSubDir = 'Chunks'
        elif (self.FeatureLevelInt <
              EFeatureLevel.ChunkCompressionSupport.value):
            self.ChunkSubDir = 'ChunksV2'
        elif (self.FeatureLevelInt <
              EFeatureLevel.VariableSizeChunksWithoutWindowSizeChunkInfo.value
              ):
            self.ChunkSubDir = 'ChunksV3'
        else:
            self.ChunkSubDir = 'ChunksV4'

        # File Sub Dir
        if (self.FeatureLevelInt < EFeatureLevel.DataFileRenames.value):
            self.FileSubDir = 'Files'
        elif (self.FeatureLevelInt <
              EFeatureLevel.StoresChunkDataShaHashes.value):
            self.FileSubDir = 'FilesV2'
        else:
            self.FileSubDir = 'FilesV3'

        # We must always make sure to seek the archive to the correct end location.
        reader.bytepos = StartPos + DataSize
 def __init__(self, data: bytes):
     self.reader = ConstBitStreamWrapper(data)
     self.start()