Пример #1
0
 private void ReadScheme()
 {
     using (PartialStream stream = new PartialStream(m_stream, m_offset, m_size))
     {
         using (EndianReader reader = new EndianReader(stream, EndianType.LittleEndian))
         {
             Header.Read(reader);
             Metadata.Read(reader);
         }
     }
 }
Пример #2
0
        private static async Task <ISerializable> DeserializePayloadAsync(
            Stream stream,
            IReadOnlyDictionary <string, object?> header,
            CancellationToken cancellationToken = default)
        {
            var payloadLength = header.GetValueOrDefault(LengthKey) switch
            {
                null => (long?)null,
                var value => Convert.ToInt64(value)
            };

            var payloadType = header.GetValueOrDefault(TypeKey) as string;

            // Event
            if (string.Equals(payloadType, TypeValueEvent, StringComparison.OrdinalIgnoreCase))
            {
                var bufferLength = (int)(payloadLength ?? stream.Length);
                var buffer       = await stream.ReadByteChunkAsync(bufferLength, cancellationToken).ConfigureAwait(false);

                using var jsonDocument = JsonDocument.Parse(buffer);

                return(new JsonSerializable(
                           SentryEvent.FromJson(jsonDocument.RootElement.Clone())
                           ));
            }

            // User report
            if (string.Equals(payloadType, TypeValueUserReport, StringComparison.OrdinalIgnoreCase))
            {
                var bufferLength = (int)(payloadLength ?? stream.Length);
                var buffer       = await stream.ReadByteChunkAsync(bufferLength, cancellationToken).ConfigureAwait(false);

                using var jsonDocument = JsonDocument.Parse(buffer);

                return(new JsonSerializable(
                           UserFeedback.FromJson(jsonDocument.RootElement.Clone())
                           ));
            }

            // Arbitrary payload
            var payloadStream = new PartialStream(stream, stream.Position, payloadLength);

            if (payloadLength != null)
            {
                stream.Seek(payloadLength.Value, SeekOrigin.Current);
            }
            else
            {
                stream.Seek(0, SeekOrigin.End);
            }

            return(new StreamSerializable(payloadStream));
        }
Пример #3
0
        public SerializedFile ReadFile(IFileCollection collection, IAssemblyManager manager)
        {
            SerializedFile file = new SerializedFile(collection, manager, this);

            using (PartialStream stream = new PartialStream(m_stream, m_offset, m_size))
            {
                EndianType endianess = Header.SwapEndianess ? EndianType.BigEndian : EndianType.LittleEndian;
                using (EndianReader reader = new EndianReader(stream, endianess, stream.Position))
                {
                    file.Read(reader);
                }
            }
            return(file);
        }
        public async Task PartialStream_WithOffsetAndLength_SettingInvalidPosition_Throws()
        {
            // Arrange
            using var originalStream = new MemoryStream();
            await originalStream.FillWithRandomBytesAsync(1024);

            const int offset = 10;
            const int length = 100;

            using var partialStream = new PartialStream(originalStream, offset, length);

            // Act & assert
            Assert.Throws <InvalidOperationException>(() => partialStream.Position = 200);
        }
Пример #5
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.patchFile != null)
                {
                    this.patchFile.Close();
                }
            }

            this.patchFile     = null;
            this.patchBlock    = null;
            this.inflateStream = null;
        }
        public async Task PartialStream_WithOffsetAndLength_Length_ReturnsPartialLength()
        {
            // Arrange
            using var originalStream = new MemoryStream();
            await originalStream.FillWithRandomBytesAsync(1024);

            const int offset = 10;
            const int length = 100;

            using var partialStream = new PartialStream(originalStream, offset, length);

            // Act & assert
            partialStream.Length.Should().Be(length);
        }
Пример #7
0
        public static DuplicatableStream ReadDuplicatableSubstream(this Stream stream, long bytecount)
        {
            DuplicatableStream?ds = stream as DuplicatableStream;

            if (ds != null)
            {
                long          p  = ds.Position;
                PartialStream ps = new PartialStream(ds, p, bytecount);
                ds.Position = p + bytecount;
                return(ps);
            }
            else
            {
                return(new DuplicatableByteArrayStream(ReadBytes(stream, bytecount)));
            }
        }
Пример #8
0
        public byte[] GetContent(ISerializedFile file)
        {
            IResourceFile res = file.Collection.FindResourceFile(Path);

            if (res == null)
            {
                return(null);
            }

            byte[] data = new byte[Size];
            using (PartialStream resStream = new PartialStream(res.Stream, res.Offset, res.Size))
            {
                resStream.Position = Offset;
                resStream.ReadBuffer(data, 0, data.Length);
            }
            return(data);
        }
        public async Task PartialStream_WithOffset_ReadToEnd_ReturnsOnlyDataInRange()
        {
            // Arrange
            using var originalStream = new MemoryStream();
            await originalStream.FillWithRandomBytesAsync(1024);

            const int offset = 10;

            using var partialStream = new PartialStream(originalStream, offset, null);

            // Act
            using var outputStream = new MemoryStream();
            await partialStream.CopyToAsync(outputStream);

            // Assert
            var originalPortion = originalStream.ToArray().Skip(offset).ToArray();

            outputStream.Length.Should().Be(originalStream.Length - offset);
            outputStream.ToArray().Should().Equal(originalPortion);
        }
