package com.akdeniz.googleplaycrawler;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import com.akdeniz.googleplaycrawler.GooglePlay.AndroidAppDeliveryData;
import com.akdeniz.googleplaycrawler.GooglePlay.HttpCookie;
import com.akdeniz.googleplaycrawler.misc.Base64;
public class DownloadData {
private AndroidAppDeliveryData appDeliveryData;
private String downloadUrl;
private HttpCookie downloadAuthCookie;
private GooglePlayAPI api;
public DownloadData(GooglePlayAPI api, AndroidAppDeliveryData appDeliveryData) {
this.appDeliveryData = appDeliveryData;
this.api = api;
this.downloadUrl = appDeliveryData.getDownloadUrl();
this.downloadAuthCookie = appDeliveryData.getDownloadAuthCookie(0);
}
/**
* Access the APK file
*
* @return an inputstream from which the app can be read (already processed
* through crypto).
* @throws NoSuchPaddingException
* @throws NoSuchProviderException
* @throws NoSuchAlgorithmException
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeyException
*/
public InputStream openApp() throws IOException, NoSuchAlgorithmException,
NoSuchProviderException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException {
InputStream ret = api.executeDownload(downloadUrl, downloadAuthCookie.getName() + "="
+ downloadAuthCookie.getValue());
if (appDeliveryData.hasEncryptionParams()) {
int version = ret.read();
if (version != 0) {
throw new IOException("Unknown crypto container!");
}
ret.skip(4); // Meta data
byte[] iv = new byte[16];
ret.read(iv);
byte[] encoded = appDeliveryData.getEncryptionParams().getEncryptionKey().getBytes("UTF-8");
byte[] decoded = Base64.decode(encoded, Base64.DEFAULT);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(decoded, "AES");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return new CipherInputStream(ret, cipher);
}
else {
return ret;
}
}
/**
* Access the first expansion
*
* @return a stream or null if there is no expansion.
*/
public InputStream openMainExpansion() throws IOException {
if (appDeliveryData.getAdditionalFileCount() < 1) {
return null;
}
String url = appDeliveryData.getAdditionalFile(0).getDownloadUrl();
return api.executeDownload(url,
downloadAuthCookie.getName() + "=" + downloadAuthCookie.getValue());
}
/**
* Access the second expansion
*
* @return a stream or null if there is no expansion.
*/
public InputStream openPatchExpansion() throws IOException {
if (appDeliveryData.getAdditionalFileCount() < 2) {
return null;
}
String url = appDeliveryData.getAdditionalFile(1).getDownloadUrl();
return api.executeDownload(url,
downloadAuthCookie.getName() + "=" + downloadAuthCookie.getValue());
}
public int getPatchFileVersion() {
if (appDeliveryData.getAdditionalFileCount()>1) {
return appDeliveryData.getAdditionalFile(1).getVersionCode();
}
return -1;
}
public int getMainFileVersion() {
if (appDeliveryData.getAdditionalFileCount()>0) {
return appDeliveryData.getAdditionalFile(0).getVersionCode();
}
return -1;
}
}