diff --git a/ShareX.UploadersLib/FileUploaders/AzureStorage.cs b/ShareX.UploadersLib/FileUploaders/AzureStorage.cs index 60f717469..2a9724bf7 100644 --- a/ShareX.UploadersLib/FileUploaders/AzureStorage.cs +++ b/ShareX.UploadersLib/FileUploaders/AzureStorage.cs @@ -51,7 +51,7 @@ public override bool CheckConfig(UploadersConfig config) public override GenericUploader CreateUploader(UploadersConfig config, TaskReferenceHelper taskInfo) { - return new AzureStorage(config.AzureStorageAccountName, config.AzureStorageAccountAccessKey, config.AzureStorageContainer, config.AzureStorageEnvironment, config.AzureStorageCustomDomain); + return new AzureStorage(config.AzureStorageAccountName, config.AzureStorageAccountAccessKey, config.AzureStorageContainer, config.AzureStorageEnvironment, config.AzureStorageCustomDomain, config.AzureStorageUploadPath, config.AzureStorageExcludeContainer); } public override TabPage GetUploadersConfigTabPage(UploadersConfigForm form) => form.tpAzureStorage; @@ -66,14 +66,18 @@ public sealed class AzureStorage : FileUploader public string AzureStorageContainer { get; private set; } public string AzureStorageEnvironment { get; private set; } public string AzureStorageCustomDomain { get; private set; } + public string AzureStorageUploadPath { get; private set; } + public bool AzureStorageExcludeContainer { get; private set; } - public AzureStorage(string azureStorageAccountName, string azureStorageAccessKey, string azureStorageContainer, string azureStorageEnvironment, string customDomain) + public AzureStorage(string azureStorageAccountName, string azureStorageAccessKey, string azureStorageContainer, string azureStorageEnvironment, string customDomain, string uploadPath, bool excludeContainer) { AzureStorageAccountName = azureStorageAccountName; AzureStorageAccountAccessKey = azureStorageAccessKey; AzureStorageContainer = azureStorageContainer; AzureStorageEnvironment = (!string.IsNullOrEmpty(azureStorageEnvironment)) ? azureStorageEnvironment : "blob.core.windows.net"; AzureStorageCustomDomain = customDomain; + AzureStorageUploadPath = uploadPath; + AzureStorageExcludeContainer = excludeContainer; } public override UploadResult Upload(Stream stream, string fileName) @@ -90,7 +94,16 @@ public override UploadResult Upload(Stream stream, string fileName) CreateContainerIfNotExists(); string date = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture); - string url = $"https://{AzureStorageAccountName}.{AzureStorageEnvironment}/{AzureStorageContainer}/{fileName}"; + string targetPath = GetUploadPath(fileName); + string url; + if (AzureStorageContainer == "$root") + { + url = $"https://{AzureStorageAccountName}.{AzureStorageEnvironment}/{targetPath}"; + } + else + { + url = $"https://{AzureStorageAccountName}.{AzureStorageEnvironment}/{AzureStorageContainer}/{targetPath}"; + } string contentType = Helpers.GetMimeType(fileName); NameValueCollection requestHeaders = new NameValueCollection(); @@ -99,7 +112,15 @@ public override UploadResult Upload(Stream stream, string fileName) requestHeaders["x-ms-blob-type"] = "BlockBlob"; string canonicalizedHeaders = $"x-ms-blob-type:BlockBlob\nx-ms-date:{date}\nx-ms-version:{APIVersion}\n"; - string canonicalizedResource = $"/{AzureStorageAccountName}/{AzureStorageContainer}/{fileName}"; + string canonicalizedResource; + if (AzureStorageContainer == "$root") + { + canonicalizedResource = $"/{AzureStorageAccountName}/{targetPath}"; + } + else + { + canonicalizedResource = $"/{AzureStorageAccountName}/{AzureStorageContainer}/{targetPath}"; + } string stringToSign = GenerateStringToSign(canonicalizedHeaders, canonicalizedResource, stream.Length.ToString(), contentType); requestHeaders["Authorization"] = $"SharedKey {AzureStorageAccountName}:{stringToSign}"; @@ -112,7 +133,14 @@ public override UploadResult Upload(Stream stream, string fileName) if (!string.IsNullOrEmpty(AzureStorageCustomDomain)) { - result = URLHelpers.CombineURL(AzureStorageCustomDomain, AzureStorageContainer, fileName); + if (AzureStorageExcludeContainer) + { + result = URLHelpers.CombineURL(AzureStorageCustomDomain, targetPath); + } + else + { + result = URLHelpers.CombineURL(AzureStorageCustomDomain, AzureStorageContainer, targetPath); + } result = URLHelpers.FixPrefix(result); } else @@ -224,5 +252,18 @@ private string HashRequest(string stringToSign) return hashedString; } + + private string GetUploadPath(string fileName) + { + if (!String.IsNullOrEmpty(AzureStorageUploadPath)) + { + string path = NameParser.Parse(NameParserType.FolderPath, AzureStorageUploadPath.Trim('/')); + return URLHelpers.CombineURL(path, fileName); + } + else + { + return fileName; + } + } } } \ No newline at end of file diff --git a/ShareX.UploadersLib/Forms/UploadersConfigForm.Designer.cs b/ShareX.UploadersLib/Forms/UploadersConfigForm.Designer.cs index c4409e0b5..ef84a07fb 100644 --- a/ShareX.UploadersLib/Forms/UploadersConfigForm.Designer.cs +++ b/ShareX.UploadersLib/Forms/UploadersConfigForm.Designer.cs @@ -309,6 +309,9 @@ private void InitializeComponent() this.txtGoogleCloudStorageBucket = new System.Windows.Forms.TextBox(); this.oauth2GoogleCloudStorage = new ShareX.UploadersLib.OAuthControl(); this.tpAzureStorage = new System.Windows.Forms.TabPage(); + this.cbAzureStorageExcludeContainer = new System.Windows.Forms.CheckBox(); + this.txtAzureStorageUploadPath = new System.Windows.Forms.TextBox(); + this.lblAzureStorageUploadPath = new System.Windows.Forms.Label(); this.cbAzureStorageEnvironment = new System.Windows.Forms.ComboBox(); this.lblAzureStorageEnvironment = new System.Windows.Forms.Label(); this.btnAzureStoragePortal = new System.Windows.Forms.Button(); @@ -2830,6 +2833,9 @@ private void InitializeComponent() // tpAzureStorage // this.tpAzureStorage.BackColor = System.Drawing.SystemColors.Window; + this.tpAzureStorage.Controls.Add(this.cbAzureStorageExcludeContainer); + this.tpAzureStorage.Controls.Add(this.txtAzureStorageUploadPath); + this.tpAzureStorage.Controls.Add(this.lblAzureStorageUploadPath); this.tpAzureStorage.Controls.Add(this.cbAzureStorageEnvironment); this.tpAzureStorage.Controls.Add(this.lblAzureStorageEnvironment); this.tpAzureStorage.Controls.Add(this.btnAzureStoragePortal); @@ -2844,6 +2850,24 @@ private void InitializeComponent() resources.ApplyResources(this.tpAzureStorage, "tpAzureStorage"); this.tpAzureStorage.Name = "tpAzureStorage"; // + // cbAzureStorageExcludeContainer + // + resources.ApplyResources(this.cbAzureStorageExcludeContainer, "cbAzureStorageExcludeContainer"); + this.cbAzureStorageExcludeContainer.Name = "cbAzureStorageExcludeContainer"; + this.cbAzureStorageExcludeContainer.UseVisualStyleBackColor = true; + this.cbAzureStorageExcludeContainer.CheckedChanged += new System.EventHandler(this.cbAzureStorageExcludeContainer_CheckedChanged); + // + // txtAzureStorageUploadPath + // + resources.ApplyResources(this.txtAzureStorageUploadPath, "txtAzureStorageUploadPath"); + this.txtAzureStorageUploadPath.Name = "txtAzureStorageUploadPath"; + this.txtAzureStorageUploadPath.TextChanged += new System.EventHandler(this.txtAzureStorageUploadPath_TextChanged); + // + // lblAzureStorageUploadPath + // + resources.ApplyResources(this.lblAzureStorageUploadPath, "lblAzureStorageUploadPath"); + this.lblAzureStorageUploadPath.Name = "lblAzureStorageUploadPath"; + // // cbAzureStorageEnvironment // this.cbAzureStorageEnvironment.FormattingEnabled = true; @@ -6082,6 +6106,9 @@ private void InitializeComponent() private System.Windows.Forms.ListBox lbSharedFolderAccounts; private System.Windows.Forms.Label lblGoogleCloudStoragePathPreviewLabel; private System.Windows.Forms.Label lblGoogleCloudStoragePathPreview; + private System.Windows.Forms.TextBox txtAzureStorageUploadPath; + private System.Windows.Forms.Label lblAzureStorageUploadPath; + private System.Windows.Forms.CheckBox cbAzureStorageExcludeContainer; private System.Windows.Forms.Label lblFirebaseDomain; } } diff --git a/ShareX.UploadersLib/Forms/UploadersConfigForm.cs b/ShareX.UploadersLib/Forms/UploadersConfigForm.cs index ee9aa3a08..7bed1acb7 100644 --- a/ShareX.UploadersLib/Forms/UploadersConfigForm.cs +++ b/ShareX.UploadersLib/Forms/UploadersConfigForm.cs @@ -667,6 +667,8 @@ public void LoadSettings() txtAzureStorageContainer.Text = Config.AzureStorageContainer; cbAzureStorageEnvironment.Text = Config.AzureStorageEnvironment; txtAzureStorageCustomDomain.Text = Config.AzureStorageCustomDomain; + txtAzureStorageUploadPath.Text = Config.AzureStorageUploadPath; + cbAzureStorageExcludeContainer.Checked = Config.AzureStorageExcludeContainer; #endregion Azure Storage @@ -2870,6 +2872,16 @@ private void txtAzureStorageCustomDomain_TextChanged(object sender, EventArgs e) Config.AzureStorageCustomDomain = txtAzureStorageCustomDomain.Text; } + private void txtAzureStorageUploadPath_TextChanged(object sender, EventArgs e) + { + Config.AzureStorageUploadPath = txtAzureStorageUploadPath.Text; + } + + private void cbAzureStorageExcludeContainer_CheckedChanged(object sender, EventArgs e) + { + Config.AzureStorageExcludeContainer = cbAzureStorageExcludeContainer.Checked; + } + private void btnAzureStoragePortal_Click(object sender, EventArgs e) { URLHelpers.OpenURL("https://portal.azure.com/?feature.customportal=false#blade/HubsExtension/Resources/resourceType/Microsoft.Storage%2FStorageAccounts"); diff --git a/ShareX.UploadersLib/Forms/UploadersConfigForm.resx b/ShareX.UploadersLib/Forms/UploadersConfigForm.resx index d87827d03..592516ac3 100644 --- a/ShareX.UploadersLib/Forms/UploadersConfigForm.resx +++ b/ShareX.UploadersLib/Forms/UploadersConfigForm.resx @@ -3537,7 +3537,7 @@ store.book[0].title 3, 3, 3, 3 - 972, 537 + 178, 42 7 @@ -7279,6 +7279,84 @@ store.book[0].title 7 + + True + + + NoControl + + + 16, 299 + + + 230, 17 + + + 13 + + + Exclude container name from returned URL + + + cbAzureStorageExcludeContainer + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tpAzureStorage + + + 0 + + + 16, 223 + + + 526, 20 + + + 10 + + + txtAzureStorageUploadPath + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tpAzureStorage + + + 1 + + + NoControl + + + 13, 207 + + + 100, 13 + + + 9 + + + Upload Path: + + + lblAzureStorageUploadPath + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tpAzureStorage + + + 2 + blob.core.windows.net @@ -7310,7 +7388,7 @@ store.book[0].title tpAzureStorage - 0 + 3 True @@ -7340,7 +7418,7 @@ store.book[0].title tpAzureStorage - 1 + 4 NoControl @@ -7352,7 +7430,7 @@ store.book[0].title 24, 24 - 6 + 2 ... @@ -7367,7 +7445,7 @@ store.book[0].title tpAzureStorage - 2 + 5 16, 128 @@ -7376,7 +7454,7 @@ store.book[0].title 526, 20 - 5 + 6 txtAzureStorageContainer @@ -7388,7 +7466,7 @@ store.book[0].title tpAzureStorage - 3 + 6 True @@ -7403,7 +7481,7 @@ store.book[0].title 55, 13 - 4 + 5 Container: @@ -7418,7 +7496,7 @@ store.book[0].title tpAzureStorage - 4 + 7 16, 80 @@ -7427,7 +7505,7 @@ store.book[0].title 526, 20 - 3 + 4 txtAzureStorageAccessKey @@ -7439,7 +7517,7 @@ store.book[0].title tpAzureStorage - 5 + 8 True @@ -7457,7 +7535,7 @@ store.book[0].title 65, 13 - 2 + 3 Access key: @@ -7472,7 +7550,7 @@ store.book[0].title tpAzureStorage - 6 + 9 16, 32 @@ -7493,7 +7571,7 @@ store.book[0].title tpAzureStorage - 7 + 10 True @@ -7526,16 +7604,16 @@ store.book[0].title tpAzureStorage - 8 + 11 - 16, 222 + 16, 273 526, 20 - 9 + 12 txtAzureStorageCustomDomain @@ -7547,19 +7625,19 @@ store.book[0].title tpAzureStorage - 9 + 12 NoControl - 13, 206 + 13, 257 100, 13 - 10 + 11 Custom Domain: @@ -7574,10 +7652,10 @@ store.book[0].title tpAzureStorage - 10 + 13 - 4, 202 + 4, 40 3, 3, 3, 3 diff --git a/ShareX.UploadersLib/UploadersConfig.cs b/ShareX.UploadersLib/UploadersConfig.cs index fc9404a42..ff36bbb22 100644 --- a/ShareX.UploadersLib/UploadersConfig.cs +++ b/ShareX.UploadersLib/UploadersConfig.cs @@ -372,6 +372,8 @@ public class UploadersConfig : SettingsBase public string AzureStorageContainer = ""; public string AzureStorageEnvironment = "blob.core.windows.net"; public string AzureStorageCustomDomain = ""; + public string AzureStorageUploadPath = ""; + public bool AzureStorageExcludeContainer = false; #endregion Azure Storage