Пример #10
0
        private void ExportTexture(IExportContainer container, FileStream fileStream, Texture2D texture)
        {
            byte[] buffer = null;
            if (Texture2D.IsReadStreamData(texture.File.Version))
            {
                string path = texture.StreamData.Path;
                if (path == string.Empty)
                {
                    buffer = (byte[])texture.ImageData;
                }
                else
                {
                    if (texture.ImageData.Count != 0)
                    {
                        throw new Exception("Texture contains data and resource path");
                    }

                    using (ResourcesFile res = texture.File.Collection.FindResourcesFile(texture.File, path))
                    {
                        using (PartialStream resStream = new PartialStream(res.Stream, res.Offset, res.Size))
                        {
                            resStream.Position = texture.StreamData.Offset;
                            buffer             = new byte[texture.StreamData.Size];
                            resStream.Read(buffer, 0, buffer.Length);
                        }
                    }
                }
            }
            else
            {
                buffer = (byte[])texture.ImageData;
            }

            using (Bitmap bitmap = ConvertToBitmap(container, texture, buffer))
            {
                if (bitmap != null)
                {
                    bitmap.Save(fileStream, ImageFormat.Png);
                }
            }
        }
Пример #11
0
        public static void ExportBinary(Texture2D texture, Stream exportStream)
        {
            if (texture.CompleteImageSize == 0)
            {
                return;
            }

            if (Texture2D.IsReadStreamData(texture.File.Version))
            {
                string path = texture.StreamData.Path;
                if (path != string.Empty)
                {
                    if (texture.ImageData.Count != 0)
                    {
                        throw new Exception("Texture contains data and resource path");
                    }

                    using (ResourcesFile res = texture.File.Collection.FindResourcesFile(texture.File, path))
                    {
                        if (res == null)
                        {
                            Logger.Log(LogType.Warning, LogCategory.Export, $"Can't export '{texture.ValidName}' because resources file '{path}' wasn't found");
                            return;
                        }

                        using (PartialStream resStream = new PartialStream(res.Stream, res.Offset, res.Size))
                        {
                            resStream.Position = texture.StreamData.Offset;
                            Export(texture, exportStream, resStream, texture.StreamData.Size);
                        }
                    }
                    return;
                }
            }

            using (MemoryStream memStream = new MemoryStream((byte[])texture.ImageData))
            {
                Export(texture, exportStream, memStream, texture.ImageData.Count);
            }
        }
Пример #12
0
        public override void ExportBinary(IExportContainer container, Stream stream)
        {
            if (CompleteImageSize == 0)
            {
                return;
            }

            if (IsReadStreamData(container.Version))
            {
                string path = StreamData.Path;
                if (path != string.Empty)
                {
                    if (m_imageData.Length != 0)
                    {
                        throw new Exception("Texture contains data and resource path");
                    }

                    using (ResourcesFile res = File.Collection.FindResourcesFile(File, path))
                    {
                        if (res == null)
                        {
                            Logger.Log(LogType.Warning, LogCategory.Export, $"Can't export '{ValidName}' because resources file '{path}' wasn't found");
                            return;
                        }

                        using (PartialStream resStream = new PartialStream(res.Stream, res.Offset, res.Size))
                        {
                            resStream.Position = StreamData.Offset;
                            Export(container, stream, resStream, StreamData.Size);
                        }
                    }
                    return;
                }
            }

            using (MemoryStream memStream = new MemoryStream(m_imageData))
            {
                Export(container, stream, memStream, m_imageData.Length);
            }
        }
Пример #13
0
        public IReadOnlyList <byte> GetImageData()
        {
            byte[] data = m_imageData;
            if (IsReadStreamData(File.Version))
            {
                if (StreamData.Path != string.Empty)
                {
                    if (m_imageData.Length != 0)
                    {
                        throw new Exception($"Texture '{ValidName}' contains both data and resource path");
                    }

                    using (ResourcesFile res = File.Collection.FindResourcesFile(File, StreamData.Path))
                    {
                        if (res != null)
                        {
                            data = new byte[StreamData.Size];
                            using (PartialStream resStream = new PartialStream(res.Stream, res.Offset, res.Size))
                            {
                                resStream.Position = StreamData.Offset;
                                resStream.ReadBuffer(data, 0, data.Length);
                            }
                        }
                    }
                }
            }

            if (IsSwapBytes(File.Platform, TextureFormat))
            {
                for (int i = 0; i < data.Length; i += 2)
                {
                    byte b = data[i];
                    data[i]     = data[i + 1];
                    data[i + 1] = b;
                }
            }

            return(data);
        }
        public async Task PartialStream_WithOffsetAndLength_InnerPositionChanged_StillReadsCorrectly()
        {
            // Arrange
            using var originalStream = new MemoryStream();
            await originalStream.FillWithRandomBytesAsync(1024);

            const int offset = 10;
            const int length = 100;

            using var partialStream = new PartialStream(originalStream, offset, length);

            // Act
            originalStream.Position = 1000;

            // Assert
            using var outputStream = new MemoryStream();
            await partialStream.CopyToAsync(outputStream);

            var originalPortion = originalStream.ToArray().Skip(offset).Take(length).ToArray();

            outputStream.ToArray().Should().Equal(originalPortion);
        }
