예제 #1
0
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            // TODO - Rewrite this shit. Use dictionary or something.
            // Yes, I know that string interpolation exists, but I dont like it.
            sb.AppendFormat(
                "levelID={0}&version={1}&user_id={2}&credits={3}&cowboyChance={4}&title={5}&time={6}&note={7}&min_level={8}&song={9}&gravity={10}&max_time={11}&has_pass={12}&live={13}&items={14}&gameMode={15}&data={16}",
                this.Id,
                this.Version,
                this.UserId,
                String.Empty,
                this.CowboyChance,
                this.Title.ToUrlEncodedString(),
                this.SubmittedDate.GetSecondsSinceUnixTime(),
                this.Note.ToUrlEncodedString(),
                this.MinLevel,
                this.Song,
                this.Gravity.ToString(StringFormat.DECIMAL_TWO, CultureInfo.InvariantCulture),
                this.MaxTime,
                !String.IsNullOrEmpty(this.PassHash),
                Convert.ToInt32(this.Live),
                this.Items,
                this.GameMode.GetEnumDescription(),
                this.Data);

            using (MD5Wrapper md5 = new MD5Wrapper())
            {
                String hash = md5.GetHashedString(String.Concat(this.Version.ToString(), this.Id.ToString(), sb.ToString(), Pepper.LEVEL_LOAD));
                sb.Append(hash);
            }

            return(sb.ToString());
        }
        public void MD5ComparisonTest()
        {
            CloudStorageAccount.UseV1MD5 = false;

            try
            {
                using (MD5Wrapper nativeHash = new MD5Wrapper())
                {
                    nativeHash.UpdateHash(data, 0, data.Length);
                    string nativeResult = nativeHash.ComputeHash();

                    MD5 hash = MD5.Create();
                    hash.TransformBlock(data, 0, data.Length, null, 0);
                    hash.TransformFinalBlock(new byte[0], 0, 0);
                    byte[] bytes = hash.Hash;
                    string result = Convert.ToBase64String(bytes);

                    Assert.AreEqual(nativeResult, result);
                }
            }
            finally
            {
                CloudStorageAccount.UseV1MD5 = true;
            }
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the FileWriteStreamBase class for a file.
        /// </summary>
        /// <param name="file">File reference to write to.</param>
        /// <param name="fileSize">Size of the file.</param>
        /// <param name="createNew">Use <c>true</c> if the file is newly created, <c>false</c> otherwise.</param>
        /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the file. If <c>null</c>, no condition is used.</param>
        /// <param name="options">An <see cref="FileRequestOptions"/> object that specifies additional options for the request.</param>
        /// <param name="operationContext">An <see cref="OperationContext"/> object for tracking the current operation.</param>
        protected FileWriteStreamBase(CloudFile file, long fileSize, bool createNew, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext)
            : base()
        {
            this.internalBuffer       = new MultiBufferMemoryStream(file.ServiceClient.BufferManager);
            this.currentOffset        = 0;
            this.accessCondition      = accessCondition;
            this.options              = options;
            this.operationContext     = operationContext;
            this.noPendingWritesEvent = new CounterEvent();
            this.fileMD5              = this.options.StoreFileContentMD5.Value ? new MD5Wrapper() : null;
            this.rangeMD5             = this.options.UseTransactionalMD5.Value ? new MD5Wrapper() : null;
#if !(NETCORE || WINDOWS_RT)
            this.parallelOperationSemaphoreAsync = new AsyncSemaphoreAsync(options.ParallelOperationThreadCount.Value);
#else
            this.parallelOperationSemaphore = new AsyncSemaphore(options.ParallelOperationThreadCount.Value);
#endif
            this.lastException     = null;
            this.committed         = false;
            this.disposed          = false;
            this.currentFileOffset = 0;
            this.file     = file;
            this.fileSize = fileSize;
            this.streamWriteSizeInBytes = file.StreamWriteSizeInBytes;
            this.newFile = createNew;
        }
예제 #4
0
 /// <summary>
 /// Encodes the input as a MD5 hash
 /// </summary>
 /// <param name="input">
 /// The input we want encoded <see cref="System.String"/>
 /// </param>
 /// <returns>
 /// The MD5 hash encoded result of input <see cref="System.String"/>
 /// </returns>
 public string CreateMD5Hash(string input)
 {
             #if !UNITY_FLASH && !UNITY_WP8 && !UNITY_METRO
     // Gets the MD5 hash for input
     MD5    md5  = new MD5CryptoServiceProvider();
     byte[] data = Encoding.UTF8.GetBytes(input);
     byte[] hash = md5.ComputeHash(data);
     // Transforms as hexa
     string hexaHash = "";
     foreach (byte b in hash)
     {
         hexaHash += String.Format("{0:x2}", b);
     }
     // Returns MD5 hexa hash as string
     return(hexaHash);
             #elif UNITY_WP8 || UNITY_METRO
     byte[] data = Encoding.UTF8.GetBytes(input);
     byte[] hash = MD5Core.GetHash(data);
     // Transforms as hexa
     string hexaHash = "";
     foreach (byte b in hash)
     {
         hexaHash += String.Format("{0:x2}", b);
     }
     // Returns MD5 hexa hash as string
     return(hexaHash);
             #else
     return(MD5Wrapper.Md5Sum(input));
             #endif
 }
        /// <summary>
        /// Releases the blob resources used by the Stream.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.blobMD5 != null)
                {
                    this.blobMD5.Dispose();
                    this.blobMD5 = null;
                }

                if (this.blockMD5 != null)
                {
                    this.blockMD5.Dispose();
                    this.blockMD5 = null;
                }

                if (this.internalBuffer != null)
                {
                    this.internalBuffer.Dispose();
                    this.internalBuffer = null;
                }
            }

            base.Dispose(disposing);
        }
