305 lines
14 KiB
Java
305 lines
14 KiB
Java
package com.psmreborn.nopsmdrm;
|
|
|
|
import static com.psmreborn.nopsmdrm.Helper.*;
|
|
import static com.psmreborn.nopsmdrm.Root.*;
|
|
|
|
import android.app.Activity;
|
|
import android.app.AlertDialog;
|
|
import android.app.ProgressDialog;
|
|
import android.content.Context;
|
|
import android.content.pm.PackageManager;
|
|
import android.os.AsyncTask;
|
|
import android.os.Build;
|
|
import android.os.Environment;
|
|
import android.telephony.TelephonyManager;
|
|
import android.util.Log;
|
|
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.io.PrintWriter;
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.util.Locale;
|
|
|
|
import eu.chainfire.libsuperuser.Shell;
|
|
|
|
// Sorry if this is kinda hard to follow ...
|
|
|
|
public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
|
|
private boolean wasError = false;
|
|
private String errorMsg = "";
|
|
private ProgressDialog dialog = null;
|
|
private Context ctx = null;
|
|
private StringEncryptor stringEncryptor = null;
|
|
|
|
public NoPsmDrmInstaller(Context context){
|
|
this.ctx = context;
|
|
this.stringEncryptor = new StringEncryptor(this.ctx);
|
|
}
|
|
|
|
private void setError(String msg) throws Exception {
|
|
this.wasError = true;
|
|
this.errorMsg = msg;
|
|
Log.e("INSTALLER",errorMsg);
|
|
throw new Exception(msg);
|
|
}
|
|
|
|
private void generateDeviceFingerprint(String outputFilename) throws FileNotFoundException, UnsupportedEncodingException {
|
|
|
|
|
|
TelephonyManager tm = ((TelephonyManager) ctx.getSystemService( Context.TELEPHONY_SERVICE));
|
|
|
|
String deviceId = "(blank)";
|
|
if(tm != null)
|
|
deviceId = tm.getDeviceId();
|
|
|
|
if(deviceId == null)
|
|
deviceId = "(blank)";
|
|
|
|
String serial = Build.SERIAL;
|
|
if(serial == null)
|
|
serial = "(blank)";
|
|
|
|
String brand = Build.BRAND;
|
|
if(brand == null)
|
|
brand = "(blank)";
|
|
|
|
String manu = Build.MANUFACTURER;
|
|
if(manu == null)
|
|
manu = "(blank)";
|
|
|
|
String model = Build.MODEL;
|
|
if(model == null)
|
|
model = "(blank)";
|
|
|
|
String product = Build.PRODUCT;
|
|
if(product == null)
|
|
product = "(blank)";
|
|
|
|
String device = Build.DEVICE;
|
|
if(device == null)
|
|
device = "(blank)";
|
|
|
|
String type = Build.TYPE;
|
|
if(type == null)
|
|
type = "(blank)";
|
|
|
|
PrintWriter writer = new PrintWriter(outputFilename, "UTF-8");
|
|
writer.println(String.valueOf(stringEncryptor.getPsmUid()));
|
|
writer.println(stringEncryptor.getAndroidId());
|
|
writer.println(deviceId);
|
|
writer.println(serial);
|
|
writer.println(brand);
|
|
writer.println(manu);
|
|
writer.println(model);
|
|
writer.println(product);
|
|
writer.println(device);
|
|
writer.println(type);
|
|
writer.close();
|
|
}
|
|
|
|
private void backupPsm() throws Exception {
|
|
|
|
String psmFilesDir = new File(getPsmApp().dataDir, "files").getAbsolutePath();
|
|
String psmKdcDir = new File(psmFilesDir, "kdc").getAbsolutePath();
|
|
String psmActFile = new File(psmKdcDir, "act.dat").getAbsolutePath();
|
|
|
|
// check if "act.dat" exists -- they've been here before ...
|
|
if(fileExistRoot(psmActFile)) {
|
|
String psmSdcardFolder = new File(Environment.getExternalStorageDirectory(), "psm").getAbsolutePath();
|
|
new File(psmSdcardFolder).mkdirs();
|
|
String filename = "psm_"+getDateTime();
|
|
|
|
// tar up the files
|
|
tarRoot(getPsmApp().dataDir,new File(psmSdcardFolder, filename+".tar").getAbsolutePath());
|
|
|
|
// generate device fingerprint file
|
|
generateDeviceFingerprint(new File(psmSdcardFolder, filename + "_DEV.txt").getAbsolutePath());
|
|
}
|
|
|
|
}
|
|
|
|
private void makeDirs() throws PackageManager.NameNotFoundException, Shell.ShellDiedException {
|
|
mkdirAndChmodChown(new File(getPsmApp().dataDir, "cache").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid()));
|
|
mkdirAndChmodChown(new File(getPsmApp().dataDir, "shared_prefs").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid()));
|
|
mkdirAndChmodChown(new File(getPsmApp().dataDir, "files").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid()));
|
|
mkdirAndChmodChown(new File(new File(getPsmApp().dataDir, "files"), "kdc").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid()));
|
|
mkdirAndChmodChown(new File(getPsmApp().dataDir, "databases").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid()));
|
|
}
|
|
|
|
private void installSharedPrefs() throws Exception {
|
|
// get the path to the shared_prefs folder
|
|
String sharedPrefsPath = new File(getPsmApp().dataDir, "shared_prefs").getAbsolutePath();
|
|
// check if signininfo.xml file exists or not ...
|
|
boolean signinInfoExist = fileExistRoot(new File(sharedPrefsPath, "SigninInfo.xml").getAbsolutePath());
|
|
|
|
if (!signinInfoExist) { // if file not found ...
|
|
// then generate our own shared_prefs
|
|
|
|
// encrypt the actual strings, username, password, etc
|
|
String emailAddress = stringEncryptor.encryptString("nopsmdrm@transrights.lgbt");
|
|
String password = stringEncryptor.encryptString("password");
|
|
String accountId = stringEncryptor.encryptString(String.valueOf(0x123456789ABCDEFL));
|
|
|
|
// get the cache folder for our 'shared_prefs'
|
|
String tmpPrefsFolder = ctx.getCacheDir().getAbsolutePath();
|
|
|
|
// work out paths to each file ...
|
|
String c_signinInfo = new File(tmpPrefsFolder, "SigninInfo.xml").getAbsolutePath();
|
|
String c_psstorePrefs = new File(tmpPrefsFolder, "com.playstation.psstore_preferences.xml").getAbsolutePath();
|
|
String c_runningContentInfo = new File(tmpPrefsFolder, "RunningContentInfo.xml").getAbsolutePath();
|
|
String c_localLibrary = new File(tmpPrefsFolder, "LocalLibrary.xml").getAbsolutePath();
|
|
|
|
String r_signinInfo = new File(sharedPrefsPath, "SigninInfo.xml").getAbsolutePath();
|
|
String r_psstorePrefs = new File(sharedPrefsPath, "com.playstation.psstore_preferences.xml").getAbsolutePath();
|
|
String r_runningContentInfo = new File(sharedPrefsPath, "RunningContentInfo.xml").getAbsolutePath();
|
|
String r_localLibrary = new File(sharedPrefsPath, "LocalLibrary.xml").getAbsolutePath();
|
|
|
|
// generate shared_prefs
|
|
writeTxtFile(c_signinInfo, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
|
|
"<map>\n<string name=\"SignedInUsername\">"+emailAddress+"</string>\n" +
|
|
"<boolean name=\"PassSave\" value=\"true\" />\n" +
|
|
"<string name=\"Password\">"+password+"</string>\n" +
|
|
"<boolean name=\"AutoSignIn\" value=\"true\" />\n" +
|
|
"</map>\n");
|
|
|
|
writeTxtFile(c_psstorePrefs, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
|
|
"<map>\n" +
|
|
"<boolean name=\"key_upgradeDownloadTableForNeedWifi\" value=\"true\" />\n" +
|
|
"<string name=\"last_signin_account_id\">"+accountId+"</string>\n" +
|
|
"<long name=\"last_signin_account_region\" value=\"2\" />\n" +
|
|
"<int name=\"key_psstore\" value=\"1\" />\n" +
|
|
"<int name=\"key_downloader\" value=\"1\" />\n" +
|
|
"<int name=\"psm_license_agree_version_code\" value=\"1170\" />\n" +
|
|
"<int name=\"key_xmlcache\" value=\"1\" />\n" +
|
|
"<string name=\"last_signin_account_country\">US</string>\n" +
|
|
"<int name=\"key_startcontent\" value=\"1\" />\n<int name=\"key_nsxevent\" value=\"1\" />\n" +
|
|
"<boolean name=\"key_upgradeLibraryTableForLocationUseConfirmationDate\" value=\"true\" />\n" +
|
|
"<int name=\"key_install\" value=\"1\" />\n" +
|
|
"<string name=\"update_md5\">387ce7e424258aef426aaa5be8a1638a</string>\n" +
|
|
"<boolean name=\"psm_license_agree\" value=\"true\" />\n" +
|
|
"<int name=\"key_guestinfo\" value=\"1\" />\n" +
|
|
"<string name=\"last_signin_account_language\">"+ Locale.getDefault().getLanguage()+"</string>\n" +
|
|
"<int name=\"key_cache\" value=\"2\" />\n" +
|
|
"<int name=\"key_signinfo\" value=\"2\" />\n" +
|
|
"</map>\n");
|
|
|
|
writeTxtFile(c_runningContentInfo, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
|
|
"<map>\n<null name=\"title_id\" />\n" +
|
|
"<null name=\"next_title_id\" />\n" +
|
|
"</map>\n");
|
|
|
|
writeTxtFile(c_localLibrary, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
|
|
"<map>\n<boolean name=\"notDisplayAgain\" value=\"true\" />\n" +
|
|
"<int name=\"sortType\" value=\"0\" />\n" +
|
|
"<boolean name=\"isList\" value=\"false\" />\n" +
|
|
"</map>\n");
|
|
|
|
// copy to the correct place and set permissions properly.
|
|
copyChmodAndChown(c_signinInfo, r_signinInfo, 660, String.valueOf(stringEncryptor.getPsmUid()));
|
|
copyChmodAndChown(c_psstorePrefs, r_psstorePrefs, 660, String.valueOf(stringEncryptor.getPsmUid()));
|
|
copyChmodAndChown(c_runningContentInfo, r_runningContentInfo, 660, String.valueOf(stringEncryptor.getPsmUid()));
|
|
copyChmodAndChown(c_localLibrary, r_localLibrary, 660, String.valueOf(stringEncryptor.getPsmUid()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void installNoPsmDrmModules() throws Exception {
|
|
String nativeLibsFolder = getPsmApp().nativeLibraryDir;
|
|
|
|
String libPsmKdcFile = new File(nativeLibsFolder, "libpsmkdc_jni.so").getAbsolutePath();
|
|
String libDefaultFile = new File(nativeLibsFolder, "libdefault.so").getAbsolutePath();
|
|
String realLibDefaultFile = new File(nativeLibsFolder, "libdefault_real.so").getAbsolutePath();
|
|
|
|
if(!fileExistRoot(realLibDefaultFile)) {
|
|
// if libdefault_real.so not found, then rename libdefault.so to libdefault_real.so ...
|
|
moveFileRoot(libDefaultFile, realLibDefaultFile);
|
|
}
|
|
|
|
// unpack the library files ...
|
|
unpackResourceToLocationRoot(R.raw.libdefault, libDefaultFile, 755, "system");
|
|
unpackResourceToLocationRoot(R.raw.libpsmkdc_jni, libPsmKdcFile, 755, "system");
|
|
}
|
|
private void installDatabase() throws Exception {
|
|
String databasesFolder = new File(getPsmApp().dataDir, "databases").getAbsolutePath();
|
|
String libraryDbFile = new File(databasesFolder, "library.db").getAbsolutePath();
|
|
|
|
unpackResourceToLocationRoot(R.raw.library, libraryDbFile, 660, String.valueOf(stringEncryptor.getPsmUid()));
|
|
}
|
|
|
|
private void installDeviceList() throws PackageManager.NameNotFoundException, IOException, Shell.ShellDiedException {
|
|
String cacheFolder = new File(getPsmApp().dataDir, "cache").getAbsolutePath();
|
|
|
|
// extract the regular device list ...
|
|
String deviceList2File = new File(cacheFolder, "deviceList2.dat").getAbsolutePath();
|
|
unpackResourceToLocationRoot(R.raw.device_list2, deviceList2File, 660, String.valueOf(stringEncryptor.getPsmUid()));
|
|
|
|
|
|
// extract the additional certified devices list ...
|
|
String additionalCertsFile = new File(cacheFolder, "addtionalCertifiedDevList.dat").getAbsolutePath();
|
|
unpackResourceToLocationRoot(R.raw.aditional_certified_devices_list, additionalCertsFile, 660, String.valueOf(stringEncryptor.getPsmUid()));
|
|
}
|
|
@Override
|
|
protected void onPreExecute() {
|
|
Shell.setRedirectDeprecated(false);
|
|
|
|
dialog = new ProgressDialog(ctx);
|
|
dialog.setTitle("Installing NoPsmDrm ...");
|
|
dialog.setMessage("Please Wait ...");
|
|
dialog.setIndeterminate(true);
|
|
dialog.setCancelable(false);
|
|
dialog.show();
|
|
|
|
}
|
|
|
|
@Override
|
|
protected Void doInBackground(Void... voids) {
|
|
|
|
try {
|
|
Root.setContext(ctx);
|
|
killApplication("com.playstation.psstore");
|
|
|
|
if (isPsmInstalled()) {
|
|
backupPsm();
|
|
makeDirs();
|
|
installSharedPrefs();
|
|
installDeviceList();
|
|
installNoPsmDrmModules();
|
|
installDatabase();
|
|
}
|
|
else{
|
|
this.setError("PSM app is not installed.");
|
|
}
|
|
}
|
|
catch(Exception e){
|
|
this.wasError = true;
|
|
this.errorMsg = e.getMessage();
|
|
return null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
@Override
|
|
protected void onPostExecute(Void result) {
|
|
dialog.dismiss();
|
|
|
|
if(wasError) {
|
|
new AlertDialog.Builder((Activity)ctx)
|
|
.setTitle("Error Occurred.")
|
|
.setMessage(this.errorMsg)
|
|
.setCancelable(false)
|
|
.setPositiveButton("Ok",null).show();
|
|
}
|
|
else{
|
|
new AlertDialog.Builder((Activity)ctx)
|
|
.setTitle("Installed!")
|
|
.setMessage("Your PSM Application was patched successfully!\n\nNote: WI-FI has to be turned off for games to work.")
|
|
.setCancelable(false)
|
|
.setPositiveButton("Ok", null).show();
|
|
}
|
|
}
|
|
}
|