diff --git a/.gitignore b/.gitignore index 50599d5..3a2de2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ .* !.gitignore +.class bin/ +target/* +!target/*.jar diff --git a/build.xml b/build.xml deleted file mode 100644 index f05537b..0000000 --- a/build.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cloudkey-1.1.jar b/cloudkey-1.1.jar deleted file mode 100644 index 1cdd0a7..0000000 Binary files a/cloudkey-1.1.jar and /dev/null differ diff --git a/examples/Example.class b/examples/Example.class deleted file mode 100644 index 2a1069a..0000000 Binary files a/examples/Example.class and /dev/null differ diff --git a/examples/Example.java b/examples/Example.java index 474244c..f218bf2 100644 --- a/examples/Example.java +++ b/examples/Example.java @@ -1,53 +1,56 @@ + import net.dmcloud.cloudkey.*; import net.dmcloud.util.*; import java.util.Map; import java.util.HashMap; import java.util.ArrayList; -public class Example { +public class Example +{ private static String user_id = "4c1a4d3edede832bfd000002"; private static String api_key = "52a32c7890338770e3ea1601214c02142d297298"; private static String base_url = "http://sebest.api.dev.int.dmcloud.net"; - - public static void mediaList() { - try { + public static void mediaList() + { + try + { CloudKey cloud = new CloudKey(user_id, api_key, base_url, CloudKey.CDN_URL, ""); - DCObject result = cloud.call - ( - "media.list", - DCObject.create() - .push("fields", DCArray.create() - .push("id") - .push("meta.title") - .push("assets.jpeg_thumbnail_auto.stream_url") - .push("assets.mp4_h264_aac.video_width") - .push("assets.mp4_h264_aac.video_height") - .push("assets.source.download_url") - ) - ); + DCObject result = cloud.call( + "media.list", + DCObject.create() + .push("fields", DCArray.create() + .push("id") + .push("meta.title") + .push("assets.jpeg_thumbnail_auto.stream_url") + .push("assets.mp4_h264_aac.video_width") + .push("assets.mp4_h264_aac.video_height") + .push("assets.source.download_url"))); - DCArray list = DCArray.create((ArrayList)result.get("list")); - for(int i=0; i map = token3.getRights(); - if (map != null ) { - for (Map.Entry entry : map.entrySet()) { + HashMap map = token3.getRights(); + if (map != null) + { + for (Map.Entry entry : map.entrySet()) + { System.out.println("Right " + entry.getKey() + " -> " + entry.getValue()); } } - } catch(Exception e) { + } + catch (Exception e) + { e.printStackTrace(); System.out.println("oups"); System.out.println(e); } } - public static void getApiKey() { + public static void getApiKey() + { String ck_user_id = "4c1a4d3edede832bfd000000"; String ck_api_key = "59f7d6fca9080ec7b59b83eab00e104e3d3d2789"; CloudKey cloudkey = new CloudKey(ck_user_id, ck_api_key, base_url, CloudKey.CDN_URL, ""); DCObject ck_obj = DCObject.create() - .push("id", user_id) - .push("fields", DCArray.create() - .push("id") - .push("api_key") - .push("streaming_active") - .push("is_active") - .push("permissions") - ); - try { + .push("id", user_id) + .push("fields", DCArray.create() + .push("id") + .push("api_key") + .push("streaming_active") + .push("is_active") + .push("permissions")); + try + { DCObject result = cloudkey.call("user.info", ck_obj); System.out.println(result.get("api_key")); - } catch (DCException e) { + } + catch (DCException e) + { System.out.println(e); } - } + } - public static void main(String[] args) { + public static void main(String[] args) + { //mediaList(); testToken(); //getApiKey(); } - } \ No newline at end of file diff --git a/examples/Test_FileUpload.java b/examples/Test_FileUpload.java new file mode 100644 index 0000000..f1feed4 --- /dev/null +++ b/examples/Test_FileUpload.java @@ -0,0 +1,22 @@ +package net.dmcloud.cloudkey; + +import java.io.File; + +public class Test_FileUpload +{ + + public static void main(String[] args) + { + try + { + CloudKey cloud = new CloudKey(Test.user_id, Test.api_key); + File f = new File("file-example.mp4"); + String media_id = cloud.mediaCreate(f); + System.out.println(media_id); + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..6132e08 --- /dev/null +++ b/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + net.dmcloud + cloudkey + 1.3-SNAPSHOT + cloudkey + http://www.dmcloud.net + jar + + + UTF-8 + + + + scm:git:git@github.com:dailymotion/cloudkey-java.git + scm:git:git@github.com:dailymotion/cloudkey-java.git + scm:git:git@github.com:dailymotion/cloudkey-java.git + + + + package + + + org.apache.maven.plugins + maven-release-plugin + 2.3.2 + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 1.6 + 1.6 + + + + + + + + junit + junit + 4.10 + test + + + + + commons-codec + commons-codec + 1.6 + compile + + + + commons-httpclient + commons-httpclient + 3.1 + compile + + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.9 + compile + + + + + diff --git a/src/main/java/net/dmcloud/cloudkey/Api.java b/src/main/java/net/dmcloud/cloudkey/Api.java new file mode 100644 index 0000000..23515fd --- /dev/null +++ b/src/main/java/net/dmcloud/cloudkey/Api.java @@ -0,0 +1,128 @@ +package net.dmcloud.cloudkey; + +import java.io.IOException; +import java.util.Map; +import net.dmcloud.util.*; +import org.codehaus.jackson.map.ObjectMapper; + +public class Api +{ + + public static int SECLEVEL_NONE = 0; + public static int SECLEVEL_DELEGATE = 1 << 0; + public static int SECLEVEL_ASNUM = 1 << 1; + public static int SECLEVEL_IP = 1 << 2; + public static int SECLEVEL_USERAGENT = 1 << 3; + public static int SECLEVEL_USEONCE = 1 << 4; + public static int SECLEVEL_COUNTRY = 1 << 5; + public static int SECLEVEL_REFERER = 1 << 6; + public static String API_URL = "http://api.dmcloud.net"; + public static String CDN_URL = "http://cdn.dmcloud.net"; + public static String STATIC_URL = "http://static.dmcloud.net"; + protected String user_id = null; + protected String api_key = null; + protected String base_url = null; + protected String cdn_url = null; + protected String proxy = null; + + public Api(String _user_id, String _api_key) + { + this(_user_id, _api_key, CloudKey.API_URL, CloudKey.CDN_URL, ""); + } + + public Api(String _user_id, String _api_key, String _base_url, String _cdn_url, String _proxy) + { + this.user_id = _user_id; + this.api_key = _api_key; + this.base_url = _base_url; + this.cdn_url = _cdn_url; + this.proxy = _proxy; + } + + public DCObject call(String call, DCObject args) throws DCException + { + ObjectMapper mapper = new ObjectMapper(); + + DCObject jo = DCObject.create() + .push("call", call) + .push("args", args); + + jo.push("auth", this.user_id + ":" + Helpers.md5(this.user_id + Helpers.normalize(jo) + this.api_key)); + + String json_encoded = null; + DCObject json_response = null; + try + { + json_encoded = mapper.writeValueAsString(jo); + } + catch (IOException e) + { + throw new DCException("JSON serialization error: " + e.getMessage()); + } + String response = Helpers.curl(this.base_url + "/api", json_encoded); + try + { + json_response = DCObject.create(mapper.readValue(response, Map.class)); + } + catch (IOException e) + { + throw new DCException("JSON deserialization error: " + e.getMessage()); + } + if (json_response.containsKey("error")) + { + String message = ""; + int error_code = Integer.parseInt(json_response.pull("error.code")); + switch (error_code) + { + case 200: + message = "ProcessorException"; + break; + case 300: + message = "TransportException"; + break; + case 400: + message = "AuthenticationErrorException"; + break; + case 410: + message = "RateLimitExceededException"; + break; + case 500: + message = "SerializerException"; + break; + + case 600: + message = "InvalidRequestException"; + break; + case 610: + message = "InvalidObjectException"; + break; + case 620: + message = "InvalidMethodException"; + break; + case 630: + message = "InvalidParamException"; + break; + + case 1000: + message = "ApplicationException"; + break; + case 1010: + message = "NotFoundException"; + break; + case 1020: + message = "ExistsException"; + break; + case 1030: + message = "LimitExceededException"; + break; + + default: + message = "RPCException (error:" + json_response.pull("error.code").toString() + ")"; + break; + } + message += " : " + json_response.pull("error.message").toString(); + throw new DCException(message, error_code); + } + return DCObject.create((Map) json_response.get("result")); + } +} diff --git a/src/main/java/net/dmcloud/cloudkey/CloudKey.java b/src/main/java/net/dmcloud/cloudkey/CloudKey.java new file mode 100644 index 0000000..66b57c9 --- /dev/null +++ b/src/main/java/net/dmcloud/cloudkey/CloudKey.java @@ -0,0 +1,179 @@ +package net.dmcloud.cloudkey; + +import java.io.*; +import java.util.Map; + +import net.dmcloud.util.*; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.codehaus.jackson.map.ObjectMapper; + +public class CloudKey extends Api +{ + + public CloudKey(String _user_id, String _api_key) + { + super(_user_id, _api_key, CloudKey.API_URL, CloudKey.CDN_URL, ""); + } + + public CloudKey(String _user_id, String _api_key, String _base_url, String _cdn_url, String _proxy) + { + super(_user_id, _api_key, _base_url, _cdn_url, _proxy); + } + + public String mediaGetEmbedUrl(String id) throws DCException + { + return this.mediaGetEmbedUrl(CloudKey.API_URL, id, CloudKey.SECLEVEL_NONE, "", "", "", null, null, 0); + } + + public String mediaGetEmbedUrl(String id, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires) throws DCException + { + return this.mediaGetEmbedUrl(CloudKey.API_URL, id, seclevel, asnum, ip, useragent, countries, referers, expires); + } + + public String mediaGetEmbedUrl(String url, String id, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires) throws DCException + { + String _url = url + "/embed/" + this.user_id + "/" + id; + return Helpers.sign_url(_url, this.api_key, seclevel, asnum, ip, useragent, countries, referers, expires); + } + + public String mediaGetStreamUrl(String id) throws DCException + { + return this.mediaGetStreamUrl(CloudKey.API_URL, id, "mp4_h264_aac", CloudKey.SECLEVEL_NONE, "", "", "", null, null, 0, "", false); + } + + public String mediaGetStreamUrl(String id, String asset_name) throws DCException + { + return this.mediaGetStreamUrl(CloudKey.API_URL, id, asset_name, CloudKey.SECLEVEL_NONE, "", "", "", null, null, 0, "", false); + } + + public String mediaGetStreamUrl(String id, String asset_name, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires, String extension, Boolean download) throws DCException + { + return this.mediaGetStreamUrl(CloudKey.API_URL, id, asset_name, seclevel, asnum, ip, useragent, countries, referers, expires, extension, download); + } + + public String mediaGetStreamUrl(String url, String id, String asset_name, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires, String extension, Boolean download) throws DCException + { + if (extension.equals("")) + { + String[] parts = asset_name.split("\\_"); + extension = (!parts[0].equals(asset_name)) ? parts[0] : extension; + } + if (asset_name.length() >= 15 && asset_name.substring(0, 15).equals("jpeg_thumbnail_")) + { + return CloudKey.STATIC_URL + this.user_id + "/" + id + "/" + asset_name + "." + extension; + } + else + { + String _url = this.cdn_url + "/route/" + this.user_id + "/" + id + "/" + asset_name + ((!extension.equals("")) ? "." + extension : ""); + return Helpers.sign_url(_url, this.api_key, seclevel, asnum, ip, useragent, countries, referers, expires) + (download ? "&throttle=0&helper=0&cache=0" : ""); + } + } + + public String mediaCreate() throws Exception + { + return mediaCreate(""); + } + + public String mediaCreate(String url) throws Exception + { + return mediaCreate(url, null, null); + } + + public String mediaCreate(String url, DCArray assets_names, DCObject meta) throws Exception + { + DCObject args = DCObject.create().push("url", url); + if (assets_names != null && assets_names.size() > 0) + { + args.push("assets_names", assets_names); + } + if (meta != null && meta.size() > 0) + { + args.push("meta", meta); + } + DCObject result = this.call("media.create", args); + return result.pull("id"); + } + + public String mediaCreate(File f) throws Exception + { + return this.mediaCreate(f, null, null); + } + + public String mediaCreate(File f, DCArray assets_names, DCObject meta) throws Exception + { + String upload_url = this.fileUpload(); + + PostMethod filePost = null; + try + { + filePost = new PostMethod(upload_url); + + Part[] parts = + { + new FilePart("file", f) + }; + + filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams())); + HttpClient client = new HttpClient(); + client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); + + int status = client.executeMethod(filePost); + if (status == HttpStatus.SC_OK) + { + ObjectMapper mapper = new ObjectMapper(); + DCObject json_response = DCObject.create(mapper.readValue(filePost.getResponseBodyAsString(), Map.class)); + return this.mediaCreate(json_response.pull("url"), assets_names, meta); + } + else + { + throw new DCException("Upload failed."); + } + } + catch (Exception e) + { + throw new DCException("Upload failed."); + } + finally + { + if (filePost != null) + { + filePost.releaseConnection(); + } + } + } + + public void mediaDelete(String id) throws Exception + { + this.call("media.delete", DCObject.create().push("id", id)); + } + + public String fileUpload() throws Exception + { + DCObject result = fileUpload(false, "", ""); + return result.pull("url"); + } + + public DCObject fileUpload(Boolean status, String jsonp_cb, String target) throws Exception + { + DCObject args = DCObject.create(); + if (status) + { + args.push("status", true); + } + if (!jsonp_cb.equals("")) + { + args.push("jsonp_cb", jsonp_cb); + } + if (!target.equals("")) + { + args.push("target", target); + } + return (DCObject) this.call("file.upload", args); + } +} diff --git a/src/main/java/net/dmcloud/cloudkey/DCException.java b/src/main/java/net/dmcloud/cloudkey/DCException.java new file mode 100644 index 0000000..b3719d4 --- /dev/null +++ b/src/main/java/net/dmcloud/cloudkey/DCException.java @@ -0,0 +1,23 @@ +package net.dmcloud.cloudkey; + +public class DCException extends Exception +{ + + int code = 0; + + public DCException(String message) + { + super(message); + } + + public DCException(String message, int _code) + { + this(message); + this.code = _code; + } + + public int getCode() + { + return this.code; + } +} \ No newline at end of file diff --git a/src/main/java/net/dmcloud/cloudkey/Helpers.java b/src/main/java/net/dmcloud/cloudkey/Helpers.java new file mode 100644 index 0000000..4d6ecee --- /dev/null +++ b/src/main/java/net/dmcloud/cloudkey/Helpers.java @@ -0,0 +1,286 @@ +package net.dmcloud.cloudkey; + +import java.io.*; +import java.net.*; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.zip.Deflater; +import org.apache.commons.codec.binary.Base64; + +public class Helpers +{ + + static public String curl(String targetURL, String urlParameters) + { + URL url; + HttpURLConnection connection = null; + try + { + // Create connection + url = new URL(targetURL); + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length)); + connection.setUseCaches(false); + connection.setDoInput(true); + connection.setDoOutput(true); + + // Send request + DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); + wr.writeBytes(urlParameters); + wr.flush(); + wr.close(); + + // Get Response + InputStream is = connection.getInputStream(); + BufferedReader rd = new BufferedReader(new InputStreamReader(is)); + String line; + StringBuffer response = new StringBuffer(); + while ((line = rd.readLine()) != null) + { + response.append(line); + response.append('\r'); + } + rd.close(); + return response.toString(); + } + catch (Exception e) + { + e.printStackTrace(); + return null; + } + finally + { + if (connection != null) + { + connection.disconnect(); + } + } + } + + static public String normalize(Map data) + { + String normalize = ""; + data = new TreeMap(data); + Iterator iter = data.entrySet().iterator(); + while (iter.hasNext()) + { + Map.Entry entry = (Map.Entry) iter.next(); + normalize += entry.getKey(); + normalize += normalizing(entry.getValue()); + } + return normalize; + } + + static public String normalize(ArrayList data) + { + String normalize = ""; + for (int i = 0; i < data.size(); i++) + { + normalize += normalizing(data.get(i)); + } + return normalize; + } + + static private String normalizing(Object o) + { + String normalize = ""; + if (o instanceof Map) + { + normalize = normalize((Map) o); + } + else if (o instanceof ArrayList) + { + normalize = normalize((ArrayList) o); + } + else + { + normalize = o.toString(); + } + return normalize; + } + + static public String sign_url(String url, String secret) throws DCException + { + return sign_url(url, secret, CloudKey.SECLEVEL_NONE, "", "", "", null, null, 0); + } + + static public String sign_url(String url, String secret, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires) throws DCException + { + expires = (expires == 0) ? (int) ((new Date().getTime() / 1000) + 7200) : expires; + + // Compute digest + String[] tokens = url.split("\\?"); + String query = ""; + if (tokens.length > 1) + { + url = tokens[0]; + query = tokens[1]; + } + + String secparams = ""; + ArrayList public_secparams = new ArrayList(); + if ((seclevel & CloudKey.SECLEVEL_DELEGATE) == 0) + { + if ((seclevel & CloudKey.SECLEVEL_ASNUM) > 0) + { + if (asnum.equals("")) + { + throw new DCException("IP security level required and no IP address provided."); + } + secparams += asnum; + } + if ((seclevel & CloudKey.SECLEVEL_IP) > 0) + { + if (asnum.equals("")) + { + throw new DCException("IP security level required and no IP address provided."); + } + secparams += ip; + } + if ((seclevel & CloudKey.SECLEVEL_USERAGENT) > 0) + { + if (asnum.equals("")) + { + throw new DCException("USERAGENT security level required and no user-agent provided."); + } + secparams += useragent; + } + if ((seclevel & CloudKey.SECLEVEL_COUNTRY) > 0) + { + if (countries == null || countries.length == 0) + { + throw new DCException("COUNTRY security level required and no country list provided."); + } + public_secparams.add("cc=" + implode(",", countries).toLowerCase()); + } + if ((seclevel & CloudKey.SECLEVEL_REFERER) > 0) + { + if (referers == null || referers.length == 0) + { + throw new DCException("REFERER security level required and no referer list provided."); + } + try + { + StringBuffer ref = new StringBuffer(); + for (int i = 0; i < referers.length; i++) + { + if (i > 0) + { + ref.append(" "); + } + ref.append(referers[i].replace(" ", "%20")); + } + public_secparams.add("rf=" + URLEncoder.encode(ref.toString(), "UTF-8")); + } + catch (Exception e) + { + throw new DCException(e.getMessage()); + } + } + } + String public_secparams_encoded = ""; + + if (public_secparams.size() > 0) + { + try + { + public_secparams_encoded = Base64.encodeBase64URLSafeString(gzcompress(implode("&", public_secparams))); + } + catch (Exception e) + { + throw new DCException(e.getMessage()); + } + } + String rand = ""; + String letters = "abcdefghijklmnopqrstuvwxyz0123456789"; + for (int i = 0; i < 8; i++) + { + int index = (int) Math.round(Math.random() * 35); + rand += letters.substring(index, index + 1); + } + + String digest = md5(seclevel + url + expires + rand + secret + secparams + public_secparams_encoded); + + return url + "?" + (!query.equals("") ? query + '&' : "") + "auth=" + expires + "-" + seclevel + "-" + rand + "-" + digest + (public_secparams_encoded != "" ? "-" + public_secparams_encoded : ""); + } + + private static String implode(String delim, String[] args) + { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < args.length; i++) + { + if (i > 0) + { + sb.append(delim); + } + sb.append(args[i]); + } + return sb.toString(); + } + + private static String implode(String delim, ArrayList args) + { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < args.size(); i++) + { + if (i > 0) + { + sb.append(delim); + } + sb.append(args.get(i)); + } + return sb.toString(); + } + + public static String md5(String password) + { + byte[] uniqueKey = password.getBytes(); + byte[] hash = null; + + try + { + hash = MessageDigest.getInstance("MD5").digest(uniqueKey); + } + catch (NoSuchAlgorithmException e) + { + throw new Error("No MD5 support in this VM."); + } + + StringBuilder hashString = new StringBuilder(); + for (int i = 0; i < hash.length; i++) + { + String hex = Integer.toHexString(hash[i]); + if (hex.length() == 1) + { + hashString.append('0'); + hashString.append(hex.charAt(hex.length() - 1)); + } + else + { + hashString.append(hex.substring(hex.length() - 2)); + } + } + return hashString.toString(); + } + + private static byte[] gzcompress(String inputString) throws Exception + { + byte[] input = inputString.getBytes("UTF-8"); + Deflater compresser = new Deflater(); + compresser.setInput(input); + compresser.finish(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length); + byte[] buf = new byte[1024]; + while (!compresser.finished()) + { + int count = compresser.deflate(buf); + bos.write(buf, 0, count); + } + bos.close(); + + return bos.toByteArray(); + } +} diff --git a/src/main/java/net/dmcloud/util/DCArray.java b/src/main/java/net/dmcloud/util/DCArray.java new file mode 100644 index 0000000..bd39bad --- /dev/null +++ b/src/main/java/net/dmcloud/util/DCArray.java @@ -0,0 +1,25 @@ +package net.dmcloud.util; + +import java.util.ArrayList; + +public class DCArray extends ArrayList +{ + + static public DCArray create() + { + return new DCArray(); + } + + static public DCArray create(ArrayList array) + { + DCArray obj = create(); + obj.addAll(array); + return obj; + } + + public DCArray push(Object s) + { + this.add(s); + return this; + } +} diff --git a/src/main/java/net/dmcloud/util/DCObject.java b/src/main/java/net/dmcloud/util/DCObject.java new file mode 100644 index 0000000..69b638e --- /dev/null +++ b/src/main/java/net/dmcloud/util/DCObject.java @@ -0,0 +1,56 @@ +package net.dmcloud.util; + +import java.util.HashMap; +import java.util.Map; + +public class DCObject extends HashMap +{ + + static public DCObject create() + { + return new DCObject(); + } + + static public DCObject create(Map map) + { + DCObject obj = create(); + obj.putAll(map); + return obj; + } + + public DCObject push(Object s, Object ss) + { + this.put(s, ss); + return this; + } + + public String pull(String path) + { + try + { + if (!path.contains(".")) + { + return this.get(path).toString(); + } + + String[] tokens = path.split("\\."); + Map map = (Map) this.get(tokens[0]); + for (int i = 1; i < tokens.length; i++) + { + if (map.get(tokens[i]) instanceof Map) + { + map = (Map) map.get(tokens[i]); + } + else + { + return map.get(tokens[i]).toString(); + } + } + return "null"; + } + catch (java.lang.NullPointerException e) + { + return "null"; + } + } +} diff --git a/src/net/dmcloud/util/FAToken.java b/src/main/java/net/dmcloud/util/FAToken.java similarity index 53% rename from src/net/dmcloud/util/FAToken.java rename to src/main/java/net/dmcloud/util/FAToken.java index 673e9d9..ea56c5f 100644 --- a/src/net/dmcloud/util/FAToken.java +++ b/src/main/java/net/dmcloud/util/FAToken.java @@ -1,42 +1,43 @@ package net.dmcloud.util; -import java.util.Map; -import java.util.HashMap; -import java.util.Date; -import java.io.IOException; -import java.security.SecureRandom; import java.math.BigInteger; -import net.dmcloud.util.DCObject; +import java.security.SecureRandom; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; import net.dmcloud.cloudkey.Helpers; -import org.codehaus.jackson.map.ObjectMapper; import org.apache.commons.codec.binary.Base64; +import org.codehaus.jackson.map.ObjectMapper; -public class FAToken { +public class FAToken +{ - private String user_id = null; + private String user_id = null; private String media_id = null; private String api_key = null; private String nonce = null; - private HashMap rights = null; - private HashMap meta = null; + private HashMap rights = null; + private HashMap meta = null; private String callback_url = null; private Integer expires = 0; private Integer maxReplay = 0; - public static int DEFAULT_TIMEOUT = 600; - public FAToken(String token, String api_key) throws Exception { + public FAToken(String token, String api_key) throws Exception + { this(token, api_key, true); } - public FAToken(String token, String api_key, Boolean check_auth) throws Exception { - ObjectMapper mapper; - DCObject token_info; + public FAToken(String token, String api_key, Boolean check_auth) throws Exception + { + ObjectMapper mapper; + DCObject token_info; String auth; this.api_key = api_key; - if (Base64.isBase64(token)) { + if (Base64.isBase64(token)) + { token = new String(Base64.decodeBase64(token)); } @@ -45,149 +46,185 @@ public FAToken(String token, String api_key, Boolean check_auth) throws Exceptio user_id = token_info.get("user_id").toString(); media_id = token_info.get("media_id").toString(); expires = Integer.parseInt(token_info.get("expires").toString()); - if (token_info.containsKey("max_replay")) { + if (token_info.containsKey("max_replay")) + { maxReplay = Integer.parseInt(token_info.get("max_replay").toString()); } - if (token_info.containsKey("nonce")) { + if (token_info.containsKey("nonce")) + { nonce = token_info.get("nonce").toString(); } - if (token_info.containsKey("rights")) { - rights = (HashMap)token_info.get("rights"); - } else { - rights = new HashMap(); + if (token_info.containsKey("rights")) + { + rights = (HashMap) token_info.get("rights"); } - if (token_info.containsKey("meta")) { - meta = (HashMap)token_info.get("meta"); - } else { - meta = new HashMap(); + else + { + rights = new HashMap(); } - if (token_info.containsKey("callback_url")) { + if (token_info.containsKey("meta")) + { + meta = (HashMap) token_info.get("meta"); + } + else + { + meta = new HashMap(); + } + if (token_info.containsKey("callback_url")) + { callback_url = token_info.get("callback_url").toString(); } - if (check_auth == true) { + if (check_auth == true) + { auth = token_info.get("auth").toString(); token_info.remove("auth"); - if (!getAuth(token_info).equals(auth)) { + if (!getAuth(token_info).equals(auth)) + { throw new Exception("Auth doesn't match"); } } } - public FAToken(String user_id, String media_id, String api_key) { - this(user_id, media_id, api_key, (int)(new Date().getTime() / 1000) + DEFAULT_TIMEOUT); + public FAToken(String user_id, String media_id, String api_key) + { + this(user_id, media_id, api_key, (int) (new Date().getTime() / 1000) + DEFAULT_TIMEOUT); } - public FAToken(String user_id, String media_id, String api_key, Integer expires) { + public FAToken(String user_id, String media_id, String api_key, Integer expires) + { this.user_id = user_id; this.media_id = media_id; this.api_key = api_key; - this.rights = new HashMap(); - this.meta = new HashMap(); + this.rights = new HashMap(); + this.meta = new HashMap(); this.expires = expires; } - public Boolean isExpired() { + public Boolean isExpired() + { Date expireDate = new Date(Long.valueOf(expires) * 1000); return expireDate.before(new Date()); } - public void setExpires(Integer expires) { + public void setExpires(Integer expires) + { this.expires = expires; } - public Integer getExpires() { + public Integer getExpires() + { return this.expires; } - public void setMaxReplay(Integer maxReplay) { + public void setMaxReplay(Integer maxReplay) + { this.maxReplay = maxReplay; } - public Integer getMaxReplay() { + public Integer getMaxReplay() + { return this.maxReplay; } - public String getUserId() { + public String getUserId() + { return user_id; } - public String getMediaId() { + public String getMediaId() + { return media_id; } - public void setRight(String name, String value) { + public void setRight(String name, String value) + { rights.put(name, value); } - public HashMap getRights() { + public HashMap getRights() + { return rights; } - public void setMeta(String name, String value) { + public void setMeta(String name, String value) + { meta.put(name, value); } - public HashMap getMeta() { + public HashMap getMeta() + { return meta; } - public void setCallbackUrl(String callback_url) { + public void setCallbackUrl(String callback_url) + { this.callback_url = callback_url; } - public String getCallbackUrl() { + public String getCallbackUrl() + { return this.callback_url; } - public void setNonce(String nonce) { + public void setNonce(String nonce) + { this.nonce = nonce; } - public String getNonce() { + public String getNonce() + { return nonce; } - public void genNonce() { + public void genNonce() + { SecureRandom random = new SecureRandom(); nonce = new BigInteger(130, random).toString(32); } - public String getAuth(DCObject token_info) { + public String getAuth(DCObject token_info) + { return Helpers.md5(Helpers.normalize(token_info) + api_key); } - public String toJSON() throws Exception { - ObjectMapper mapper; + public String toJSON() throws Exception + { + ObjectMapper mapper; DCObject token_info; - if (nonce == null) { + if (nonce == null) + { genNonce(); } - token_info = DCObject.create() - .push("user_id", user_id) - .push("media_id", media_id) - .push("expires", expires) - .push("nonce", nonce); - if (maxReplay > 0) { + token_info = DCObject.create() + .push("user_id", user_id) + .push("media_id", media_id) + .push("expires", expires) + .push("nonce", nonce); + if (maxReplay > 0) + { token_info.push("max_replay", maxReplay); } - if (callback_url != null) { + if (callback_url != null) + { token_info.push("callback_url", callback_url); } - if (!rights.isEmpty()) { + if (!rights.isEmpty()) + { token_info.push("rights", rights); } - if (!meta.isEmpty()) { + if (!meta.isEmpty()) + { token_info.push("meta", meta); } mapper = new ObjectMapper(); - token_info.push("auth", getAuth(token_info)); + token_info.push("auth", getAuth(token_info)); return mapper.writeValueAsString(token_info); } - public String toBase64() throws Exception { - return Base64.encodeBase64String(toJSON().getBytes()); - } - + public String toBase64() throws Exception + { + return Base64.encodeBase64URLSafeString(toJSON().getBytes()); + } } \ No newline at end of file diff --git a/src/net/dmcloud/cloudkey/Api.java b/src/net/dmcloud/cloudkey/Api.java deleted file mode 100644 index d824372..0000000 --- a/src/net/dmcloud/cloudkey/Api.java +++ /dev/null @@ -1,95 +0,0 @@ -package net.dmcloud.cloudkey; - -import java.io.IOException; -import java.util.Map; -import net.dmcloud.util.*; -import org.codehaus.jackson.map.ObjectMapper; - -public class Api -{ - public static int SECLEVEL_NONE = 0; - public static int SECLEVEL_DELEGATE = 1 << 0; - public static int SECLEVEL_ASNUM = 1 << 1; - public static int SECLEVEL_IP = 1 << 2; - public static int SECLEVEL_USERAGENT = 1 << 3; - public static int SECLEVEL_USEONCE = 1 << 4; - public static int SECLEVEL_COUNTRY = 1 << 5; - public static int SECLEVEL_REFERER = 1 << 6; - - public static String API_URL = "http://api.dmcloud.net"; - public static String CDN_URL = "http://cdn.dmcloud.net"; - public static String STATIC_URL = "http://static.dmcloud.net"; - - protected String user_id = null; - protected String api_key = null; - protected String base_url = null; - protected String cdn_url = null; - protected String proxy = null; - - public Api(String _user_id, String _api_key) - { - this(_user_id, _api_key, CloudKey.API_URL, CloudKey.CDN_URL, ""); - } - - public Api(String _user_id, String _api_key, String _base_url, String _cdn_url, String _proxy) - { - this.user_id = _user_id; - this.api_key = _api_key; - this.base_url = _base_url; - this.cdn_url = _cdn_url; - this.proxy = _proxy; - } - - public DCObject call(String call, DCObject args) throws DCException - { - ObjectMapper mapper = new ObjectMapper(); - - DCObject jo = DCObject.create() - .push("call", call) - .push("args", args); - - jo.push("auth", this.user_id + ":" + Helpers.md5(this.user_id + Helpers.normalize(jo) + this.api_key)); - - String json_encoded = null; - DCObject json_response = null; - try { - json_encoded = mapper.writeValueAsString(jo); - } catch(IOException e) { - throw new DCException("JSON serialization error: " + e.getMessage()); - } - String response = Helpers.curl(this.base_url + "/api", json_encoded); - try { - json_response = DCObject.create(mapper.readValue(response, Map.class)); - } catch(IOException e) { - throw new DCException("JSON deserialization error: " + e.getMessage()); - } - if (json_response.containsKey("error")) - { - String message = ""; - int error_code = Integer.parseInt(json_response.pull("error.code")); - switch (error_code) - { - case 200 : message = "ProcessorException"; break; - case 300 : message = "TransportException"; break; - case 400 : message = "AuthenticationErrorException"; break; - case 410 : message = "RateLimitExceededException"; break; - case 500 : message = "SerializerException"; break; - - case 600 : message = "InvalidRequestException"; break; - case 610 : message = "InvalidObjectException"; break; - case 620 : message = "InvalidMethodException"; break; - case 630 : message = "InvalidParamException"; break; - - case 1000 : message = "ApplicationException"; break; - case 1010 : message = "NotFoundException"; break; - case 1020 : message = "ExistsException"; break; - case 1030 : message = "LimitExceededException"; break; - - default : message = "RPCException (error:" + json_response.pull("error.code").toString() + ")"; break; - } - message += " : " + json_response.pull("error.message").toString(); - throw new DCException(message, error_code); - } - return DCObject.create((Map)json_response.get("result")); - } -} diff --git a/src/net/dmcloud/cloudkey/CloudKey.java b/src/net/dmcloud/cloudkey/CloudKey.java deleted file mode 100644 index d1a408a..0000000 --- a/src/net/dmcloud/cloudkey/CloudKey.java +++ /dev/null @@ -1,178 +0,0 @@ -package net.dmcloud.cloudkey; - -import java.io.*; -import java.util.Map; - -import net.dmcloud.util.*; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.multipart.FilePart; -import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; -import org.apache.commons.httpclient.methods.multipart.Part; -import org.codehaus.jackson.map.ObjectMapper; - -public class CloudKey extends Api -{ - public CloudKey(String _user_id, String _api_key) - { - super(_user_id, _api_key, CloudKey.API_URL, CloudKey.CDN_URL, ""); - } - - public CloudKey(String _user_id, String _api_key, String _base_url, String _cdn_url, String _proxy) - { - super(_user_id, _api_key, _base_url, _cdn_url, _proxy); - } - - public String mediaGetEmbedUrl(String id) throws DCException - { - return this.mediaGetEmbedUrl(CloudKey.API_URL, id, CloudKey.SECLEVEL_NONE, "", "", "", null, null, 0); - } - - public String mediaGetEmbedUrl(String id, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires) throws DCException - { - return this.mediaGetEmbedUrl(CloudKey.API_URL, id, seclevel, asnum, ip, useragent, countries, referers, expires); - } - - public String mediaGetEmbedUrl(String url, String id, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires) throws DCException - { - String _url = url + "/embed/" + this.user_id + "/" + id; - return Helpers.sign_url(_url, this.api_key, seclevel, asnum, ip, useragent, countries, referers, expires); - } - - public String mediaGetStreamUrl(String id) throws DCException - { - return this.mediaGetStreamUrl(CloudKey.API_URL, id, "mp4_h264_aac", CloudKey.SECLEVEL_NONE, "", "", "", null, null, 0, "", false); - } - - public String mediaGetStreamUrl(String id, String asset_name) throws DCException - { - return this.mediaGetStreamUrl(CloudKey.API_URL, id, asset_name, CloudKey.SECLEVEL_NONE, "", "", "", null, null, 0, "", false); - } - - public String mediaGetStreamUrl(String id, String asset_name, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires, String extension, Boolean download) throws DCException - { - return this.mediaGetStreamUrl(CloudKey.API_URL, id, asset_name, seclevel, asnum, ip, useragent, countries, referers, expires, extension, download); - } - - public String mediaGetStreamUrl(String url, String id, String asset_name, int seclevel, String asnum, String ip, String useragent, String[] countries, String[] referers, int expires, String extension, Boolean download) throws DCException - { - if (extension == "") - { - String[] parts = asset_name.split("\\_"); - extension = (parts[0] != asset_name) ? parts[0] : extension; - } - if (asset_name.length() >= 15 && asset_name.substring(0, 15) == "jpeg_thumbnail_") - { - return CloudKey.STATIC_URL + this.user_id + "/" + id + "/" + asset_name + "." + extension; - } - else - { - String _url = this.cdn_url + "/route/" + this.user_id + "/" + id + "/" + asset_name + ((extension != "") ? "." + extension : ""); - return Helpers.sign_url(_url, this.api_key, seclevel, asnum, ip, useragent, countries, referers, expires) + (download ? "&throttle=0&helper=0&cache=0" : ""); - } - } - - public String mediaCreate() throws Exception - { - return mediaCreate(""); - } - - public String mediaCreate(String url) throws Exception - { - return mediaCreate(url, null, null); - } - - public String mediaCreate(String url, DCArray assets_names, DCObject meta) throws Exception - { - DCObject args = DCObject.create().push("url", url); - if (assets_names != null && assets_names.size() > 0) - { - args.push("assets_names", assets_names); - } - if (meta != null && meta.size() > 0) - { - args.push("meta", meta); - } - DCObject result = this.call("media.create", args); - return result.pull("id"); - } - - - public String mediaCreate(File f) throws Exception - { - return this.mediaCreate(f, null, null); - } - - public String mediaCreate(File f, DCArray assets_names, DCObject meta) throws Exception - { - String upload_url = this.fileUpload(); - - PostMethod filePost = null; - try - { - filePost = new PostMethod(upload_url); - - Part[] parts = { - new FilePart("file", f) - }; - - filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams())); - HttpClient client = new HttpClient(); - client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); - - int status = client.executeMethod(filePost); - if (status == HttpStatus.SC_OK) - { - ObjectMapper mapper = new ObjectMapper(); - DCObject json_response = DCObject.create(mapper.readValue(filePost.getResponseBodyAsString(), Map.class)); - return this.mediaCreate(json_response.pull("url"), assets_names, meta); - } - else - { - throw new DCException("Upload failed."); - } - } - catch (Exception e) - { - throw new DCException("Upload failed."); - } - finally - { - if (filePost != null) - { - filePost.releaseConnection(); - } - } - } - - public void mediaDelete(String id) throws Exception - { - this.call("media.delete", DCObject.create().push("id", id)); - } - - public String fileUpload() throws Exception - { - DCObject result = fileUpload(false, "", ""); - return result.pull("url"); - } - - public DCObject fileUpload(Boolean status, String jsonp_cb, String target) throws Exception - { - DCObject args = DCObject.create(); - if (status) - { - args.push("status", true); - } - if (jsonp_cb != "") - { - args.push("jsonp_cb", jsonp_cb); - } - if (target != "") - { - args.push("target", target); - } - return (DCObject) this.call("file.upload", args); - } -} diff --git a/src/net/dmcloud/cloudkey/DCException.java b/src/net/dmcloud/cloudkey/DCException.java deleted file mode 100644 index ab03357..0000000 --- a/src/net/dmcloud/cloudkey/DCException.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.dmcloud.cloudkey; - -public class DCException extends Exception -{ - int code = 0; - - public DCException(String message) - { - super(message); - } - - public DCException(String message, int _code) - { - this(message); - this.code = _code; - } - - public int getCode() - { - return this.code; - } -} \ No newline at end of file diff --git a/src/net/dmcloud/cloudkey/Helpers.java b/src/net/dmcloud/cloudkey/Helpers.java deleted file mode 100644 index fabbb06..0000000 --- a/src/net/dmcloud/cloudkey/Helpers.java +++ /dev/null @@ -1,284 +0,0 @@ -package net.dmcloud.cloudkey; - -import java.io.*; -import java.net.*; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.*; -import java.util.zip.Deflater; -import org.apache.commons.codec.binary.Base64; - -public class Helpers -{ - static public String curl(String targetURL, String urlParameters) - { - URL url; - HttpURLConnection connection = null; - try - { - // Create connection - url = new URL(targetURL); - connection = (HttpURLConnection)url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length)); - connection.setUseCaches (false); - connection.setDoInput(true); - connection.setDoOutput(true); - - // Send request - DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); - wr.writeBytes (urlParameters); - wr.flush(); - wr.close(); - - // Get Response - InputStream is = connection.getInputStream(); - BufferedReader rd = new BufferedReader(new InputStreamReader(is)); - String line; - StringBuffer response = new StringBuffer(); - while ((line = rd.readLine()) != null) - { - response.append(line); - response.append('\r'); - } - rd.close(); - return response.toString(); - } - catch (Exception e) - { - e.printStackTrace(); - return null; - } - finally - { - if (connection != null) - { - connection.disconnect(); - } - } - } - - static public String normalize(Map data) - { - String normalize = ""; - data = new TreeMap(data); - Iterator iter = data.entrySet().iterator(); - while (iter.hasNext()) - { - Map.Entry entry = (Map.Entry)iter.next(); - normalize += entry.getKey(); - normalize += normalizing(entry.getValue()); - } - return normalize; - } - - static public String normalize(ArrayList data) - { - String normalize = ""; - for (int i=0; i 1) - { - url = tokens[0]; - query = tokens[1]; - } - - String secparams = ""; - ArrayList public_secparams = new ArrayList(); - if ((seclevel & CloudKey.SECLEVEL_DELEGATE) == 0) - { - if ((seclevel & CloudKey.SECLEVEL_ASNUM) > 0) - { - if (asnum == "") - { - throw new DCException("IP security level required and no IP address provided."); - } - secparams += asnum; - } - if ((seclevel & CloudKey.SECLEVEL_IP) > 0) - { - if (asnum == "") - { - throw new DCException("IP security level required and no IP address provided."); - } - secparams += ip; - } - if ((seclevel & CloudKey.SECLEVEL_USERAGENT) > 0) - { - if (asnum == "") - { - throw new DCException("USERAGENT security level required and no user-agent provided."); - } - secparams += useragent; - } - if ((seclevel & CloudKey.SECLEVEL_COUNTRY) > 0) - { - if (countries == null || countries.length == 0) - { - throw new DCException("COUNTRY security level required and no country list provided."); - } - public_secparams.add("cc=" + implode(",", countries).toLowerCase()); - } - if ((seclevel & CloudKey.SECLEVEL_REFERER) > 0) - { - if (referers == null || referers.length == 0) - { - throw new DCException("REFERER security level required and no referer list provided."); - } - try - { - StringBuffer ref = new StringBuffer(); - for (int i=0; i 0) - ref.append(" "); - ref.append(referers[i].replace(" ", "%20")); - } - public_secparams.add("rf=" + URLEncoder.encode(ref.toString(), "UTF-8")); - } - catch (Exception e) - { - throw new DCException(e.getMessage()); - } - } - } - String public_secparams_encoded = ""; - - if (public_secparams.size() > 0) - { - try - { - public_secparams_encoded = Base64.encodeBase64String(gzcompress(implode("&", public_secparams))); - } - catch (Exception e) - { - throw new DCException(e.getMessage()); - } - } - String rand = ""; - String letters = "abcdefghijklmnopqrstuvwxyz0123456789"; - for (int i=0; i<8; i++) - { - int index = (int)Math.round(Math.random() * 35); - rand += letters.substring(index, index + 1); - } - - String digest = md5(seclevel + url + expires + rand + secret + secparams + public_secparams_encoded); - - return url + "?" + (query != "" ? query + '&' : "") + "auth=" + expires + "-" + seclevel + "-" + rand + "-" + digest + (public_secparams_encoded != "" ? "-" + public_secparams_encoded : ""); - } - - private static String implode(String delim, String[] args) - { - StringBuffer sb = new StringBuffer(); - for (int i=0; i 0) - { - sb.append(delim); - } - sb.append(args[i]); - } - return sb.toString(); - } - - private static String implode(String delim, ArrayList args) - { - StringBuffer sb = new StringBuffer(); - for (int i=0; i 0) - { - sb.append(delim); - } - sb.append(args.get(i)); - } - return sb.toString(); - } - - public static String md5(String password) - { - byte[] uniqueKey = password.getBytes(); - byte[] hash = null; - - try - { - hash = MessageDigest.getInstance("MD5").digest(uniqueKey); - } - catch (NoSuchAlgorithmException e) - { - throw new Error("No MD5 support in this VM."); - } - - StringBuilder hashString = new StringBuilder(); - for (int i=0; i