Skip to content

Commit 933388c

Browse files
Fix format handling in signed URLs
1 parent 4855882 commit 933388c

File tree

2 files changed

+38
-72
lines changed

2 files changed

+38
-72
lines changed

CloudinaryDotNet.Tests/Asset/SignatureTest.cs

+14-32
Original file line numberDiff line numberDiff line change
@@ -222,40 +222,22 @@ public void TestSignedUrl()
222222
Assert.AreEqual(expected, actual);
223223
}
224224

225-
[Test]
226-
public void TestSignedAnsiAndUnicodeUrl()
225+
[TestCase("testFolder/%20Test Image_僅測試", "s--MIMNFCL4--/c_scale,h_200,w_300/v1/testFolder/%2520Test%20Image_%E5%83%85%E6%B8%AC%E8%A9%A6.jpg")]
226+
[TestCase("testFolder/TestImage_僅測試", "s--FvJh0bXb--/c_scale,h_200,w_300/v1/testFolder/TestImage_%E5%83%85%E6%B8%AC%E8%A9%A6.jpg")]
227+
[TestCase("testFolder/Test Image_僅測試", "s--_jfm-XyC--/c_scale,h_200,w_300/v1/testFolder/Test%20Image_%E5%83%85%E6%B8%AC%E8%A9%A6.jpg")]
228+
[TestCase("testFolder/Test Image", "s--rmmMhYpj--/c_scale,h_200,w_300/v1/testFolder/Test%20Image.jpg")]
229+
[TestCase("testFolder/TestImage", "s--lzoFcAJk--/c_scale,h_200,w_300/v1/testFolder/TestImage.jpg")]
230+
[TestCase("testFolder/%20Test Image", "s--AlS6-LgU--/c_scale,h_200,w_300/v1/testFolder/%2520Test%20Image.jpg")]
231+
[TestCase("testFolder/%20TestImage", "s--8xAbqJri--/c_scale,h_200,w_300/v1/testFolder/%2520TestImage.jpg")]
232+
public void TestSignedAnsiAndUnicodeUrl(string publicId, string expectedPath)
227233
{
234+
var urlBuilder = m_api.UrlImgUp.Action("authenticated")
235+
.Transform(new Transformation().Crop("scale").Height(200).Width(300))
236+
.Secure()
237+
.Signed(true);
228238

229-
string[] sourcePublicIds = {
230-
"testFolder/%20Test Image_僅測試.jpg",
231-
"testFolder/TestImage_僅測試.jpg",
232-
"testFolder/Test Image_僅測試.jpg",
233-
"testFolder/Test Image.jpg",
234-
"testFolder/TestImage.jpg",
235-
"testFolder/%20Test Image.jpg",
236-
"testFolder/%20TestImage.jpg"
237-
};
238-
239-
string[] expectedSignedUrls = {
240-
"https://res.cloudinary.com/testcloud/image/authenticated/s--MIMNFCL4--/c_scale,h_200,w_300/v1/testFolder/%2520Test%20Image_%E5%83%85%E6%B8%AC%E8%A9%A6.jpg",
241-
"https://res.cloudinary.com/testcloud/image/authenticated/s--FvJh0bXb--/c_scale,h_200,w_300/v1/testFolder/TestImage_%E5%83%85%E6%B8%AC%E8%A9%A6.jpg",
242-
"https://res.cloudinary.com/testcloud/image/authenticated/s--_jfm-XyC--/c_scale,h_200,w_300/v1/testFolder/Test%20Image_%E5%83%85%E6%B8%AC%E8%A9%A6.jpg",
243-
"https://res.cloudinary.com/testcloud/image/authenticated/s--rmmMhYpj--/c_scale,h_200,w_300/v1/testFolder/Test%20Image.jpg",
244-
"https://res.cloudinary.com/testcloud/image/authenticated/s--lzoFcAJk--/c_scale,h_200,w_300/v1/testFolder/TestImage.jpg",
245-
"https://res.cloudinary.com/testcloud/image/authenticated/s--AlS6-LgU--/c_scale,h_200,w_300/v1/testFolder/%2520Test%20Image.jpg",
246-
"https://res.cloudinary.com/testcloud/image/authenticated/s--8xAbqJri--/c_scale,h_200,w_300/v1/testFolder/%2520TestImage.jpg"
247-
};
248-
249-
for (int x = 0; x < sourcePublicIds.Length; x++)
250-
{
251-
var actual = m_api.UrlImgUp.Action("authenticated")
252-
.Transform(new Transformation().Crop("scale").Height(200).Width(300))
253-
.Secure(true)
254-
.Signed(true)
255-
.BuildUrl(sourcePublicIds[x]);
256-
257-
Assert.AreEqual(expectedSignedUrls[x], actual);
258-
}
239+
Assert.IsTrue(urlBuilder.BuildUrl($"{publicId}.jpg").EndsWith(expectedPath));
240+
Assert.IsTrue(urlBuilder.Format("jpg").BuildUrl(publicId).EndsWith(expectedPath));
259241
}
260242