Пример #15
0
        /// <summary>
        /// Imports a resource file.
        /// </summary>
        public void Import(Stream stream)
        {
            var resourceStream = new PartialStream(
                archiveWrapper.archive_.BaseStream,
                delegate()     // offset
            {
                return(file.FileOffset * RageArchiveWrapper7.BLOCK_SIZE);
            },
                delegate()     // size
            {
                return(file.FileSize);
            },
                delegate(long length)
            {
                archiveWrapper.RequestBytesRES(file, length);
            }

                );

            resourceStream.SetLength(stream.Length);

            // read resource
            var reader = new DataReader(stream);

            reader.Position = 0;
            var ident         = reader.ReadUInt32();
            var version       = reader.ReadUInt32();
            var systemFlags   = reader.ReadUInt32();
            var graphicsFlags = reader.ReadUInt32();

            reader.Position = 0;
            var buffer = reader.ReadBytes((int)stream.Length);

            file.SystemFlags   = systemFlags;
            file.GraphicsFlags = graphicsFlags;
            resourceStream.Write(buffer, 0, buffer.Length);
        }
Пример #16
0
        private void ReadScheme()
        {
            using (PartialStream stream = new PartialStream(m_stream, m_offset, m_size))
            {
                using (EndianReader reader = new EndianReader(stream, EndianType.BigEndian))
                {
                    Header.Read(reader);

                    switch (Header.Type)
                    {
                    case ArchiveType.GZip:
                        m_dataStream = ReadGZip(reader);
                        break;

                    case ArchiveType.Brotli:
                        m_dataStream = ReadBrotli(reader);
                        break;

                    default:
                        throw new NotSupportedException(Header.Type.ToString());
                    }
                }
            }
        }