예제 #6
0
        private string GenerateBlockIdPrefix()
        {
            //var blockIdPrefix = Guid.NewGuid().ToString("N") + "-";

            // Originally the blockId is an GUID + "-". It will cause some problem when switch machines or jnl get cleaned
            // to upload to the same block blob - block id is not shared between the 2 DMLib instances
            // and it may result in reaching the limitation of maximum 50000 uncommited blocks + 50000 committed blocks.
            //
            // Change it to hash based prefix to make it preditable and can be shared between multiple DMLib instances
            string blobNameHash;

            using (var md5 = new MD5Wrapper())
            {
                var blobNameBytes = Encoding.UTF8.GetBytes(this.destLocation.Blob.Name);
                md5.UpdateHash(blobNameBytes, 0, blobNameBytes.Length);
                blobNameHash = md5.ComputeHash();
            }

            // The original GUID format prefix's length is 32 + 1 ("-")
            // As the service requires the blockid has the same size of each block,
            // To keep the compatibility, add 9 chars to the end of the hash ( 33 - 24)
            var blockIdPrefix = blobNameHash + "12345678-";

            return(blockIdPrefix);
        }
        /// <summary>
        /// Releases the file resources used by the Stream.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.fileMD5 != null)
                {
                    this.fileMD5.Dispose();
                    this.fileMD5 = null;
                }

                if (this.rangeMD5 != null)
                {
                    this.rangeMD5.Dispose();
                    this.rangeMD5 = null;
                }

                if (this.internalBuffer != null)
                {
                    this.internalBuffer.Dispose();
                    this.internalBuffer = null;
                }

                if (this.noPendingWritesEvent != null)
                {
                    this.noPendingWritesEvent.Dispose();
                    this.noPendingWritesEvent = null;
                }
            }

            base.Dispose(disposing);
        }
 /// <summary>
 /// Initializes a new instance of the BlobReadStreamBase class.
 /// </summary>
 /// <param name="blob">Blob reference to read from</param>
 /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
 /// <param name="options">An object that specifies any additional options for the request.</param>
 /// <param name="operationContext">An <see cref="OperationContext"/> object for tracking the current operation.</param>
 protected BlobReadStreamBase(ICloudBlob blob, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
 {
     this.blob = blob;
     this.isLengthAvailable = false;
     this.currentOffset = 0;
     this.buffer = new MemoryStream();
     this.accessCondition = accessCondition;
     this.lockedToETag = false;
     this.options = options;
     this.operationContext = operationContext;
     this.blobMD5 = options.DisableContentMD5Validation.Value ? null : new MD5Wrapper();
     this.lastException = null;
 }
예제 #9
0
 /// <summary>
 /// Initializes a new instance of the BlobReadStreamBase class.
 /// </summary>
 /// <param name="blob">Blob reference to read from</param>
 /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
 /// <param name="options">An object that specifies any additional options for the request.</param>
 /// <param name="operationContext">An <see cref="OperationContext"/> object for tracking the current operation.</param>
 protected BlobReadStreamBase(ICloudBlob blob, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
 {
     this.blob = blob;
     this.isLengthAvailable = false;
     this.currentOffset     = 0;
     this.buffer            = new MemoryStream();
     this.accessCondition   = accessCondition;
     this.lockedToETag      = false;
     this.options           = options;
     this.operationContext  = operationContext;
     this.blobMD5           = options.DisableContentMD5Validation.Value ? null : new MD5Wrapper();
     this.lastException     = null;
 }
 /// <summary>
 /// Initializes a new instance of the BlobWriteStreamBase class.
 /// </summary>
 /// <param name="serviceClient">The service client.</param>
 /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
 /// <param name="options">An object that specifies any additional options for the request.</param>
 /// <param name="operationContext">An <see cref="OperationContext" /> object for tracking the current operation.</param>
 private BlobWriteStreamBase(CloudBlobClient serviceClient, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
     : base()
 {
     this.currentOffset              = 0;
     this.accessCondition            = accessCondition;
     this.options                    = options;
     this.operationContext           = operationContext;
     this.pendingWrites              = 0;
     this.noPendingWritesEvent       = new ManualResetEvent(true);
     this.blobMD5                    = options.StoreBlobContentMD5.Value ? new MD5Wrapper() : null;
     this.blockMD5                   = options.UseTransactionalMD5.Value ? new MD5Wrapper() : null;
     this.parallelOperationSemaphore = new AsyncSemaphore(serviceClient.ParallelOperationThreadCount);
     this.lastException              = null;
 }
 /// <summary>
 /// Initializes a new instance of the BlobWriteStreamBase class.
 /// </summary>
 /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param>
 /// <param name="options">An object that specifies any additional options for the request.</param>
 /// <param name="operationContext">An <see cref="OperationContext"/> object for tracking the current operation.</param>
 private BlobWriteStreamBase(CloudBlobClient serviceClient, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
     : base()
 {
     this.currentOffset = 0;
     this.accessCondition = accessCondition;
     this.options = options;
     this.operationContext = operationContext;
     this.pendingWrites = 0;
     this.noPendingWritesEvent = new ManualResetEvent(true);
     this.blobMD5 = options.StoreBlobContentMD5.Value ? new MD5Wrapper() : null;
     this.blockMD5 = options.UseTransactionalMD5.Value ? new MD5Wrapper() : null;
     this.parallelOperationSemaphore = new AsyncSemaphore(serviceClient.ParallelOperationThreadCount);
     this.lastException = null;
 }
예제 #12
0
        public void MD5SingleByteTest()
        {
            MD5Wrapper nativeHash = new MD5Wrapper();
            nativeHash.UpdateHash(data, 3, 2);
            string nativeResult = nativeHash.ComputeHash();

            MD5 hash = MD5.Create();
            hash.TransformBlock(data, 3, 2, null, 0);
            hash.TransformFinalBlock(new byte[0], 0, 0);
            var bytes = hash.Hash;
            string result = Convert.ToBase64String(bytes);

            Assert.AreEqual(nativeResult, result);
        }
예제 #13
0
        /// <summary>
        /// Sets the position within the current stream.
        /// </summary>
        /// <param name="offset">A byte offset relative to the origin parameter.</param>
        /// <param name="origin">A value of type <c>SeekOrigin</c> indicating the reference
        /// point used to obtain the new position.</param>
        /// <returns>The new position within the current stream.</returns>
        /// <remarks>Seeking in a BlobReadStream disables MD5 validation.</remarks>
        public override long Seek(long offset, SeekOrigin origin)
        {
            if (this.lastException != null)
            {
                throw this.lastException;
            }

            long newOffset;

            switch (origin)
            {
            case SeekOrigin.Begin:
                newOffset = offset;
                break;

            case SeekOrigin.Current:
                newOffset = this.currentOffset + offset;
                break;

            case SeekOrigin.End:
                newOffset = this.Length + offset;
                break;

            default:
                CommonUtility.ArgumentOutOfRange("origin", origin);
                throw new ArgumentOutOfRangeException("origin");
            }

            CommonUtility.AssertInBounds("offset", newOffset, 0, this.Length);

            if (newOffset != this.currentOffset)
            {
                long bufferOffset = this.internalBuffer.Position + (newOffset - this.currentOffset);
                if ((bufferOffset >= 0) && (bufferOffset < this.internalBuffer.Length))
                {
                    this.internalBuffer.Position = bufferOffset;
                }
                else
                {
                    this.internalBuffer.SetLength(0);
                }

                this.blobMD5       = null;
                this.currentOffset = newOffset;
            }

            return(this.currentOffset);
        }
        public void MD5V1ComparisonTest()
        {
            using (MD5Wrapper nativeHash = new MD5Wrapper())
            {
                nativeHash.UpdateHash(data, 0, data.Length);
                string nativeResult = nativeHash.ComputeHash();

                MD5 hash = MD5.Create();
                hash.TransformBlock(data, 0, data.Length, null, 0);
                hash.TransformFinalBlock(new byte[0], 0, 0);
                byte[] bytes = hash.Hash;
                string result = Convert.ToBase64String(bytes);
                
                Assert.AreEqual(nativeResult, result);
            }
        }
예제 #15
0
 /// <summary>
 /// Initializes a new instance of the BlobWriteStreamBase class.
 /// </summary>
 /// <param name="serviceClient">The service client.</param>
 /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the condition that must be met in order for the request to proceed. If <c>null</c>, no condition is used.</param>
 /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param>
 /// <param name="operationContext">An <see cref="OperationContext"/> object that represents the context for the current operation.</param>
 private BlobWriteStreamBase(CloudBlobClient serviceClient, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
     : base()
 {
     this.internalBuffer             = new MultiBufferMemoryStream(serviceClient.BufferManager);
     this.accessCondition            = accessCondition;
     this.currentOffset              = 0;
     this.options                    = options;
     this.operationContext           = operationContext;
     this.noPendingWritesEvent       = new CounterEvent();
     this.blobMD5                    = this.options.StoreBlobContentMD5.Value ? new MD5Wrapper() : null;
     this.blockMD5                   = this.options.UseTransactionalMD5.Value ? new MD5Wrapper() : null;
     this.parallelOperationSemaphore = new AsyncSemaphore(options.ParallelOperationThreadCount.Value);
     this.lastException              = null;
     this.committed                  = false;
     this.disposed                   = false;
 }
예제 #16
0
        public void MD5EmptyArrayTest()
        {
            byte[] data = new byte[] { };
            MD5Wrapper nativeHash = new MD5Wrapper();
            nativeHash.UpdateHash(data, 0, data.Length);
            string nativeResult = nativeHash.ComputeHash();


            MD5 hash = MD5.Create();
            hash.ComputeHash(data, 0, data.Length);
            var varResult = hash.Hash;
            string result = Convert.ToBase64String(varResult);

            Assert.AreEqual(nativeResult, result);

        }
 /// <summary>
 /// Initializes a new instance of the BlobWriteStreamBase class.
 /// </summary>
 /// <param name="serviceClient">The service client.</param>        
 /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the condition that must be met in order for the request to proceed. If <c>null</c>, no condition is used.</param>
 /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param>
 /// <param name="operationContext">An <see cref="OperationContext"/> object that represents the context for the current operation.</param>
 private BlobWriteStreamBase(CloudBlobClient serviceClient, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
     : base()
 {
     this.internalBuffer = new MultiBufferMemoryStream(serviceClient.BufferManager);
     this.accessCondition = accessCondition;
     this.currentOffset = 0;
     this.options = options;
     this.operationContext = operationContext;
     this.noPendingWritesEvent = new CounterEvent();
     this.blobMD5 = this.options.StoreBlobContentMD5.Value ? new MD5Wrapper() : null;
     this.blockMD5 = this.options.UseTransactionalMD5.Value ? new MD5Wrapper() : null;
     this.parallelOperationSemaphore = new AsyncSemaphore(options.ParallelOperationThreadCount.Value);
     this.lastException = null;
     this.committed = false;
     this.disposed = false;
 }
예제 #18
0
        /// <summary>
        /// Initializes a new instance of the BlobReadStreamBase class.
        /// </summary>
        /// <param name="blob">Blob reference to read from</param>
        /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the condition that must be met in order for the request to proceed. If <c>null</c>, no condition is used.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param>
        /// <param name="operationContext">An <see cref="OperationContext"/> object that represents the context for the current operation.</param>
        protected BlobReadStreamBase(CloudBlob blob, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
        {
            if (options.UseTransactionalMD5.Value)
            {
                CommonUtility.AssertInBounds("StreamMinimumReadSizeInBytes", blob.StreamMinimumReadSizeInBytes, 1, Constants.MaxRangeGetContentMD5Size);
            }

            this.blob           = blob;
            this.blobProperties = new BlobProperties(blob.Properties);
            this.currentOffset  = 0;
            this.streamMinimumReadSizeInBytes = this.blob.StreamMinimumReadSizeInBytes;
            this.internalBuffer   = new MultiBufferMemoryStream(blob.ServiceClient.BufferManager);
            this.accessCondition  = accessCondition;
            this.options          = options;
            this.operationContext = operationContext;
            this.blobMD5          = (this.options.DisableContentMD5Validation.Value || string.IsNullOrEmpty(this.blobProperties.ContentMD5)) ? null : new MD5Wrapper();
            this.lastException    = null;
        }
        /// <summary>
        /// Initializes a new instance of the BlobReadStreamBase class.
        /// </summary>
        /// <param name="blob">Blob reference to read from</param>
        /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the condition that must be met in order for the request to proceed. If <c>null</c>, no condition is used.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param>
        /// <param name="operationContext">An <see cref="OperationContext"/> object that represents the context for the current operation.</param>
        protected BlobReadStreamBase(CloudBlob blob, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
        {
            if (options.UseTransactionalMD5.Value)
            {
                CommonUtility.AssertInBounds("StreamMinimumReadSizeInBytes", blob.StreamMinimumReadSizeInBytes, 1, Constants.MaxRangeGetContentMD5Size);
            }

            this.blob = blob;
            this.blobProperties = new BlobProperties(blob.Properties);
            this.currentOffset = 0;
            this.streamMinimumReadSizeInBytes = this.blob.StreamMinimumReadSizeInBytes;
            this.internalBuffer = new MultiBufferMemoryStream(blob.ServiceClient.BufferManager);
            this.accessCondition = accessCondition;
            this.options = options;
            this.operationContext = operationContext;
            this.blobMD5 = (this.options.DisableContentMD5Validation.Value || string.IsNullOrEmpty(this.blobProperties.ContentMD5)) ? null : new MD5Wrapper();
            this.lastException = null;
        }
예제 #20
0
        /// <summary>
        /// Processes list of levels and returns its string representation ready to be sent to client.
        /// </summary>
        /// <param name="levels">List of LevelRowDTO.</param>
        /// <returns></returns>
        public static String GetLevelListString(this IList <LevelRowDTO> levels)
        {
            if (!levels.Any())
            {
                return(String.Empty);
            }

            StringBuilder sb = new StringBuilder();

            for (Int32 i = 0; i < levels.Count; i++)
            {
                LevelRowDTO current = levels[i];

                // TODO - Rewrite this shit. Use dictionary or something.
                // Yes, I know that string interpolation exists, but I dont like it.
                sb.AppendFormat(
                    "levelID{0}={1}&version{0}={2}&title{0}={3}&rating{0}={4}&playCount{0}={5}&minLevel{0}={6}&note{0}={7}&userName{0}={8}&group{0}={9}&live{0}={10}&pass{0}={11}&type{0}={12}{13}",
                    i,
                    current.LevelId,
                    current.Version,
                    current.Title.ToUrlEncodedString(),
                    current.Rating.ToString(StringFormat.DECIMAL_TWO, CultureInfo.InvariantCulture) ?? String.Empty,
                    current.PlayCount,
                    current.MinRank,
                    current.Note.ToUrlEncodedString(),
                    current.Username.ToUrlEncodedString(),
                    current.Group,
                    Convert.ToInt32(current.IsPublished),
                    current.HasPass ? StatusMessages.ONE : String.Empty,
                    current.GameMode.GetEnumDescription().FirstOrDefault() + String.Empty,
                    (i < levels.Count - 1) ? Separators.AMPERSAND : String.Empty);
            }

            using (MD5Wrapper md5 = new MD5Wrapper())
            {
                String hash = md5.GetHashedString(String.Concat(sb.ToString(), Pepper.LEVEL_LIST));
                sb.Append(String.Concat("&hash=", hash));
            }

            return(sb.ToString());
        }
 /// <summary>
 /// Initializes a new instance of the FileWriteStreamBase class for a file.
 /// </summary>
 /// <param name="file">File reference to write to.</param>
 /// <param name="fileSize">Size of the file.</param>
 /// <param name="createNew">Use <c>true</c> if the file is newly created, <c>false</c> otherwise.</param>
 /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the file. If <c>null</c>, no condition is used.</param>
 /// <param name="options">An <see cref="FileRequestOptions"/> object that specifies additional options for the request.</param>
 /// <param name="operationContext">An <see cref="OperationContext"/> object for tracking the current operation.</param>
 protected FileWriteStreamBase(CloudFile file, long fileSize, bool createNew, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext)
     : base()
 {
     this.internalBuffer = new MultiBufferMemoryStream(file.ServiceClient.BufferManager);
     this.currentOffset = 0;
     this.accessCondition = accessCondition;
     this.options = options;
     this.operationContext = operationContext;
     this.noPendingWritesEvent = new CounterEvent();
     this.fileMD5 = this.options.StoreFileContentMD5.Value ? new MD5Wrapper() : null;
     this.rangeMD5 = this.options.UseTransactionalMD5.Value ? new MD5Wrapper() : null;
     this.parallelOperationSemaphore = new AsyncSemaphore(options.ParallelOperationThreadCount.Value);
     this.lastException = null;
     this.committed = false;
     this.disposed = false;
     this.currentFileOffset = 0;
     this.file = file;
     this.fileSize = fileSize;
     this.streamWriteSizeInBytes = file.StreamWriteSizeInBytes;
     this.newFile = createNew;
 }
예제 #22
0
        /// <summary>
        /// Updates the blob MD5 with newly downloaded content.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        protected void VerifyBlobMD5(byte[] buffer, int offset, int count)
        {
            if ((this.blobMD5 != null) && (this.lastException == null))
            {
                this.blobMD5.UpdateHash(buffer, offset, count);

                if ((this.currentOffset == this.Length) &&
                    !string.IsNullOrEmpty(this.blob.Properties.ContentMD5))
                {
                    string computedMD5 = this.blobMD5.ComputeHash();
                    this.blobMD5 = null;
                    if (!computedMD5.Equals(this.blob.Properties.ContentMD5))
                    {
                        this.lastException = new IOException(string.Format(
                                                                 SR.BlobDataCorrupted,
                                                                 this.blob.Properties.ContentMD5,
                                                                 computedMD5));
                    }
                }
            }
        }
예제 #23
0
        /// <summary>
        /// Computes the hash value for this stream.
        /// </summary>
        /// <returns>String representation of the computed hash value.</returns>
        public string ComputeMD5Hash()
        {
            using (MD5Wrapper md5 = new MD5Wrapper())
            {
                // Maximum amount you can read is from current spot to the end.
                long leftToRead = this.Length - this.Position;

                while (leftToRead != 0)
                {
                    ArraySegment <byte> currentBlock = this.GetCurrentBlock();

                    // Update hash with the block
                    int blockReadLength = (int)Math.Min(leftToRead, currentBlock.Count);
                    md5.UpdateHash(currentBlock.Array, currentBlock.Offset, blockReadLength);

                    this.AdvancePosition(ref leftToRead, blockReadLength);
                }

                return(md5.ComputeHash());
            }
        }
예제 #24
0
        /// <summary>
        /// Sets the position within the current stream.
        /// </summary>
        /// <param name="offset">A byte offset relative to the origin parameter.</param>
        /// <param name="origin">A value of type <c>SeekOrigin</c> indicating the reference
        /// point used to obtain the new position.</param>
        /// <returns>The new position within the current stream.</returns>
        public override long Seek(long offset, SeekOrigin origin)
        {
            if (this.lastException != null)
            {
                throw this.lastException;
            }

            long newOffset;

            switch (origin)
            {
            case SeekOrigin.Begin:
                newOffset = offset;
                break;

            case SeekOrigin.Current:
                newOffset = this.currentOffset + offset;
                break;

            case SeekOrigin.End:
                newOffset = this.Length + offset;
                break;

            default:
                CommonUtils.ArgumentOutOfRange("origin", origin);
                throw new ArgumentOutOfRangeException();
            }

            CommonUtils.AssertInBounds("offset", newOffset, 0, this.Length);

            if (newOffset != this.currentOffset)
            {
                this.blobMD5 = null;
                this.buffer.SetLength(0);
                this.currentOffset = newOffset;
            }

            return(this.currentOffset);
        }
예제 #25
0
        /// <summary>
        /// Updates the file MD5 with newly downloaded content.
        /// </summary>
        /// <param name="buffer">The buffer to read the data from.</param>
        /// <param name="offset">The byte offset in buffer at which to begin reading data.</param>
        /// <param name="count">The maximum number of bytes to read.</param>
        protected void VerifyFileMD5(byte[] buffer, int offset, int count)
        {
            if ((this.fileMD5 != null) && (this.lastException == null) && (count > 0))
            {
                this.fileMD5.UpdateHash(buffer, offset, count);

                if ((this.currentOffset == this.Length) &&
                    !string.IsNullOrEmpty(this.fileProperties.ContentMD5))
                {
                    string computedMD5 = this.fileMD5.ComputeHash();
                    this.fileMD5.Dispose();
                    this.fileMD5 = null;

                    if (!computedMD5.Equals(this.fileProperties.ContentMD5))
                    {
                        this.lastException = new IOException(string.Format(
                                                                 CultureInfo.InvariantCulture,
                                                                 SR.FileDataCorrupted,
                                                                 this.fileProperties.ContentMD5,
                                                                 computedMD5));
                    }
                }
            }
        }
예제 #26
0
        /// <summary>
        /// Verify and redownload any missing/old files
        /// </summary>
        /// <param name="clientDirectory">The pso2_dir directory</param>
        /// <param name="version">Specify the version</param>
        /// <param name="filelist">Specify the patchlist to check and download</param>
        /// <param name="options">Provide the options for current download sessions</param>
        public async Task VerifyAndDownloadAsync(string clientDirectory, ClientVersionCheckResult version, RemotePatchlist filelist, ClientUpdateOptions options)
        {
            ConcurrentDictionary <PSO2File, Exception> failedfiles = new ConcurrentDictionary <PSO2File, Exception>();

            int currentprogress = 0, downloadedfiles = 0;

            CancellationTokenSource totalCancelSource = new CancellationTokenSource();

            options.ParallelOptions.CancellationToken = totalCancelSource.Token;

            //*
            options.ParallelOptions.CancellationToken.Register(() =>
            {
                if (options.ChecksumCache != null && downloadedfiles > 0)
                {
                    this.StepChanged?.Invoke(UpdateStep.WriteCache, options.ChecksumCache);
                    options.ChecksumCache.WriteChecksumCache(version.LatestVersion);
                }
                options.Dispose();
                this.UpdateCompleted?.Invoke(new PSO2NotifyEventArgs(true, clientDirectory, new ReadOnlyDictionary <PSO2File, Exception>(failedfiles)));
            });
            //*/

            this.cancelBag.Add(totalCancelSource);

            this.StepChanged.Invoke(UpdateStep.BeginFileCheckAndDownload, null);

            if (options.ChecksumCache == null)
            {
                options.Profile = UpdaterProfile.PreferAccuracy;
            }
            else
            {
                options.ChecksumCache.ReadChecksumCache();
            }

            ConcurrentBag <PSO2File> pso2fileBag = new ConcurrentBag <PSO2File>(filelist.Values);
            Func <Task> actionV;

            switch (options.Profile)
            {
            case UpdaterProfile.PreferAccuracy:
                actionV = new Func <Task>(async() =>
                {
                    PSO2File pso2file;
                    while (!totalCancelSource.IsCancellationRequested && pso2fileBag.TryTake(out pso2file))
                    {
                        string fullpath = Path.Combine(clientDirectory, pso2file.WindowFilename);
                        try
                        {
                            if (string.Equals(pso2file.SafeFilename, DefaultValues.CensorFilename, StringComparison.OrdinalIgnoreCase))
                            {
                                if (File.Exists(fullpath))
                                {
                                    string md5fromfile = MD5Wrapper.HashFromFile(fullpath);
                                    if (!string.Equals(md5fromfile, pso2file.MD5Hash, StringComparison.OrdinalIgnoreCase))
                                    {
                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);
                                        using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                            try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                        File.Delete(fullpath);
                                        File.Move(fullpath + ".dtmp", fullpath);
                                        Interlocked.Increment(ref downloadedfiles);
                                        if (options.ChecksumCache != null)
                                        {
                                            ChecksumCache.PSO2FileChecksum newchecksum = ChecksumCache.PSO2FileChecksum.FromFile(clientDirectory, fullpath);
                                            options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                        }
                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                    }
                                    else
                                    {
                                        if (!options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                        {
                                            ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, pso2file.Length, pso2file.MD5Hash);
                                            options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                            Interlocked.Increment(ref downloadedfiles);
                                        }
                                    }
                                }
                                else
                                {
                                    fullpath = Path.Combine(clientDirectory, pso2file.WindowFilename + ".backup");
                                    if (File.Exists(fullpath))
                                    {
                                        string md5fromfile = MD5Wrapper.HashFromFile(fullpath);
                                        if (!string.Equals(md5fromfile, pso2file.MD5Hash, StringComparison.OrdinalIgnoreCase))
                                        {
                                            this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                            using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                                try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                            File.Delete(fullpath);
                                            File.Move(fullpath + ".dtmp", fullpath);
                                            Interlocked.Increment(ref downloadedfiles);
                                            if (options.ChecksumCache != null)
                                            {
                                                ChecksumCache.PSO2FileChecksum newchecksum = ChecksumCache.PSO2FileChecksum.FromFile(clientDirectory, fullpath);
                                                options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                            }

                                            this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                        }
                                        else
                                        {
                                            if (!options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                            {
                                                ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, pso2file.Length, pso2file.MD5Hash);
                                                options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                                Interlocked.Increment(ref downloadedfiles);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (File.Exists(fullpath))
                                {
                                    string md5fromfile = MD5Wrapper.HashFromFile(fullpath);
                                    if (!string.Equals(md5fromfile, pso2file.MD5Hash, StringComparison.OrdinalIgnoreCase))
                                    {
                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                        using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                            try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                        File.Delete(fullpath);
                                        File.Move(fullpath + ".dtmp", fullpath);
                                        Interlocked.Increment(ref downloadedfiles);
                                        if (options.ChecksumCache != null)
                                        {
                                            ChecksumCache.PSO2FileChecksum newchecksum = ChecksumCache.PSO2FileChecksum.FromFile(clientDirectory, fullpath);
                                            options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                        }
                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                    }
                                    else
                                    {
                                        if (!options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                        {
                                            ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, pso2file.Length, pso2file.MD5Hash);
                                            options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                            Interlocked.Increment(ref downloadedfiles);
                                        }
                                    }
                                }
                                else
                                {
                                    this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                    using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                        try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                    File.Delete(fullpath);
                                    File.Move(fullpath + ".dtmp", fullpath);
                                    Interlocked.Increment(ref downloadedfiles);
                                    if (options.ChecksumCache != null)
                                    {
                                        ChecksumCache.PSO2FileChecksum newchecksum = ChecksumCache.PSO2FileChecksum.FromFile(clientDirectory, fullpath);
                                        options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                    }
                                    this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                }
                            }
                        }
#if !DEBUG
                        catch (Exception ex)
                        {
                            failedfiles.TryAdd(pso2file, ex);
                        }
#endif
                        finally
                        {
                            try { File.Delete(fullpath + ".dtmp"); } catch { }
                            Interlocked.Increment(ref currentprogress);
                            this.ProgressChanged?.Invoke(currentprogress, filelist.Count);
                        }
                    }
                });
                break;

            case UpdaterProfile.PreferSpeed:
                actionV = new Func <Task>(async() =>
                {
                    PSO2File pso2file;
                    while (!totalCancelSource.IsCancellationRequested && pso2fileBag.TryTake(out pso2file))
                    {
                        string fullpath = Path.Combine(clientDirectory, pso2file.WindowFilename);
                        try
                        {
                            if (!string.Equals(pso2file.SafeFilename, DefaultValues.CensorFilename, StringComparison.OrdinalIgnoreCase))
                            {
                                if (options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                {
                                    if (!string.Equals(options.ChecksumCache.ChecksumList[pso2file.Filename].MD5, pso2file.MD5Hash, StringComparison.OrdinalIgnoreCase))
                                    {
                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                        using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                            try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                        File.Delete(fullpath);
                                        File.Move(fullpath + ".dtmp", fullpath);
                                        Interlocked.Increment(ref downloadedfiles);
                                        ChecksumCache.PSO2FileChecksum newchecksum = ChecksumCache.PSO2FileChecksum.FromFile(clientDirectory, fullpath);
                                        options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));

                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                    }
                                }
                                else
                                {
                                    this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                    using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                        try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                    File.Delete(fullpath);
                                    File.Move(fullpath + ".dtmp", fullpath);
                                    Interlocked.Increment(ref downloadedfiles);
                                    ChecksumCache.PSO2FileChecksum newchecksum = ChecksumCache.PSO2FileChecksum.FromFile(clientDirectory, fullpath);
                                    options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));

                                    this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                }
                            }
                        }
#if !DEBUG
                        catch (Exception ex)
                        {
                            failedfiles.TryAdd(pso2file, ex);
                        }
#endif
                        finally
                        {
                            try { File.Delete(fullpath + ".dtmp"); } catch { }
                            Interlocked.Increment(ref currentprogress);
                            this.ProgressChanged?.Invoke(currentprogress, filelist.Count);
                        }
                    }
                });
                break;

            default:
                actionV = new Func <Task>(async() =>
                {
                    PSO2File pso2file;
                    while (!totalCancelSource.IsCancellationRequested && pso2fileBag.TryTake(out pso2file))
                    {
                        string fullpath = Path.Combine(clientDirectory, pso2file.WindowFilename);
                        try
                        {
                            if (string.Equals(pso2file.SafeFilename, DefaultValues.CensorFilename, StringComparison.OrdinalIgnoreCase))
                            {
                                if (File.Exists(fullpath))
                                {
                                    string md5fromfile = null;
                                    if (options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                    {
                                        var checksumfile = options.ChecksumCache.ChecksumList[pso2file.Filename];
                                        using (FileStream fs = File.OpenRead(fullpath))
                                            if (fs.Length == checksumfile.FileSize)
                                            {
                                                md5fromfile = checksumfile.MD5;
                                            }
                                    }
                                    if (string.IsNullOrEmpty(md5fromfile))
                                    {
                                        md5fromfile = MD5Wrapper.HashFromFile(fullpath);
                                    }

                                    if (!string.Equals(md5fromfile, pso2file.MD5Hash, StringComparison.OrdinalIgnoreCase))
                                    {
                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                        using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                        {
                                            try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                            ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, fs.Length, pso2file.MD5Hash);
                                            options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                        }
                                        File.Delete(fullpath);
                                        File.Move(fullpath + ".dtmp", fullpath);
                                        Interlocked.Increment(ref downloadedfiles);

                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                    }
                                    else
                                    {
                                        if (!options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                        {
                                            ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, pso2file.Length, pso2file.MD5Hash);
                                            options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                            Interlocked.Increment(ref downloadedfiles);
                                        }
                                    }
                                }
                                else
                                {
                                    fullpath = Path.Combine(clientDirectory, pso2file.Filename + ".backup");
                                    if (File.Exists(fullpath))
                                    {
                                        string md5fromfile = null;
                                        if (options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                        {
                                            var checksumfile = options.ChecksumCache.ChecksumList[pso2file.Filename];
                                            using (FileStream fs = File.OpenRead(fullpath))
                                                if (fs.Length == checksumfile.FileSize)
                                                {
                                                    md5fromfile = checksumfile.MD5;
                                                }
                                        }
                                        if (string.IsNullOrEmpty(md5fromfile))
                                        {
                                            md5fromfile = MD5Wrapper.HashFromFile(fullpath);
                                        }

                                        if (!string.Equals(md5fromfile, pso2file.MD5Hash, StringComparison.OrdinalIgnoreCase))
                                        {
                                            this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                            using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                            {
                                                try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                                ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, fs.Length, pso2file.MD5Hash);
                                                options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                            }
                                            File.Delete(fullpath);
                                            File.Move(fullpath + ".dtmp", fullpath);
                                            Interlocked.Increment(ref downloadedfiles);

                                            this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                        }
                                        else
                                        {
                                            if (!options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                            {
                                                ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, pso2file.Length, pso2file.MD5Hash);
                                                options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                                Interlocked.Increment(ref downloadedfiles);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (File.Exists(fullpath))
                                {
                                    string md5fromfile = null;
                                    if (options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                    {
                                        var checksumfile = options.ChecksumCache.ChecksumList[pso2file.Filename];
                                        using (FileStream fs = File.OpenRead(fullpath))
                                            if (fs.Length == checksumfile.FileSize)
                                            {
                                                md5fromfile = checksumfile.MD5;
                                            }
                                    }
                                    if (string.IsNullOrEmpty(md5fromfile))
                                    {
                                        md5fromfile = MD5Wrapper.HashFromFile(fullpath);
                                    }

                                    if (!string.Equals(md5fromfile, pso2file.MD5Hash, StringComparison.OrdinalIgnoreCase))
                                    {
                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                        using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                        {
                                            try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                            ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, fs.Length, pso2file.MD5Hash);
                                            options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                        }
                                        File.Delete(fullpath);
                                        File.Move(fullpath + ".dtmp", fullpath);
                                        Interlocked.Increment(ref downloadedfiles);

                                        this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                    }
                                    else
                                    {
                                        if (!options.ChecksumCache.ChecksumList.ContainsKey(pso2file.Filename))
                                        {
                                            ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, pso2file.Length, pso2file.MD5Hash);
                                            options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                            Interlocked.Increment(ref downloadedfiles);
                                        }
                                    }
                                }
                                else
                                {
                                    this.StepChanged?.Invoke(UpdateStep.DownloadingFileStart, pso2file);

                                    using (FileStream fs = File.Create(fullpath + ".dtmp"))
                                    {
                                        try { await this.DownloadFileAsync(pso2file, fs, totalCancelSource); } catch (TaskCanceledException) { }
                                        ChecksumCache.PSO2FileChecksum newchecksum = new ChecksumCache.PSO2FileChecksum(pso2file.Filename, fs.Length, pso2file.MD5Hash);
                                        options.ChecksumCache.ChecksumList.AddOrUpdate(pso2file.Filename, newchecksum, new Func <string, ChecksumCache.PSO2FileChecksum, ChecksumCache.PSO2FileChecksum>((key, oldval) => { return(newchecksum); }));
                                    }
                                    File.Delete(fullpath);
                                    File.Move(fullpath + ".dtmp", fullpath);
                                    Interlocked.Increment(ref downloadedfiles);

                                    this.StepChanged?.Invoke(UpdateStep.DownloadingFileEnd, pso2file);
                                }
                            }
                        }
#if !DEBUG
                        catch (Exception ex)
                        {
                            failedfiles.TryAdd(pso2file, ex);
                        }
#endif
                        finally
                        {
                            try { File.Delete(fullpath + ".dtmp"); } catch { }
                            Interlocked.Increment(ref currentprogress);
                            this.ProgressChanged?.Invoke(currentprogress, filelist.Count);
                        }
                    }
                });
                break;
            }

            try
            {
                Task[] tasks = new Task[options.ParallelOptions.MaxDegreeOfParallelism];
                for (int i = 0; i < tasks.Length; i++)
                {
                    tasks[i] = Task.Factory.StartNew(actionV, TaskCreationOptions.LongRunning).Unwrap();
                }
                await Task.WhenAll(tasks);

                if (options.ChecksumCache != null && downloadedfiles > 0)
                {
                    this.StepChanged?.Invoke(UpdateStep.WriteCache, options.ChecksumCache);
                    options.ChecksumCache.WriteChecksumCache(version.LatestVersion);
                }
                options.Dispose();
                if (!totalCancelSource.IsCancellationRequested)
                {
                    if (failedfiles.Count < 4)
                    {
                        Settings.VersionString = version.LatestVersion;
                    }
                    this.UpdateCompleted?.Invoke(new PSO2NotifyEventArgs(version.LatestVersion, clientDirectory, new ReadOnlyDictionary <PSO2File, Exception>(failedfiles)));
                }
                else
                {
                    this.UpdateCompleted?.Invoke(new PSO2NotifyEventArgs(true, clientDirectory, new ReadOnlyDictionary <PSO2File, Exception>(failedfiles)));
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception)
            {
                if (options.ChecksumCache != null && downloadedfiles > 0)
                {
                    this.StepChanged?.Invoke(UpdateStep.WriteCache, options.ChecksumCache);
                    options.ChecksumCache.WriteChecksumCache(version.LatestVersion);
                }
                options.Dispose();
                throw;
            }
        }
예제 #27
0
 public static string StringToMD5(string source)
 {
     return(MD5Wrapper.FromString(source));
 }
예제 #28
0
 public static string FileToMD5Hash(string filepath)
 {
     return(MD5Wrapper.FromFile(filepath));
 }
        /// <summary>
        /// Sets the position within the current stream.
        /// </summary>
        /// <param name="offset">A byte offset relative to the origin parameter.</param>
        /// <param name="origin">A value of type <c>SeekOrigin</c> indicating the reference
        /// point used to obtain the new position.</param>
        /// <returns>The new position within the current stream.</returns>
        /// <remarks>Seeking in a BlobReadStream disables MD5 validation.</remarks>
        public override long Seek(long offset, SeekOrigin origin)
        {
            if (this.lastException != null)
            {
                throw this.lastException;
            }

            long newOffset;
            switch (origin)
            {
                case SeekOrigin.Begin:
                    newOffset = offset;
                    break;

                case SeekOrigin.Current:
                    newOffset = this.currentOffset + offset;
                    break;

                case SeekOrigin.End:
                    newOffset = this.Length + offset;
                    break;

                default:
                    CommonUtility.ArgumentOutOfRange("origin", origin);
                    throw new ArgumentOutOfRangeException("origin");
            }

            CommonUtility.AssertInBounds("offset", newOffset, 0, this.Length);

            if (newOffset != this.currentOffset)
            {
                long bufferOffset = this.internalBuffer.Position + (newOffset - this.currentOffset);
                if ((bufferOffset >= 0) && (bufferOffset < this.internalBuffer.Length))
                {
                    this.internalBuffer.Position = bufferOffset;
                }
                else
                {
                    this.internalBuffer.SetLength(0);
                }

                this.blobMD5 = null;
                this.currentOffset = newOffset;
            }

            return this.currentOffset;
        }
        /// <summary>
        /// Releases the blob resources used by the Stream.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.internalBuffer != null)
                {
                    this.internalBuffer.Dispose();
                    this.internalBuffer = null;
                }

                if (this.blobMD5 != null)
                {
                    this.blobMD5.Dispose();
                    this.blobMD5 = null;
                }
            }

            base.Dispose(disposing);
        }
예제 #31
0
        /// <summary>
        /// Uploads the block list.
        /// </summary>
        /// <param name="blocks">The blocks to upload.</param>
        /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand{T}"/> that uploads the block list.</returns>
        internal RESTCommand<NullType> PutBlockListImpl(IEnumerable<PutBlockListItem> blocks, AccessCondition accessCondition, BlobRequestOptions options)
        {
            MemoryStream memoryStream = new MemoryStream();
            BlobRequest.WriteBlockListBody(blocks, memoryStream);
            memoryStream.Seek(0, SeekOrigin.Begin);

            string contentMD5;
            using (MD5Wrapper md5 = new MD5Wrapper())
            {
                contentMD5 = md5.ComputeHash(memoryStream);
            }

            memoryStream.Seek(0, SeekOrigin.Begin);

            RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.Uri);

            putCmd.ApplyRequestOptions(options);
            putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.PutBlockList(uri, serverTimeout, this.Properties, accessCondition, ctx);
            putCmd.SetHeaders = (r, ctx) =>
            {
                r.Headers.Set(HttpRequestHeader.ContentMd5, contentMD5);
                BlobHttpWebRequestFactory.AddMetadata(r, this.Metadata);
            };
            putCmd.SendStream = memoryStream;
            putCmd.RecoveryAction = RecoveryActions.RewindStream;
            putCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest;
            putCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex, ctx);
                CloudBlobSharedImpl.ParseSizeAndLastModified(this.attributes, resp);
                this.Properties.Length = 0;
                return NullType.Value;
            };

            return putCmd;
        }
예제 #32
0
        public void SaveLevel(Int64 userId, String username, LevelDataDTO levelData, String ipAddress)
        {
            // TODO - Validation of level data.
            // TODO - Consider the difference based approach when saving levels.

            if (levelData == null)
            {
                throw new PR2Exception(ErrorMessages.ERR_NO_LEVEL_DATA);
            }
            else if (String.IsNullOrEmpty(levelData.Title))
            {
                throw new PR2Exception(ErrorMessages.ERR_NO_LEVEL_TITLE);
            }
            else if (levelData.GameMode == GameMode.Unknown)
            {
                throw new PR2Exception(ErrorMessages.ERR_INVALID_GAME_MODE);
            }
            else if (!String.IsNullOrEmpty(levelData.Items) &&
                     !Regex.IsMatch(levelData.Items, ValidationConstraints.LEVEL_ITEMS_PATTERN))
            {
                throw new PR2Exception(ErrorMessages.ERR_INVALID_ITEMS);
            }

            using (MD5Wrapper md5 = new MD5Wrapper())
            {
                String hash = md5.GetHashedString(
                    String.Concat(levelData.Title, username?.ToLower() ?? String.Empty, levelData.Data, Pepper.LEVEL_SAVE));

                if (String.CompareOrdinal(hash, levelData.Hash) != 0)
                {
                    throw new PR2Exception(ErrorMessages.ERR_LEVEL_DATA_HASH_MISMATCH);
                }
            }

            DateTime     utcDateMinus1min = DateTime.UtcNow.AddMinutes(-1); // To prevent usage of SQL functions.
            LevelVersion lastSaved        = this.dbContext.LevelVersions
                                            .Where(v => v.Level != null && v.Level.AuthorId == userId && DateTime.Compare(v.SubmittedDate, utcDateMinus1min) > 0)
                                            .OrderByDescending(v => v.SubmittedDate).FirstOrDefault();

            if (lastSaved != null)
            {
                throw new PR2Exception(String.Format(
                                           ErrorMessages.ERR_WAIT_BEFORE_SAVING,
                                           Math.Round(TimeSpan.FromMinutes(1).Subtract(DateTime.UtcNow.Subtract(lastSaved.SubmittedDate.ToUniversalTime())).TotalSeconds)));
            }

            Level level = this.dbContext.Levels.FirstOrDefault(l => l.AuthorId == userId && l.Title == levelData.Title);

            if (level == null)
            {
                level = new Level
                {
                    AuthorId  = userId,
                    Title     = levelData.Title,
                    IsDeleted = false
                };

                this.dbContext.Levels.Add(level);
            }

            level.IsPublished = levelData.Live;

            this.dbContext.LevelVersions.Add(new LevelVersion
            {
                Level         = level,
                SubmittedDate = DateTime.UtcNow,
                SubmittedIP   = ipAddress,
                Note          = levelData.Note,
                GameMode      = levelData.GameMode,
                MinRank       = levelData.MinLevel,
                CowboyChance  = levelData.CowboyChance,
                Gravity       = levelData.Gravity,
                Song          = levelData.Song,
                MaxTime       = levelData.MaxTime,
                Items         = levelData.Items,
                Data          = levelData.Data,
                PassHash      = levelData.PassHash
            });

            this.dbContext.SaveChanges();
        }
        /// <summary>
        /// Sets the position within the current stream.
        /// </summary>
        /// <param name="offset">A byte offset relative to the origin parameter.</param>
        /// <param name="origin">A value of type <c>SeekOrigin</c> indicating the reference
        /// point used to obtain the new position.</param>
        /// <returns>The new position within the current stream.</returns>
        public override long Seek(long offset, SeekOrigin origin)
        {
            if (this.lastException != null)
            {
                throw this.lastException;
            }

            long newOffset;
            switch (origin)
            {
                case SeekOrigin.Begin:
                    newOffset = offset;
                    break;

                case SeekOrigin.Current:
                    newOffset = this.currentOffset + offset;
                    break;

                case SeekOrigin.End:
                    newOffset = this.Length + offset;
                    break;

                default:
                    CommonUtils.ArgumentOutOfRange("origin", origin);
                    throw new ArgumentOutOfRangeException();
            }

            CommonUtils.AssertInBounds("offset", newOffset, 0, this.Length);

            if (newOffset != this.currentOffset)
            {
                this.blobMD5 = null;
                this.buffer.SetLength(0);
                this.currentOffset = newOffset;
            }

            return this.currentOffset;
        }
        /// <summary>
        /// Computes the hash value for this stream.
        /// </summary>
        /// <returns>String representation of the computed hash value.</returns>
        public string ComputeMD5Hash()
        {
            using (MD5Wrapper md5 = new MD5Wrapper())
            {
                // Maximum amount you can read is from current spot to the end.
                long leftToRead = this.Length - this.Position;

                while (leftToRead != 0)
                {
                    ArraySegment<byte> currentBlock = this.GetCurrentBlock();

                    // Update hash with the block
                    int blockReadLength = (int)Math.Min(leftToRead, currentBlock.Count);
                    md5.UpdateHash(currentBlock.Array, currentBlock.Offset, blockReadLength);

                    this.AdvancePosition(ref leftToRead, blockReadLength);
                }

                return md5.ComputeHash();
            }
        }
        public void MD5LastByteTest()
        {
            CloudStorageAccount.UseV1MD5 = false;
            try
            {
                using (MD5Wrapper nativeHash = new MD5Wrapper())
                {
                    nativeHash.UpdateHash(data, 8, 1);
                    string nativeResult = nativeHash.ComputeHash();


                    MD5 hash = MD5.Create();
                    hash.ComputeHash(data, 8, 1);
                    byte[] varResult = hash.Hash;
                    string result = Convert.ToBase64String(varResult);

                    Assert.AreEqual(nativeResult, result);
                }
            }
            finally
            {
                CloudStorageAccount.UseV1MD5 = true;
            }
        }
        /// <summary>
        /// Updates the blob MD5 with newly downloaded content.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        protected void VerifyBlobMD5(byte[] buffer, int offset, int count)
        {
            if ((this.blobMD5 != null) && (this.lastException == null))
            {
                this.blobMD5.UpdateHash(buffer, offset, count);

                if ((this.currentOffset == this.Length) &&
                    !string.IsNullOrEmpty(this.blob.Properties.ContentMD5))
                {
                    string computedMD5 = this.blobMD5.ComputeHash();
                    this.blobMD5 = null;
                    if (!computedMD5.Equals(this.blob.Properties.ContentMD5))
                    {
                        this.lastException = new IOException(string.Format(
                            SR.BlobDataCorrupted,
                            this.blob.Properties.ContentMD5,
                            computedMD5));
                    }
                }
            }
        }
        /// <summary>
        /// Releases the blob resources used by the Stream.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.blobMD5 != null)
                {
                    this.blobMD5.Dispose();
                    this.blobMD5 = null;
                }

                if (this.blockMD5 != null)
                {
                    this.blockMD5.Dispose();
                    this.blockMD5 = null;
                }

                if (this.internalBuffer != null)
                {
                    this.internalBuffer.Dispose();
                    this.internalBuffer = null;
                }
       
                if (this.noPendingWritesEvent != null)
                {
                    this.noPendingWritesEvent.Dispose();
                    this.noPendingWritesEvent = null;
                }
            }

            base.Dispose(disposing);
        }
예제 #38
0
        public void MD5BigDataTest()
        {
            byte[] data = new byte[10000];
            for (int i = 1; i < 10000; i++)
            {
                data[i] = 1;
            }

            using (MD5Wrapper nativeHash = new MD5Wrapper())
            {
                MD5 hash = MD5.Create();
                for (int i = 0; i < 999; i++)
                {
                    int index = 10 * i;
                    nativeHash.UpdateHash(data, 0, 10);
                    hash.TransformBlock(data, 0, 10, null, 0);
                }
                string nativeResult = nativeHash.ComputeHash();

                hash.TransformFinalBlock(new byte[0], 0, 0);
                var varResult = hash.Hash;
                String result = Convert.ToBase64String(varResult);

                Assert.AreEqual(nativeResult, result);
            }
        }
예제 #39
0
        /// <summary>
        /// Uploads the block list.
        /// </summary>
        /// <param name="blocks">The blocks to upload.</param>
        /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param>
        /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param>
        /// <returns>A <see cref="RESTCommand"/> that uploads the block list.</returns>
        internal RESTCommand<NullType> PutBlockListImpl(IEnumerable<PutBlockListItem> blocks, AccessCondition accessCondition, BlobRequestOptions options)
        {
            MemoryStream memoryStream = new MemoryStream();
            BlobRequest.WriteBlockListBody(blocks, memoryStream);
            memoryStream.Seek(0, SeekOrigin.Begin);

            string contentMD5;
            using (MD5Wrapper md5 = new MD5Wrapper())
            {
                contentMD5 = md5.ComputeHash(memoryStream);
            }

            RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.Uri);

            putCmd.ApplyRequestOptions(options);
            putCmd.Handler = this.ServiceClient.AuthenticationHandler;
            putCmd.BuildClient = HttpClientFactory.BuildHttpClient;
            putCmd.BuildContent = (cmd, ctx) => HttpContentFactory.BuildContentFromStream(memoryStream, 0, memoryStream.Length, contentMD5, cmd, ctx);
            putCmd.BuildRequest = (cmd, cnt, ctx) =>
            {
                HttpRequestMessage msg = BlobHttpRequestMessageFactory.PutBlockList(cmd.Uri, cmd.ServerTimeoutInSeconds, this.Properties, accessCondition, cnt, ctx);
                BlobHttpRequestMessageFactory.AddMetadata(msg, this.Metadata);
                return msg;
            };
            putCmd.PreProcessResponse = (cmd, resp, ex, ctx) =>
            {
                HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex, ctx);
                CloudBlobSharedImpl.ParseSizeAndLastModified(this.attributes, resp);
                this.Properties.Length = 0;
                return NullType.Value;
            };

            return putCmd;
        }
        /// <summary>
        /// Updates the file MD5 with newly downloaded content.
        /// </summary>
        /// <param name="buffer">The buffer to read the data from.</param>
        /// <param name="offset">The byte offset in buffer at which to begin reading data.</param>
        /// <param name="count">The maximum number of bytes to read.</param>
        protected void VerifyFileMD5(byte[] buffer, int offset, int count)
        {
            if ((this.fileMD5 != null) && (this.lastException == null) && (count > 0))
            {
                this.fileMD5.UpdateHash(buffer, offset, count);

                if ((this.currentOffset == this.Length) &&
                    !string.IsNullOrEmpty(this.fileProperties.ContentMD5))
                {
                    string computedMD5 = this.fileMD5.ComputeHash();
                    this.fileMD5.Dispose();
                    this.fileMD5 = null;

                    if (!computedMD5.Equals(this.fileProperties.ContentMD5))
                    {
                        this.lastException = new IOException(string.Format(
                            CultureInfo.InvariantCulture,
                            SR.FileDataCorrupted,
                            this.fileProperties.ContentMD5,
                            computedMD5));
                    }
                }
            }
        }
예제 #41
0
        public void MD5LastByteTest()
        {
            using (MD5Wrapper nativeHash = new MD5Wrapper())
            {
                nativeHash.UpdateHash(data, 8, 1);
                string nativeResult = nativeHash.ComputeHash();


                MD5 hash = MD5.Create();
                hash.ComputeHash(data, 8, 1);
                var varResult = hash.Hash;
                string result = Convert.ToBase64String(varResult);

                Assert.AreEqual(nativeResult, result);
            }
        }