Skip to content

Commit 8b47123

Browse files
committed
Add support for 32 char SHA-256 URL signatures.
1 parent 349ec6d commit 8b47123

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

cloudinary-core/src/main/java/com/cloudinary/Configuration.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class Configuration {
1919
public final static String SHARED_CDN = AKAMAI_SHARED_CDN;
2020
public final static String VERSION = "1.0.2";
2121
public final static String USER_AGENT = "cld-android-" + VERSION;
22+
public static final boolean DEFAULT_IS_LONG_SIGNATURE = false;
2223

2324
public String cloudName;
2425
public String apiKey;
@@ -41,11 +42,12 @@ public class Configuration {
4142
public boolean clientHints = false;
4243
public AuthToken authToken;
4344
public boolean forceVersion = true;
45+
public boolean longUrlSignature = DEFAULT_IS_LONG_SIGNATURE;
4446

4547
public Configuration() {
4648
}
4749

48-
private Configuration(String cloudName, String apiKey, String apiSecret, String secureDistribution, String cname, String uploadPrefix, boolean secure, boolean privateCdn, boolean cdnSubdomain, boolean shorten, String callback, String proxyHost, int proxyPort, Boolean secureCdnSubdomain, boolean useRootPath, int timeout, boolean loadStrategies, boolean forceVersion) {
50+
private Configuration(String cloudName, String apiKey, String apiSecret, String secureDistribution, String cname, String uploadPrefix, boolean secure, boolean privateCdn, boolean cdnSubdomain, boolean shorten, String callback, String proxyHost, int proxyPort, Boolean secureCdnSubdomain, boolean useRootPath, int timeout, boolean loadStrategies, boolean forceVersion, boolean longUrlSignature) {
4951
this.cloudName = cloudName;
5052
this.apiKey = apiKey;
5153
this.apiSecret = apiSecret;
@@ -64,6 +66,7 @@ private Configuration(String cloudName, String apiKey, String apiSecret, String
6466
this.timeout = 0;
6567
this.loadStrategies = loadStrategies;
6668
this.forceVersion = forceVersion;
69+
this.longUrlSignature = longUrlSignature;
6770
}
6871

6972
@SuppressWarnings("rawtypes")
@@ -100,6 +103,7 @@ public void update(Map config) {
100103
if (properties != null) {
101104
this.properties.putAll(properties);
102105
}
106+
this.longUrlSignature = ObjectUtils.asBoolean(config.get("long_url_signature"), DEFAULT_IS_LONG_SIGNATURE);
103107
}
104108

105109
@SuppressWarnings("rawtypes")
@@ -128,6 +132,7 @@ public Map<String, Object> asMap() {
128132
}
129133
map.put("force_version", forceVersion);
130134
map.put("properties", new HashMap<String,Object>(properties));
135+
map.put("long_url_signature", longUrlSignature);
131136
return map;
132137
}
133138

@@ -156,6 +161,7 @@ public Configuration(Configuration other) {
156161
this.forceVersion = other.forceVersion;
157162
this.loadStrategies = other.loadStrategies;
158163
this.properties.putAll(other.properties);
164+
this.longUrlSignature = other.longUrlSignature;
159165
}
160166

161167
/**
@@ -265,6 +271,7 @@ public static class Builder {
265271
private boolean clientHints = false;
266272
private AuthToken authToken;
267273
private boolean forceVersion = true;
274+
private boolean longUrlSignature = DEFAULT_IS_LONG_SIGNATURE;
268275

269276
/**
270277
* Set the HTTP connection timeout.
@@ -281,7 +288,7 @@ public Builder setTimeout(int timeout) {
281288
* Creates a {@link Configuration} with the arguments supplied to this builder
282289
*/
283290
public Configuration build() {
284-
final Configuration configuration = new Configuration(cloudName, apiKey, apiSecret, secureDistribution, cname, uploadPrefix, secure, privateCdn, cdnSubdomain, shorten, callback, proxyHost, proxyPort, secureCdnSubdomain, useRootPath, timeout, loadStrategies, forceVersion);
291+
final Configuration configuration = new Configuration(cloudName, apiKey, apiSecret, secureDistribution, cname, uploadPrefix, secure, privateCdn, cdnSubdomain, shorten, callback, proxyHost, proxyPort, secureCdnSubdomain, useRootPath, timeout, loadStrategies, forceVersion, longUrlSignature);
285292
configuration.clientHints = clientHints;
286293
return configuration;
287294
}
@@ -400,6 +407,11 @@ public Builder setForceVersion(boolean forceVersion) {
400407
return this;
401408
}
402409

410+
public Builder setIsLongUrlSignature(boolean isLong) {
411+
this.longUrlSignature = isLong;
412+
return this;
413+
}
414+
403415
/**
404416
* Initialize builder from existing {@link Configuration}
405417
*
@@ -427,6 +439,7 @@ public Builder from(Configuration other) {
427439
this.clientHints = other.clientHints;
428440
this.authToken = other.authToken == null ? null : other.authToken.copy();
429441
this.forceVersion = other.forceVersion;
442+
this.longUrlSignature = other.longUrlSignature;
430443
return this;
431444
}
432445
}

cloudinary-core/src/main/java/com/cloudinary/Url.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
public class Url {
2323
private final Cloudinary cloudinary;
2424
private final Configuration config;
25+
private boolean longUrlSignature;
2526
String publicId = null;
2627
String type = null;
2728
String resourceType = null;
@@ -47,6 +48,7 @@ public class Url {
4748
public Url(Cloudinary cloudinary) {
4849
this.cloudinary = cloudinary;
4950
this.config = new Configuration(cloudinary.config);
51+
this.longUrlSignature = config.longUrlSignature;
5052
this.authToken = config.authToken;
5153
}
5254

@@ -73,7 +75,7 @@ public Url clone() {
7375
cloned.sourceTypes = this.sourceTypes;
7476
cloned.urlSuffix = this.urlSuffix;
7577
cloned.useRootPath = this.useRootPath;
76-
78+
cloned.longUrlSignature = this.longUrlSignature;
7779
return cloned;
7880
}
7981

@@ -240,6 +242,11 @@ public Url authToken(AuthToken authToken) {
240242
return this;
241243
}
242244

245+
public Url longUrlSignature(boolean isLong) {
246+
this.longUrlSignature = isLong;
247+
return this;
248+
}
249+
243250
public Url sourceTransformation(Map<String, Transformation> sourceTransformation) {
244251
this.sourceTransformation = sourceTransformation;
245252
return this;
@@ -384,7 +391,7 @@ public String generate(String source) {
384391
if (signUrl && (authToken == null || authToken.equals(AuthToken.NULL_AUTH_TOKEN))) {
385392
MessageDigest md = null;
386393
try {
387-
md = MessageDigest.getInstance("SHA-1");
394+
md = MessageDigest.getInstance(longUrlSignature ? "SHA-256" : "SHA-1");
388395
} catch (NoSuchAlgorithmException e) {
389396
throw new RuntimeException("Unexpected exception", e);
390397
}
@@ -395,7 +402,7 @@ public String generate(String source) {
395402

396403
byte[] digest = md.digest(Util.getUTF8Bytes(toSign + this.config.apiSecret));
397404
signature = Base64Coder.encodeURLSafeString(digest);
398-
signature = "s--" + signature.substring(0, 8) + "--";
405+
signature = "s--" + signature.substring(0, longUrlSignature ? 32 : 8) + "--";
399406
}
400407

401408
String resourceType = this.resourceType;

cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,15 @@ public void testNotSignTheUrlSuffix() {
251251
assertEquals("http://test123-res.cloudinary.com/images/" + expectedSignature + "/a_0/test/hello.jpg", actual);
252252
}
253253

254+
@Test
255+
public void testSignatureLength(){
256+
String url = cloudinary.url().signed(true).generate("sample.jpg");
257+
assertEquals("http://res.cloudinary.com/test123/image/upload/s--v2fTPYTu--/sample.jpg", url);
258+
259+
url = cloudinary.url().signed(true).longUrlSignature(true).generate("sample.jpg");
260+
assertEquals("http://res.cloudinary.com/test123/image/upload/s--2hbrSMPOjj5BJ4xV7SgFbRDevFaQNUFf--/sample.jpg", url);
261+
}
262+
254263
@Test
255264
public void testSupportUrlSuffixForRawUploads() {
256265
String actual = cloudinary.url().suffix("hello").privateCdn(true).resourceType("raw").generate("test");

0 commit comments

Comments
 (0)