Пример #17
0
        private PartialStream TrySplit(Stream metaStream)
        {
            metaStream.Seek(0, SeekOrigin.Begin);
            BinaryReader  r = new BinaryReader(metaStream);
            PartialStream patchBlock;

            if (r.ReadUInt16() == 0x5a4d)//"MZ"
            {
                metaStream.Seek(-4, SeekOrigin.End);
                ulong check = r.ReadUInt32();
                if (check == 0xf2f7fbf3)
                {
                    metaStream.Seek(-12, SeekOrigin.End);
                    int patchBlockLength = r.ReadInt32();
                    int noticeLength     = r.ReadInt32();
                    metaStream.Seek(-12 - noticeLength - patchBlockLength, SeekOrigin.End);
                    patchBlock = new PartialStream(metaStream, metaStream.Position, patchBlockLength);
                    metaStream.Seek(patchBlockLength, SeekOrigin.Current);
                    noticeText = Encoding.Default.GetString(r.ReadBytes(noticeLength));
                }
                else //兼容TMS的patch.exe
                {
                    metaStream.Seek(-8, SeekOrigin.End);
                    check = r.ReadUInt64();
                    if (check == 0xf2f7fbf3)
                    {
                        metaStream.Seek(-24, SeekOrigin.End);
                        long patchBlockLength = r.ReadInt64();
                        long noticeLength     = r.ReadInt64();
                        metaStream.Seek(-24 - noticeLength - patchBlockLength, SeekOrigin.End);
                        patchBlock = new PartialStream(metaStream, metaStream.Position, patchBlockLength);
                        metaStream.Seek(patchBlockLength, SeekOrigin.Current);
                        noticeText = Encoding.Default.GetString(r.ReadBytes((int)noticeLength));
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
            else
            {
                patchBlock = new PartialStream(metaStream, 0, metaStream.Length);
            }

            if (patchBlock != null)
            {
                patchBlock.Seek(0, SeekOrigin.Begin);
                r = new BinaryReader(patchBlock);
                if (Encoding.ASCII.GetString(r.ReadBytes(8)) == "WzPatch\x1A")
                {
                    patchBlock.Seek(0, SeekOrigin.Begin);
                }
                else
                {
                    return(null);
                }
            }

            return(patchBlock);
        }
Пример #18
0
        public override void Run()
        {
            long   x;
            string id;
            IFile  destTemp;
            ITempIdentityFileService destTempService;
            IFile  dest;
            Stream srcStream = null, destStream = null;
            IFileHashingService hasher;
            string sourceHash, destTempHash;

            try
            {
                lock (this.SyncLock)
                {
                    m_TaskThread = Thread.CurrentThread;

                    if (m_TransferState != TransferState.NotStarted)
                    {
                        throw new InvalidOperationException();
                    }

                    SetTransferState(TransferState.Preparing);
                    ProcessTaskStateRequest();
                }

                id = m_Source.Address.Uri + m_Source.Length.ToString()
                     + (m_Source.Attributes.CreationTime ?? DateTime.MinValue).ToBinary().ToString();

                destTempService = (ITempIdentityFileService)m_Destination.GetService(new TempIdentityFileServiceType(id));

                destTemp = destTempService.GetTempFile();

                for (;;)
                {
                    try
                    {
                        x = destTemp.Length;
                    }
                    catch (FileNotFoundException)
                    {
                        x = 0;
                    }

                    dest = m_Destination.ParentDirectory.ResolveFile("$TMP_" + m_Destination.Address.Name + "_" + Guid.NewGuid().ToString("N"));

                    try
                    {
                        if (x == m_Source.Length)
                        {
                            try
                            {
                                if (m_Source.IdenticalTo(destTemp, FileComparingFlags.CompareContents))
                                {
                                    SetTransferState(TransferState.Copying);
                                    ProcessTaskStateRequest();

                                    m_Progress.RaiseValueChanged(m_Progress.CurrentValue, 0);

                                    destTemp.MoveTo(dest, true);

                                    if (!m_Source.IdenticalTo(dest, FileComparingFlags.CompareContents))
                                    {
                                        continue;
                                    }

                                    dest.RenameTo(m_Destination.Address.NameAndQuery, true);

                                    m_BytesTransferred = m_Destination.Length;

                                    m_Progress.RaiseValueChanged(m_Progress.CurrentValue, m_BytesTransferred);

                                    SetTransferState(TransferState.Finished);
                                    ProcessTaskStateRequest();

                                    return;
                                }
                            }
                            catch (IOException)
                            {
                            }
                        }

                        srcStream = m_Source.GetContent().GetInputStream(FileShare.Read);

                        if (!srcStream.CanSeek)
                        {
                            destStream = destTemp.GetContent().GetOutputStream(FileMode.Create, FileShare.Read);
                        }
                        else
                        {
                            destStream = destTemp.GetContent().GetOutputStream(FileMode.Append, FileShare.Read);

                            SetTransferState(TransferState.Comparing);
                            ProcessTaskStateRequest();

                            hasher = (IFileHashingService)m_Source.GetService(new FileHashingServiceType("md5"));

                            sourceHash = hasher.ComputeHash(0, destStream.Length).TextValue;

                            hasher = (IFileHashingService)destTemp.GetService(new FileHashingServiceType("md5"));

                            destTempHash = hasher.ComputeHash().TextValue;

                            if (sourceHash != destTempHash)
                            {
                                destStream.Close();
                                destStream = destTemp.GetContent().GetOutputStream(FileMode.Create, FileShare.Read);
                            }
                            else
                            {
                                m_Offset = destStream.Length;

                                if (m_Offset > 0)
                                {
                                    srcStream = new PartialStream(srcStream, m_Offset);
                                }
                            }
                        }

                        m_Progress.RaiseValueChanged(0, m_Offset);
                        ProcessTaskStateRequest();

                        m_Pump = new StreamPump(srcStream, destStream, true, false, m_ServiceType.BufferSize);

                        m_Pump.TaskStateChanged += new TaskEventHandler(Pump_TaskStateChanged);

                        SetTransferState(TransferState.Transferring);
                        ProcessTaskStateRequest();

                        m_Pump.Run();

                        if (m_Pump.TaskState == TaskState.Stopped)
                        {
                            throw new StopRequestedException();
                        }

                        SetTransferState(TransferState.Copying);
                        ProcessTaskStateRequest();
                    }
                    finally
                    {
                        if (srcStream != null)
                        {
                            Routines.IgnoreExceptions(delegate
                            {
                                srcStream.Close();
                            });
                        }

                        if (destStream != null)
                        {
                            Routines.IgnoreExceptions(delegate
                            {
                                destStream.Close();
                            });
                        }
                    }

                    break;
                }

                SetTransferState(TransferState.Tidying);

                destTemp.MoveTo(dest, true);

                ///
                /// Aquire an UpdateContext for the attributes
                /// so that all updates to the attributes are
                /// commited in a single operation
                ///

                using (dest.Attributes.AquireUpdateContext())
                {
                    foreach (string s in this.m_ServiceType.AttributesToTransfer)
                    {
                        dest.Attributes[s] = m_Source.Attributes[s];
                    }
                }

                dest.RenameTo(m_Destination.Address.Name, true);

                SetTransferState(TransferState.Finished);
            }
            finally
            {
                if (m_TransferState != TransferState.Stopped)
                {
                    SetTransferState(TransferState.Finished);
                }
            }
        }
        public override void DoRun()
        {
            IFile  destinationTemp;
            Stream destinationTempStream;
            string sourceHash;

            try
            {
                lock (this)
                {
                    SetTransferState(TransferState.Preparing);
                }

                Action <IFile> transferAttributes = delegate(IFile dest)
                {
                    using (dest.Attributes.AquireUpdateContext())
                    {
                        foreach (string s in this.serviceType.AttributesToTransfer)
                        {
                            dest.Attributes[s] = this.source.Attributes[s];
                        }
                    }
                };

                Stream sourceStream = null;

                for (var i = 0; i < 4; i++)
                {
                    try
                    {
                        sourceStream = this.OperatingNode.GetContent().GetInputStream(FileMode.Open, FileShare.Read);

                        break;
                    }
                    catch (NodeNotFoundException)
                    {
                        throw;
                    }
                    catch (Exception)
                    {
                        if (i == 3)
                        {
                            throw;
                        }
                    }

                    ProcessTaskStateRequest();
                }

                using (sourceStream)
                {
                    var sourceHashingService = (IHashingService)this.OperatingNode.GetService(new StreamHashingServiceType(sourceStream, this.HashAlgorithmName));

                    // Compute the hash of the source file

                    SetTransferState(TransferState.Comparing);
                    ProcessTaskStateRequest();

                    sourceHash = sourceHashingService.ComputeHash().TextValue;

                    // Try to open the destination file

                    ProcessTaskStateRequest();

                    var destinationHashingService = (IHashingService)this.TargetNode.GetService(new FileHashingServiceType(this.HashAlgorithmName));

                    string destinationHash;

                    try
                    {
                        destinationHash = destinationHashingService.ComputeHash().TextValue;
                    }
                    catch (DirectoryNodeNotFoundException)
                    {
                        this.TargetNode.ParentDirectory.Create(true);

                        try
                        {
                            destinationHash = destinationHashingService.ComputeHash().TextValue;
                        }
                        catch (NodeNotFoundException)
                        {
                            destinationHash = null;
                        }
                    }
                    catch (NodeNotFoundException)
                    {
                        destinationHash = null;
                    }

                    ProcessTaskStateRequest();

                    // Source and destination are identical

                    if (sourceHash == destinationHash)
                    {
                        SetTransferState(TransferState.Transferring);

                        this.progress.RaiseValueChanged(0, GetBytesToTransfer());

                        SetTransferState(TransferState.Tidying);

                        // Transfer attributes

                        try
                        {
                            transferAttributes((IFile)this.TargetNode);
                        }
                        catch (FileNotFoundException)
                        {
                        }

                        // Done

                        SetTransferState(TransferState.Finished);
                        ProcessTaskStateRequest();

                        return;
                    }

                    // Get a temp file for the destination based on the source's hash

                    destinationTemp = ((ITempIdentityFileService)this.destination.GetService(new TempIdentityFileServiceType(sourceHash))).GetTempFile();

                    // Get the stream for the destination temp file

                    try
                    {
                        if (!destinationTemp.ParentDirectory.Exists)
                        {
                            destinationTemp.ParentDirectory.Create(true);
                        }
                    }
                    catch (IOException)
                    {
                    }

                    using (destinationTempStream = destinationTemp.GetContent().OpenStream(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
                    {
                        Action finishUp = delegate
                        {
                            SetTransferState(TransferState.Tidying);

                            destinationTempStream.Close();

                            for (int i = 0; i < 4; i++)
                            {
                                try
                                {
                                    // Save hash value
                                    StandardFileHashingService.SaveHashToCache((IFile)destinationTemp, this.HashAlgorithmName,
                                                                               sourceHash, (IFile)this.TargetNode);

                                    try
                                    {
                                        // Transfer attributes
                                        transferAttributes(destinationTemp);
                                    }
                                    catch (FileNotFoundException e)
                                    {
                                        Console.WriteLine(e);
                                    }

                                    // Move destination temp to destination
                                    destinationTemp.MoveTo(this.TargetNode, true);

                                    break;
                                }
                                catch (Exception)
                                {
                                    if (i == 3)
                                    {
                                        throw;
                                    }
                                }

                                ProcessTaskStateRequest();
                            }

                            // Done

                            SetTransferState(TransferState.Finished);
                            ProcessTaskStateRequest();
                        };

                        // Get the hash for the destination temp file

                        var destinationTempHashingService = (IHashingService)destinationTemp.GetService(new StreamHashingServiceType(destinationTempStream));

                        // If the destination temp and the source aren't the same
                        // then complete the destination temp

                        string destinationTempHash;

                        if (destinationTempStream.Length >= sourceStream.Length)
                        {
                            // Destination is longer than source but starts source (unlikely)

                            destinationTempHash = destinationTempHashingService.ComputeHash(0, sourceStream.Length).TextValue;

                            if (destinationTempHash == sourceHash)
                            {
                                if (destinationTempStream.Length != sourceStream.Length)
                                {
                                    destinationTempStream.SetLength(sourceStream.Length);
                                }

                                finishUp();

                                return;
                            }

                            destinationTempStream.SetLength(0);
                        }

                        if (destinationTempStream.Length > 0)
                        {
                            destinationTempHash = destinationTempHashingService.ComputeHash().TextValue;

                            // Destination shorter than the source but is a partial copy of source

                            sourceHash = sourceHashingService.ComputeHash(0, destinationTempStream.Length).TextValue;

                            if (sourceHash == destinationTempHash)
                            {
                                this.offset = destinationTempStream.Length;
                            }
                            else
                            {
                                this.offset = 0;
                                destinationTempStream.SetLength(0);
                            }
                        }
                        else
                        {
                            this.offset = 0;
                        }

                        this.progress.RaiseValueChanged(0, this.offset);

                        // Transfer over the remaining part needed (or everything if offset is 0)

                        this.offset = destinationTempStream.Length;

                        Stream sourcePartialStream          = new PartialStream(sourceStream, destinationTempStream.Length);
                        Stream destinationTempPartialStream = new PartialStream(destinationTempStream, destinationTempStream.Length);

                        this.copier =
                            new StreamCopier(new BufferedStream(sourcePartialStream, this.serviceType.BufferSize), destinationTempPartialStream,
                                             false, false, this.serviceType.ChunkSize);

                        this.copier.TaskStateChanged += delegate(object sender, TaskEventArgs eventArgs)
                        {
                            if (eventArgs.TaskState == TaskState.Running ||
                                eventArgs.TaskState == TaskState.Paused ||
                                eventArgs.TaskState == TaskState.Stopped)
                            {
                                SetTaskState(eventArgs.TaskState);
                            }
                        };

                        SetTransferState(TransferState.Transferring);
                        ProcessTaskStateRequest();

                        this.copier.Run();

                        if (this.copier.TaskState == TaskState.Stopped)
                        {
                            throw new StopRequestedException();
                        }

                        finishUp();
                    }
                }
            }
            catch (StopRequestedException)
            {
            }
            finally
            {
                if (this.TransferState != TransferState.Finished)
                {
                    SetTransferState(TransferState.Stopped);
                }
            }
        }
Пример #20
0
        public HyoutaArchiveChunk(DuplicatableStream duplicatableStream, out ulong chunkLength)
        {
            using (DuplicatableStream data = duplicatableStream.Duplicate()) {
                data.Position = 0;

                // header
                ulong extraMagic = data.ReadUInt64(EndianUtils.Endianness.LittleEndian);
                ulong magic      = extraMagic & 0x00fffffffffffffful;
                if (magic != 0x6b6e7568636168)
                {
                    throw new Exception("wrong magic");
                }
                byte extra                  = (byte)((extraMagic >> 56) & 0xffu);
                byte packedAlignment        = (byte)(extra & 0x1fu);
                long unpackedAlignment      = 1L << packedAlignment;
                bool hasMetadata            = (extra & 0x20) != 0;
                bool isCompressed           = (extra & 0x40) != 0;
                bool isBigEndian            = (extra & 0x80) != 0;
                EndianUtils.Endianness e    = isBigEndian ? EndianUtils.Endianness.BigEndian : EndianUtils.Endianness.LittleEndian;
                ulong endOfFileOffset       = data.ReadUInt64(e) << packedAlignment;
                ulong tableOfContentsOffset = data.ReadUInt64(e) << packedAlignment;
                ulong filecount             = data.ReadUInt64(e);
                chunkLength = endOfFileOffset;

                if (hasMetadata)
                {
                    // just skip past this for now
                    ulong metadataLength = data.ReadUInt64(e);
                    data.DiscardBytes(metadataLength);
                }

                DuplicatableStream dataBlockStream;
                if (isCompressed)
                {
                    ushort compressionInfoLengthRaw       = data.ReadUInt16(e);
                    uint   compressionInfoLength          = compressionInfoLengthRaw & 0xfffcu;
                    int    compressionInfoAlignmentPacked = (compressionInfoLengthRaw & 0x3) + 1;
                    data.ReadAlign(1u << compressionInfoAlignmentPacked);
                    Compression.IHyoutaArchiveCompressionInfo?compressionInfo = HyoutaArchiveCompression.Deserialize(data, compressionInfoLength == 0 ? 0x10000u : compressionInfoLength, e);
                    if (compressionInfo == null)
                    {
                        throw new Exception("File is indicated to be compressed, but no decompressor found.");
                    }
                    dataBlockStream = compressionInfo.Decompress(data);
                }
                else
                {
                    data.ReadAlign(unpackedAlignment);
                    dataBlockStream = new PartialStream(data, data.Position, (long)(endOfFileOffset - (ulong)data.Position));
                }

                try {
                    data.Dispose();

                    dataBlockStream.Position = (long)tableOfContentsOffset;
                    uint offsetToFirstFileInfo = ReadContentLength(dataBlockStream, e);

                    // decode content bitfield(s)
                    long   numberOfUnknownBits = 0;
                    ushort contentBitfield1    = dataBlockStream.ReadUInt16(e);
                    bool   hasDummyContent     = (contentBitfield1 & 0x0001u) != 0;
                    bool   hasFilename         = (contentBitfield1 & 0x0002u) != 0;
                    bool   hasCompression      = (contentBitfield1 & 0x0004u) != 0;
                    bool   hasBpsPatch         = (contentBitfield1 & 0x0008u) != 0;
                    bool   hasCrc32            = (contentBitfield1 & 0x0010u) != 0;
                    bool   hasMd5  = (contentBitfield1 & 0x0020u) != 0;
                    bool   hasSha1 = (contentBitfield1 & 0x0040u) != 0;
                    numberOfUnknownBits += (contentBitfield1 & 0x0080u) != 0 ? 1 : 0;
                    numberOfUnknownBits += (contentBitfield1 & 0x0100u) != 0 ? 1 : 0;
                    numberOfUnknownBits += (contentBitfield1 & 0x0200u) != 0 ? 1 : 0;
                    numberOfUnknownBits += (contentBitfield1 & 0x0400u) != 0 ? 1 : 0;
                    numberOfUnknownBits += (contentBitfield1 & 0x0800u) != 0 ? 1 : 0;
                    numberOfUnknownBits += (contentBitfield1 & 0x1000u) != 0 ? 1 : 0;
                    numberOfUnknownBits += (contentBitfield1 & 0x2000u) != 0 ? 1 : 0;
                    numberOfUnknownBits += (contentBitfield1 & 0x4000u) != 0 ? 1 : 0;
                    ushort currentBitfield = contentBitfield1;
                    while ((currentBitfield & 0x8000u) != 0)
                    {
                        // more bitfields, though we don't understand them since only the first handful of bits are defined at the moment, so just count and skip them
                        currentBitfield      = dataBlockStream.ReadUInt16(e);
                        numberOfUnknownBits += (currentBitfield & 0x0001u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0002u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0004u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0008u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0010u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0020u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0040u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0080u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0100u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0200u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0400u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x0800u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x1000u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x2000u) != 0 ? 1 : 0;
                        numberOfUnknownBits += (currentBitfield & 0x4000u) != 0 ? 1 : 0;
                    }
                    uint dummyContentLength   = hasDummyContent ? ReadContentLength(dataBlockStream, e) : 0;
                    uint filenameLength       = hasFilename ? ReadContentLength(dataBlockStream, e) : 0;
                    uint compressionLength    = hasCompression ? ReadContentLength(dataBlockStream, e) : 0;
                    uint bpspatchLength       = hasBpsPatch ? ReadContentLength(dataBlockStream, e) : 0;
                    uint crc32Length          = hasCrc32 ? ReadContentLength(dataBlockStream, e) : 0;
                    uint md5Length            = hasMd5 ? ReadContentLength(dataBlockStream, e) : 0;
                    uint sha1Length           = hasSha1 ? ReadContentLength(dataBlockStream, e) : 0;
                    long unknownContentLength = 0;
                    for (long i = 0; i < numberOfUnknownBits; ++i)
                    {
                        unknownContentLength += ReadContentLength(dataBlockStream, e);
                    }

                    dataBlockStream.Position = (long)(tableOfContentsOffset + offsetToFirstFileInfo);
                    List <HyoutaArchiveFileInfo> files = new List <HyoutaArchiveFileInfo>((int)filecount);
                    for (ulong i = 0; i < filecount; ++i)
                    {
                        ulong offset             = dataBlockStream.ReadUInt64(e) << packedAlignment;
                        ulong filesize           = dataBlockStream.ReadUInt64(e);
                        HyoutaArchiveFileInfo fi = new HyoutaArchiveFileInfo();
                        if (hasDummyContent)
                        {
                            fi.DummyContent = dataBlockStream.ReadBytes(dummyContentLength);
                        }
                        if (hasFilename)
                        {
                            fi.Filename = ReadString(dataBlockStream, filenameLength, e);
                        }
                        if (hasCompression)
                        {
                            fi.CompressionInfo    = HyoutaArchiveCompression.Deserialize(dataBlockStream, compressionLength, e);
                            fi.StreamIsCompressed = true;
                        }
                        if (hasBpsPatch)
                        {
                            fi.BpsPatchInfo     = HyoutaArchiveBpsPatchInfo.Deserialize(dataBlockStream, bpspatchLength, e, i, this);
                            fi.StreamIsBpsPatch = fi.BpsPatchInfo != null;
                        }
                        if (hasCrc32)
                        {
                            if (crc32Length >= 4)
                            {
                                fi.crc32 = new CRC32(dataBlockStream.ReadUInt32(EndianUtils.Endianness.BigEndian));
                                dataBlockStream.DiscardBytes(crc32Length - 4);
                            }
                            else
                            {
                                dataBlockStream.DiscardBytes(crc32Length);
                            }
                        }
                        if (hasMd5)
                        {
                            if (md5Length >= 16)
                            {
                                ulong a = dataBlockStream.ReadUInt64(EndianUtils.Endianness.BigEndian);
                                ulong b = dataBlockStream.ReadUInt64(EndianUtils.Endianness.BigEndian);
                                fi.md5 = new MD5(a, b);
                                dataBlockStream.DiscardBytes(md5Length - 16);
                            }
                            else
                            {
                                dataBlockStream.DiscardBytes(md5Length);
                            }
                        }
                        if (hasSha1)
                        {
                            if (sha1Length >= 20)
                            {
                                ulong a = dataBlockStream.ReadUInt64(EndianUtils.Endianness.BigEndian);
                                ulong b = dataBlockStream.ReadUInt64(EndianUtils.Endianness.BigEndian);
                                uint  c = dataBlockStream.ReadUInt32(EndianUtils.Endianness.BigEndian);
                                fi.sha1 = new SHA1(a, b, c);
                                dataBlockStream.DiscardBytes(sha1Length - 20);
                            }
                            else
                            {
                                dataBlockStream.DiscardBytes(sha1Length);
                            }
                        }
                        dataBlockStream.DiscardBytes(unknownContentLength);

                        fi.Data = new PartialStream(dataBlockStream, (long)offset, (long)filesize);
                        files.Add(fi);
                    }

                    Files = files;
                } finally {
                    dataBlockStream.Dispose();
                }
            }
        }
Пример #21
0
        public SaveData(HyoutaPluginBase.DuplicatableStream stream, EndianUtils.Endianness endian)
        {
            MenuBlock = new SaveMenuBlock(new PartialStream(stream, 0, 0x228));

            // actual save file
            using (DuplicatableStream saveDataStream = new PartialStream(stream, 0x228, stream.Length - 0x228)) {
                string magic = saveDataStream.ReadAscii(8);
                if (magic != "TO8SAVE\0")
                {
                    throw new Exception("Invalid magic byte sequence for ToV save: " + magic);
                }
                uint saveFileSize = saveDataStream.ReadUInt32().FromEndian(endian);
                saveDataStream.DiscardBytes(0x14);                   // seemingly unused
                uint sectionMetadataBlockStart = saveDataStream.ReadUInt32().FromEndian(endian);
                uint sectionCount   = saveDataStream.ReadUInt32().FromEndian(endian);
                uint dataStart      = saveDataStream.ReadUInt32().FromEndian(endian);
                uint refStringStart = saveDataStream.ReadUInt32().FromEndian(endian);

                for (uint i = 0; i < sectionCount; ++i)
                {
                    uint headerPosition = sectionMetadataBlockStart + i * 0x20;
                    saveDataStream.Position = headerPosition;
                    uint   refStringPos = saveDataStream.ReadUInt32().FromEndian(endian);
                    uint   offset       = saveDataStream.ReadUInt32().FromEndian(endian);
                    uint   size         = saveDataStream.ReadUInt32().FromEndian(endian);
                    var    blockStream  = new PartialStream(saveDataStream, dataStart + offset, size);
                    string blockName    = saveDataStream.ReadAsciiNulltermFromLocationAndReset(refStringStart + refStringPos);

                    if (blockName.StartsWith("PC_STATUS"))
                    {
                        int idx = int.Parse(blockName.Substring("PC_STATUS".Length)) - 1;
                        CharacterData[idx] = new SaveDataBlockPCStatus(blockStream);
                    }
                    else
                    {
                        switch (blockName)
                        {
                        case "Scenario": Scenario = new SaveDataBlockScenario(blockStream); break;

                        case "FieldCamera": FieldCamera = new SaveDataBlockFieldCamera(blockStream); break;

                        case "FieldArea": FieldArea = new SaveDataBlockFieldArea(blockStream); break;

                        case "FieldCar": FieldCar = new SaveDataBlockFieldCar(blockStream); break;

                        case "Camp": Camp = new SaveDataBlockCamp(blockStream); break;

                        case "FIELD_SAVE": FieldSave = new SaveDataBlockFieldSave(blockStream); break;

                        case "STANDBYENEMY": StandbyEnemy = new SaveDataBlockStandbyEnemy(blockStream); break;

                        case "TERASURE_SAVE": TerasureSave = new SaveDataBlockTerasureSave(blockStream); break;

                        case "TreasureSaveData": TreasureSaveData = new SaveDataBlockTreasureSaveData(blockStream); break;

                        case "CUSTOM_DATA": CustomData = new SaveDataBlockCustomData(blockStream); break;

                        case "SoundTheater": SoundTheater = new SaveDataBlockSoundTheater(blockStream); break;

                        case "SavePoint": SavePoint = new SaveDataBlockSavePoint(blockStream); break;

                        case "MG2Poker": MG2Poker = new SaveDataBlockMG2Poker(blockStream); break;

                        case "SnowBoard": SnowBoard = new SaveDataBlockSnowBoard(blockStream); break;

                        case "PARTY_DATA": PartyData = new SaveDataBlockPartyData(blockStream); break;

                        case "FieldGadget": FieldGadget = new SaveDataBlockFieldGadget(blockStream); break;

                        default: Console.WriteLine("Unknown save data block '" + blockName + "'"); break;
                        }
                    }
                }
            }
        }
Пример #22
0
        public async Task <HttpResponseMessage> Import()
        {
            using (var stream = await Request.Content.ReadAsStreamAsync().ConfigureAwait(false))
            {
                var  binaryReader = new BinaryReader(stream);
                long count        = 0;
                while (true)
                {
                    string name;
                    try
                    {
                        name = binaryReader.ReadString();
                    }
                    catch (EndOfStreamException)
                    {
                        break; // done
                    }

                    var metadata = RavenJObject.Parse(binaryReader.ReadString());

                    if (name.Length > SystemParameters.KeyMost)
                    {
                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug("File '{0}' was not created due to illegal name length", name);
                        }
                        return(GetMessageWithString(string.Format("File '{0}' was not created due to illegal name length", name), HttpStatusCode.BadRequest));
                    }

                    var contentSize = binaryReader.ReadInt64();
                    var options     = new FileActions.PutOperationOptions
                    {
                        ContentSize = contentSize
                    };

                    RavenJToken lastModifiedJToken;
                    if (metadata.TryGetValue(Constants.RavenLastModified, out lastModifiedJToken))
                    {
                        DateTimeOffset lastModified;
                        if (DateTimeOffset.TryParse(lastModifiedJToken.Value <string>(), out lastModified))
                        {
                            options.LastModified = lastModified;
                        }
                    }

                    options.PreserveTimestamps = true;

                    var fileStream = new PartialStream(stream, contentSize);
                    var tcs        = new TaskCompletionSource <Stream>();
                    tcs.SetResult(fileStream);

                    await FileSystem.Files.PutAsync(name, null, metadata, () => tcs.Task, options).ConfigureAwait(false);

                    if (count % 100 == 0)
                    {
                        SynchronizationTask.Context.NotifyAboutWork();
                    }
                }

                SynchronizationTask.Context.NotifyAboutWork();
            }


            return(new HttpResponseMessage(HttpStatusCode.OK)
            {
            });
        }
Пример #23
0
        public override void ExportBinary(IExportContainer container, Stream stream)
        {
            if (IsReadLoadType(container.Version))
            {
                using (ResourcesFile res = File.Collection.FindResourcesFile(File, FSBResource.Source))
                {
                    if (res == null)
                    {
                        Logger.Log(LogType.Warning, LogCategory.Export, $"Can't export '{ValidName}' because resources file '{FSBResource.Source}' hasn't been found");
                        return;
                    }

                    if (StreamedResource.IsReadSize(container.Version))
                    {
                        using (PartialStream resStream = new PartialStream(res.Stream, res.Offset, res.Size))
                        {
                            resStream.Position = FSBResource.Offset;
                            resStream.CopyStream(stream, FSBResource.Size);
                        }
                    }
                    else
                    {
                        // I think they read data by its type for this verison, so I can't even export raw data :/
                        Logger.Log(LogType.Warning, LogCategory.Export, $"Can't export '{ValidName}' because of unknown size");
                    }
                }
            }
            else
            {
                if (IsReadStreamingInfo(container.Version))
                {
                    if (LoadType == AudioClipLoadType.Streaming)
                    {
                        if (m_audioData == null)
                        {
                            using (ResourcesFile res = File.Collection.FindResourcesFile(File, StreamingInfo.Path))
                            {
                                if (res == null)
                                {
                                    Logger.Log(LogType.Warning, LogCategory.Export, $"Can't export '{ValidName}' because resources file '{StreamingInfo.Path}' hasn't been found");
                                    return;
                                }

                                using (PartialStream resStream = new PartialStream(res.Stream, res.Offset, res.Size))
                                {
                                    resStream.Position = StreamingInfo.Offset;
                                    resStream.CopyStream(stream, StreamingInfo.Size);
                                }
                            }
                        }
                        else
                        {
                            stream.Write(m_audioData, 0, m_audioData.Length);
                        }
                    }
                    else
                    {
                        stream.Write(m_audioData, 0, m_audioData.Length);
                    }
                }
                else
                {
                    stream.Write(m_audioData, 0, m_audioData.Length);
                }
            }
        }