261243
[Test]

CloudinaryDotNet/Url.cs

+24-40
Original file line numberDiff line numberDiff line change
@@ -856,18 +856,9 @@ public string BuildUrl(string source)
856856
throw new ArgumentException("cloudName must be specified!");
857857
}
858858

859-
if (source == null)
860-
{
861-
source = m_source;
862-
}
863-
864-
if (source == null)
865-
{
866-
source = string.Empty;
867-
}
859+
source ??= m_source ?? string.Empty;
868860

869-
if (Regex.IsMatch(source.ToLowerInvariant(), "^https?:/.*") &&
870-
(m_action == "upload" || m_action == "asset"))
861+
if (Regex.IsMatch(source.ToLowerInvariant(), "^https?:/.*") && m_action is "upload" or "asset")
871862
{
872863
return source;
873864
}
@@ -878,12 +869,11 @@ public string BuildUrl(string source)
878869
FormatValue = null;
879870
}
880871

881-
string transformationStr = Transformation.Generate();
872+
var transformationStr = Transformation.Generate();
882873

883874
var src = UpdateSource(source);
884875

885-
bool sharedDomain;
886-
var prefix = GetPrefix(src.Source, out sharedDomain);
876+
var prefix = GetPrefix(src.Source, out var sharedDomain);
887877

888878
List<string> urlParts = new List<string>(new string[] { prefix });
889879
if (!string.IsNullOrEmpty(m_apiVersion))
@@ -1264,42 +1254,36 @@ private string FinalizePosterUrl(string source)
12641254

12651255
private CSource UpdateSource(string source)
12661256
{
1267-
CSource src = null;
1268-
1269-
var tmpSource = Regex.Replace(source, @"[^\u0000-\u007F]+", string.Empty);
1270-
1271-
bool isSignedAndUnicode = (m_signed && ((tmpSource != source) || tmpSource.Contains("%"))) ? true : false;
1272-
12731257
if (Regex.IsMatch(source.ToLowerInvariant(), "^https?:/.*"))
12741258
{
1275-
src = new CSource(Encode(source));
1259+
return new CSource(Encode(source));
12761260
}
1277-
else
1278-
{
1279-
var targetSource = isSignedAndUnicode ? Utils.Encode(source) : source;
12801261

1281-
src = new CSource(Encode(Decode(targetSource)));
1262+
var isSignedAndUnicode = m_signed && (source.Any(c => c > 127) || source.Contains("%"));
12821263

1283-
if (!string.IsNullOrEmpty(m_suffix))
1284-
{
1285-
if (Regex.IsMatch(m_suffix, "[\\./]"))
1286-
{
1287-
throw new ArgumentException("Suffix should not include . or /!");
1288-
}
1264+
var targetSource = isSignedAndUnicode ? Utils.Encode(source) : source;
12891265

1290-
src.Source += "/" + m_suffix;
1291-
}
1266+
var src = new CSource(Encode(Decode(targetSource)));
12921267

1293-
if (!string.IsNullOrEmpty(FormatValue))
1294-
{
1295-
src += "." + FormatValue;
1296-
}
1268+
if (isSignedAndUnicode)
1269+
{
1270+
// Signature calculation to be in line with backend logic for mixed Ansii and Unicode publicID + authenticated
1271+
src.SourceToSign = Uri.UnescapeDataString(source);
1272+
}
12971273

1298-
if (isSignedAndUnicode)
1274+
if (!string.IsNullOrEmpty(m_suffix))
1275+
{
1276+
if (Regex.IsMatch(m_suffix, "[\\./]"))
12991277
{
1300-
// Signature calculation to be in line with backend logic for mixed Ansii and Unicode publicID + authenticated
1301-
src.SourceToSign = System.Uri.UnescapeDataString(source);
1278+
throw new ArgumentException("Suffix should not include . or /!");
13021279
}
1280+
1281+
src.Source += "/" + m_suffix;
1282+
}
1283+
1284+
if (!string.IsNullOrEmpty(FormatValue))
1285+
{
1286+
src += "." + FormatValue;
13031287
}
13041288

13051289
return src;

0 commit comments

Comments
 (0)