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}¬e={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; } }
/// <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; }
/// <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); }
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; }
/// <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; }
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); }
/// <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); } }
/// <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; }
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 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> /// 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}¬e{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; }
/// <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> /// 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()); } }
/// <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> /// 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)); } } } }
/// <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; } }
public static string StringToMD5(string source) { return(MD5Wrapper.FromString(source)); }
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); }
/// <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; }
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> /// 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); }
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); } }
/// <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; }
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); } }