From e368b56d81b1f9b53348963a98996d9c6411b0c3 Mon Sep 17 00:00:00 2001 From: Sean McCullough Date: Tue, 28 Apr 2020 17:40:46 -0700 Subject: [PATCH 1/4] Fixed storage bug where blob, file, and directory names were not url encoded --- .../Azure.Storage.Blobs/src/BlobUriBuilder.cs | 4 +-- .../tests/BlobBaseClientTests.cs | 22 ++++++++++++++++ .../src/ShareUriBuilder.cs | 2 +- .../tests/DirectoryClientTests.cs | 22 ++++++++++++++++ .../tests/FileClientTests.cs | 25 +++++++++++++++++++ .../tests/FileTestBase.cs | 2 +- 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/sdk/storage/Azure.Storage.Blobs/src/BlobUriBuilder.cs b/sdk/storage/Azure.Storage.Blobs/src/BlobUriBuilder.cs index 4b19c2c31a5d..26aeec1d767a 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/BlobUriBuilder.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/BlobUriBuilder.cs @@ -285,9 +285,9 @@ private RequestUriBuilder BuildUri() if (!string.IsNullOrWhiteSpace(BlobContainerName)) { path.Append("/").Append(BlobContainerName); - if (!String.IsNullOrWhiteSpace(BlobName)) + if (!string.IsNullOrWhiteSpace(BlobName)) { - path.Append("/").Append(BlobName); + path.Append("/").Append(Uri.EscapeDataString(BlobName)); } } diff --git a/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs b/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs index febc5c99ac91..044761bbc24b 100644 --- a/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs +++ b/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs @@ -61,6 +61,28 @@ public void Ctor_ConnectionString() Assert.AreEqual("accountName", builder2.AccountName); } + [Test] + [Ignore("Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, so we can't pass connection string validation")] + public async Task Ctor_ConnectionStringEscapeBlobName() + { + // Arrange + await using DisposingContainer test = await GetTestContainerAsync(); + string blobName = "!*'();[]:@&%=+$,/?#"; + + BlockBlobClient initalBlob = InstrumentClient(test.Container.GetBlockBlobClient(blobName)); + var data = GetRandomBuffer(Constants.KB); + + using var stream = new MemoryStream(data); + Response uploadResponse = await initalBlob.UploadAsync(stream); + + // Act + BlobBaseClient blob = new BlobBaseClient(TestConfigDefault.ConnectionString, test.Container.Name, blobName, GetOptions()); + Response propertiesResponse = await blob.GetPropertiesAsync(); + + // Assert + Assert.AreEqual(uploadResponse.Value.ETag, propertiesResponse.Value.ETag); + } + [Test] public void Ctor_Uri() { diff --git a/sdk/storage/Azure.Storage.Files.Shares/src/ShareUriBuilder.cs b/sdk/storage/Azure.Storage.Files.Shares/src/ShareUriBuilder.cs index bbade2a9a437..96e07eb9bab8 100644 --- a/sdk/storage/Azure.Storage.Files.Shares/src/ShareUriBuilder.cs +++ b/sdk/storage/Azure.Storage.Files.Shares/src/ShareUriBuilder.cs @@ -279,7 +279,7 @@ private RequestUriBuilder BuildUri() path.Append("/").Append(ShareName); if (!string.IsNullOrWhiteSpace(DirectoryOrFilePath)) { - path.Append("/").Append(DirectoryOrFilePath); + path.Append("/").Append(Uri.EscapeDataString(DirectoryOrFilePath)); } } diff --git a/sdk/storage/Azure.Storage.Files.Shares/tests/DirectoryClientTests.cs b/sdk/storage/Azure.Storage.Files.Shares/tests/DirectoryClientTests.cs index 8d4f2c461801..851b720746ad 100644 --- a/sdk/storage/Azure.Storage.Files.Shares/tests/DirectoryClientTests.cs +++ b/sdk/storage/Azure.Storage.Files.Shares/tests/DirectoryClientTests.cs @@ -44,6 +44,28 @@ public void Ctor_ConnectionString() //Assert.AreEqual("accountName", builder.AccountName); } + [Test] + [Ignore("Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, so we can't pass connection string validation")] + public async Task Ctor_ConnectionStringEscapePath() + { + // Arrange + await using DisposingShare test = await GetTestShareAsync(); + string directoryName = "!#@&=;"; + ShareDirectoryClient initalDirectory = InstrumentClient(test.Share.GetDirectoryClient(directoryName)); + Response createResponse = await initalDirectory.CreateAsync(); + + // Act + ShareDirectoryClient directory = new ShareDirectoryClient( + TestConfigDefault.ConnectionString, + test.Share.Name, + directoryName, + GetOptions()); + Response propertiesResponse = await directory.GetPropertiesAsync(); + + // Assert + Assert.AreEqual(createResponse.Value.ETag, propertiesResponse.Value.ETag); + } + [Test] public void DirectoryPathsParsing() { diff --git a/sdk/storage/Azure.Storage.Files.Shares/tests/FileClientTests.cs b/sdk/storage/Azure.Storage.Files.Shares/tests/FileClientTests.cs index 01dd5c8151c1..3ea72389e65a 100644 --- a/sdk/storage/Azure.Storage.Files.Shares/tests/FileClientTests.cs +++ b/sdk/storage/Azure.Storage.Files.Shares/tests/FileClientTests.cs @@ -50,6 +50,31 @@ public void Ctor_ConnectionString() //Assert.AreEqual("accountName", builder.AccountName); } + [Test] + [Ignore("Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, so we can't pass connection string validation")] + public async Task Ctor_ConnectionStringEscapePath() + { + // Arrange + await using DisposingShare test = await GetTestShareAsync(); + string directoryName = "!#@&=;"; + string fileName = "#$=;!"; + ShareDirectoryClient directory = InstrumentClient(test.Share.GetDirectoryClient(directoryName)); + await directory.CreateAsync(); + ShareFileClient initalFile = InstrumentClient(directory.GetFileClient(fileName)); + Response createResponse = await initalFile.CreateAsync(Constants.KB); + + // Act + ShareFileClient file = new ShareFileClient( + TestConfigDefault.ConnectionString, + test.Share.Name, + $"{directoryName}/{fileName}", + GetOptions()); + Response propertiesResponse = await file.GetPropertiesAsync(); + + // Assert + Assert.AreEqual(createResponse.Value.ETag, propertiesResponse.Value.ETag); + } + [Test] public void FilePathsParsing() { diff --git a/sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs b/sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs index c54aafae2815..466c0d5e1378 100644 --- a/sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs +++ b/sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs @@ -25,7 +25,7 @@ public class FileTestBase : StorageTestBase public static Uri s_invalidUri = new Uri("https://error.file.core.windows.net"); public FileTestBase(bool async, ShareClientOptions.ServiceVersion serviceVersion, RecordedTestMode? mode = null) - : base(async, mode) + : base(async, RecordedTestMode.Playback) { _serviceVersion = serviceVersion; } From f1d70e91d0d49ea3a3847f30ff6b09c9c8f05b83 Mon Sep 17 00:00:00 2001 From: Sean McCullough Date: Tue, 28 Apr 2020 17:44:30 -0700 Subject: [PATCH 2/4] PR comments --- sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs b/sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs index 466c0d5e1378..c54aafae2815 100644 --- a/sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs +++ b/sdk/storage/Azure.Storage.Files.Shares/tests/FileTestBase.cs @@ -25,7 +25,7 @@ public class FileTestBase : StorageTestBase public static Uri s_invalidUri = new Uri("https://error.file.core.windows.net"); public FileTestBase(bool async, ShareClientOptions.ServiceVersion serviceVersion, RecordedTestMode? mode = null) - : base(async, RecordedTestMode.Playback) + : base(async, mode) { _serviceVersion = serviceVersion; } From ccb35c88de6a0b5e4d5e03ef75ac65c065846d36 Mon Sep 17 00:00:00 2001 From: Sean McCullough Date: Tue, 5 May 2020 14:02:03 -0700 Subject: [PATCH 3/4] PR comments --- .../Azure.Storage.Blobs/tests/BlobBaseClientTests.cs | 6 ++++-- .../tests/DirectoryClientTests.cs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs b/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs index 044761bbc24b..46a260b3d740 100644 --- a/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs +++ b/sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs @@ -62,12 +62,14 @@ public void Ctor_ConnectionString() } [Test] - [Ignore("Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, so we can't pass connection string validation")] + // Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, + // so we can't pass connection string validation" + [LiveOnly] public async Task Ctor_ConnectionStringEscapeBlobName() { // Arrange await using DisposingContainer test = await GetTestContainerAsync(); - string blobName = "!*'();[]:@&%=+$,/?#"; + string blobName = "!*'();[]:@&%=+$,/?#äÄöÖüÜß"; BlockBlobClient initalBlob = InstrumentClient(test.Container.GetBlockBlobClient(blobName)); var data = GetRandomBuffer(Constants.KB); diff --git a/sdk/storage/Azure.Storage.Files.Shares/tests/DirectoryClientTests.cs b/sdk/storage/Azure.Storage.Files.Shares/tests/DirectoryClientTests.cs index 851b720746ad..9bf93f306de7 100644 --- a/sdk/storage/Azure.Storage.Files.Shares/tests/DirectoryClientTests.cs +++ b/sdk/storage/Azure.Storage.Files.Shares/tests/DirectoryClientTests.cs @@ -45,12 +45,14 @@ public void Ctor_ConnectionString() } [Test] - [Ignore("Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, so we can't pass connection string validation")] + //Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, + // so we can't pass connection string validation" + [LiveOnly] public async Task Ctor_ConnectionStringEscapePath() { // Arrange await using DisposingShare test = await GetTestShareAsync(); - string directoryName = "!#@&=;"; + string directoryName = "!#@&=;äÄöÖüÜß"; ShareDirectoryClient initalDirectory = InstrumentClient(test.Share.GetDirectoryClient(directoryName)); Response createResponse = await initalDirectory.CreateAsync(); From 2bd1792cd0b031a2134862c0bf95277d760a5289 Mon Sep 17 00:00:00 2001 From: Sean McCullough Date: Tue, 5 May 2020 14:09:03 -0700 Subject: [PATCH 4/4] PR comments --- .../Azure.Storage.Files.Shares/tests/FileClientTests.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sdk/storage/Azure.Storage.Files.Shares/tests/FileClientTests.cs b/sdk/storage/Azure.Storage.Files.Shares/tests/FileClientTests.cs index 3ea72389e65a..414df5501770 100644 --- a/sdk/storage/Azure.Storage.Files.Shares/tests/FileClientTests.cs +++ b/sdk/storage/Azure.Storage.Files.Shares/tests/FileClientTests.cs @@ -51,13 +51,15 @@ public void Ctor_ConnectionString() } [Test] - [Ignore("Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, so we can't pass connection string validation")] + // "Test framework doesn't allow recorded tests with connection string because the word 'Sanitized' is not base-64 encoded, + // so we can't pass connection string validation" + [LiveOnly] public async Task Ctor_ConnectionStringEscapePath() { // Arrange await using DisposingShare test = await GetTestShareAsync(); - string directoryName = "!#@&=;"; - string fileName = "#$=;!"; + string directoryName = "!#@&=;äÄ"; + string fileName = "#$=;!öÖ"; ShareDirectoryClient directory = InstrumentClient(test.Share.GetDirectoryClient(directoryName)); await directory.CreateAsync(); ShareFileClient initalFile = InstrumentClient(directory.GetFileClient(fileName));