Skip to content

Commit d8c2b5d

Browse files
committed
chore: url generation functionality and getAuthentication functionality implemented
1 parent 85ffc4d commit d8c2b5d

File tree

3 files changed

+269
-0
lines changed

3 files changed

+269
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.imagekit.sdk.tasks;
2+
3+
import org.apache.commons.codec.digest.HmacUtils;
4+
import java.math.BigInteger;
5+
import java.util.*;
6+
import java.util.regex.Pattern;
7+
8+
public class Calculation {
9+
private static final int DEFAULT_TIME_DIFF = 60 * 30;
10+
11+
public static Map<String, String> getAuthenticatedParams(String token, long expire, String privateKey){
12+
if (token==null){
13+
token= UUID.randomUUID().toString();
14+
}
15+
if (expire==0){
16+
expire= Calendar.getInstance().getTimeInMillis()+DEFAULT_TIME_DIFF;
17+
}
18+
if (privateKey==null) throw new RuntimeException("Private key can't be null.");
19+
20+
String signature = HmacUtils.hmacSha1Hex(privateKey, token + expire);
21+
22+
Map<String, String> auth=new HashMap<>();
23+
auth.put("token",token);
24+
auth.put("expire", String.valueOf(expire));
25+
auth.put("signature",signature);
26+
return auth;
27+
}
28+
29+
public static int getHammingDistance(String firstHex, String secondHex){
30+
if (!(isValidHex(firstHex) && isValidHex(secondHex))){
31+
throw new RuntimeException("Both argument should be hexadecimal.");
32+
}
33+
if (firstHex.length()!=secondHex.length()) throw new RuntimeException("Both argument are not equal in length.");
34+
35+
BigInteger xor = new BigInteger(firstHex, 16).xor(new BigInteger(secondHex, 16));
36+
37+
int count=0;
38+
for(int i = 0; i < xor.toString(2).length(); i++) {
39+
if (xor.toString(2).charAt(i)=='1'){
40+
count+=1;
41+
}
42+
}
43+
return count;
44+
}
45+
46+
static boolean isValidHex(String hex){
47+
return Pattern.matches("^[0-9a-fA-F]+$",hex);
48+
}
49+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.imagekit.sdk.tasks;
2+
3+
public class QueryMaker {
4+
private String query;
5+
6+
public void put(String q){
7+
if (null!=query){
8+
query+="&";
9+
}
10+
else {
11+
query="";
12+
}
13+
query+=q;
14+
}
15+
16+
public String get(){
17+
return query;
18+
}
19+
20+
}
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
package io.imagekit.sdk.tasks;
2+
3+
import io.imagekit.sdk.ImageKit;
4+
import io.imagekit.sdk.config.Configuration;
5+
import io.imagekit.sdk.constants.Transformer;
6+
import io.imagekit.sdk.constants.Version;
7+
import org.apache.commons.codec.digest.HmacUtils;
8+
9+
import java.net.URI;
10+
import java.net.URISyntaxException;
11+
import java.util.*;
12+
13+
public class UrlGen {
14+
15+
private static final long DEFAULT_TIMESTAMP=9999999999L;
16+
17+
public static String getUrl(Map<String,Object> options){
18+
String path= (String) options.get("path");
19+
String urlEndpoint= (String) options.get("urlEndpoint");
20+
String src= (String) options.get("src");
21+
Map<String,String> queryParams= (Map<String, String>) options.get("queryParameters");
22+
List<Map<String,String>> transformation= (List<Map<String, String>>) options.get("transformation");
23+
String transformationPosition= (String) options.get("transformationPosition");
24+
boolean signed=false;
25+
if (null!=options.get("signed")) {
26+
signed = (boolean) options.get("signed");
27+
}
28+
long expire=0;
29+
if (null!=options.get("expireSeconds")) {
30+
expire = (long) (int)options.get("expireSeconds");
31+
}
32+
return UrlGen.generateUrl(path,urlEndpoint,src,queryParams,transformation,transformationPosition,signed,expire);
33+
}
34+
35+
private static String generateUrl(
36+
String path,
37+
String urlEndpoint,
38+
String src,
39+
Map<String,String> queryParameters,
40+
List<Map<String, String>> transformation,
41+
String transformationPosition,
42+
boolean signed,
43+
long expireSeconds
44+
){
45+
Configuration config=ImageKit.getInstance().getConfig();
46+
if (urlEndpoint==null){
47+
urlEndpoint= config.getUrlEndpoint();
48+
}
49+
if (urlEndpoint.charAt(urlEndpoint.length()-1)!='/'){
50+
urlEndpoint+="/";
51+
}
52+
String newUrl=null;
53+
if (null!=src){
54+
newUrl=buildFullUrl(src,queryParameters,transformation,transformationPosition,signed,expireSeconds);
55+
}
56+
else {
57+
if ("query".equalsIgnoreCase(transformationPosition)){
58+
newUrl=buildFullUrl(urlEndpoint+(path.charAt(0)=='/'?path.substring(1,path.length()):path),queryParameters,transformation,transformationPosition,signed,expireSeconds);
59+
}
60+
else {
61+
newUrl = buildPathUrl(path.charAt(0)=='/'?path:"/"+path, urlEndpoint, queryParameters, transformation, transformationPosition, signed, expireSeconds, config.getPrivateKey());
62+
}
63+
}
64+
return newUrl;
65+
}
66+
67+
private static String buildPathUrl(String path, String urlEndpoint, Map<String, String> queryParameters, List<Map<String, String>> transformation, String transformationPosition, boolean signed, long expireSeconds, String privateKey) {
68+
69+
StringBuilder tr= new StringBuilder("");
70+
if (transformation.size()>0) {
71+
tr.append("tr");
72+
for (Map<String, String> map : transformation) {
73+
Set<Map.Entry<String, String>> entries = map.entrySet();
74+
tr.append(":");
75+
int i = 0;
76+
for (Map.Entry<String, String> entry : entries) {
77+
String key = entry.getKey();
78+
String value = entry.getValue();
79+
String element = Transformer.getInstance().transform(key) + (value.equalsIgnoreCase("-") ? "" : "-" + value);
80+
tr.append(element);
81+
if (i < entries.size() - 1) {
82+
tr.append(",");
83+
}
84+
i++;
85+
}
86+
}
87+
}
88+
89+
QueryMaker queryMaker=new QueryMaker();
90+
queryMaker.put(String.format(Locale.US,"%s=%s","ik-sdk-version", Version.VERSION_CODE));
91+
if (null!=queryParameters){
92+
for (Map.Entry<String,String> entry:queryParameters.entrySet()){
93+
queryMaker.put(String.format(Locale.US,"%s=%s",entry.getKey(),entry.getValue()));
94+
}
95+
}
96+
97+
URI baseUrl=URI.create(urlEndpoint);
98+
URI newUri= null;
99+
try {
100+
String newPath=baseUrl.getPath();
101+
if (tr.toString().equalsIgnoreCase("")){
102+
newPath+=path.substring(1,path.length());
103+
}
104+
else {
105+
newPath+=tr+path;
106+
}
107+
108+
URI tmpUri = new URI(baseUrl.getScheme(),baseUrl.getUserInfo(),baseUrl.getHost(),baseUrl.getPort(),
109+
newPath,
110+
queryMaker.get(),null);
111+
112+
if (signed){
113+
long expiryTimestamp = DEFAULT_TIMESTAMP;
114+
if (expireSeconds > 0){
115+
expiryTimestamp = ((Calendar.getInstance().getTimeInMillis()/1000)+expireSeconds);
116+
String signature = signUrl(privateKey,tmpUri.toString(),urlEndpoint,expiryTimestamp);
117+
queryMaker.put("ik-s=" + signature);
118+
queryMaker.put("ik-t=" + expiryTimestamp);
119+
}
120+
}
121+
122+
newUri = new URI(baseUrl.getScheme(),baseUrl.getUserInfo(),baseUrl.getHost(),baseUrl.getPort(),
123+
newPath,
124+
queryMaker.get(),null);
125+
126+
} catch (URISyntaxException e) {
127+
e.printStackTrace();
128+
}
129+
return newUri.toString();
130+
}
131+
132+
private static String buildFullUrl(String src, Map<String, String> queryParameters, List<Map<String, String>> transformation, String transformationPosition, boolean signed, long expireSeconds) {
133+
StringBuilder tr= new StringBuilder("");
134+
if (transformation.size()>0) {
135+
tr.append("tr=");
136+
for (Map<String, String> map : transformation) {
137+
Set<Map.Entry<String, String>> entries = map.entrySet();
138+
if (!tr.toString().equalsIgnoreCase("tr="))
139+
tr.append(":");
140+
int i = 0;
141+
for (Map.Entry<String, String> entry : entries) {
142+
String key = entry.getKey();
143+
String value = entry.getValue();
144+
String element = Transformer.getInstance().transform(key) + (value.equalsIgnoreCase("-") ? "" : "-" + value);
145+
tr.append(element);
146+
if (i < entries.size() - 1) {
147+
tr.append(",");
148+
}
149+
i++;
150+
}
151+
}
152+
}
153+
154+
QueryMaker queryMaker=new QueryMaker();
155+
queryMaker.put(String.format(Locale.US,"%s=%s","ik-sdk-version", Version.VERSION_CODE));
156+
157+
// check existing query params
158+
if (null!=src){
159+
String[] parts=src.split("\\?");
160+
if (parts.length>1){
161+
String[] queries=parts[1].split("&");
162+
for (String query:queries){
163+
queryMaker.put(query);
164+
}
165+
}
166+
}
167+
168+
if (null!=queryParameters){
169+
for (Map.Entry<String,String> entry:queryParameters.entrySet()){
170+
queryMaker.put(String.format(Locale.US,"%s=%s",entry.getKey(),entry.getValue()));
171+
}
172+
}
173+
if (!tr.toString().equalsIgnoreCase("")){
174+
queryMaker.put(tr.toString());
175+
}
176+
177+
URI baseUrl=URI.create(src);
178+
URI newUri= null;
179+
try {
180+
String newPath=baseUrl.getPath();
181+
newUri = new URI(baseUrl.getScheme(),baseUrl.getUserInfo(),baseUrl.getHost(),baseUrl.getPort(),
182+
newPath,
183+
queryMaker.get(),null);
184+
} catch (URISyntaxException e) {
185+
e.printStackTrace();
186+
}
187+
return newUri.toString();
188+
}
189+
190+
public static String signUrl(String privateKey, String url, String urlEndpoint, long expiryTimestamp){
191+
if (expiryTimestamp < 1){
192+
expiryTimestamp = DEFAULT_TIMESTAMP;
193+
}
194+
if (urlEndpoint.charAt(urlEndpoint.length()-1)!='/'){
195+
urlEndpoint+="/";
196+
}
197+
String replaceUrl=url.replace(urlEndpoint,"")+expiryTimestamp;
198+
return HmacUtils.hmacSha1Hex(privateKey, replaceUrl);
199+
}
200+
}

0 commit comments

Comments
 (0)