use of java.util.zip.ZipEntry in project tinker by Tencent.
the class DexDiffPatchInternal method extractDexToJar.
/**
* repack dex to jar
*
* @param zipFile
* @param entryFile
* @param extractTo
* @param targetMd5
* @return boolean
* @throws IOException
*/
private static boolean extractDexToJar(ZipFile zipFile, ZipEntry entryFile, File extractTo, String targetMd5) throws IOException {
int numAttempts = 0;
boolean isExtractionSuccessful = false;
while (numAttempts < MAX_EXTRACT_ATTEMPTS && !isExtractionSuccessful) {
numAttempts++;
FileOutputStream fos = new FileOutputStream(extractTo);
InputStream in = zipFile.getInputStream(entryFile);
ZipOutputStream zos = null;
BufferedInputStream bis = null;
TinkerLog.i(TAG, "try Extracting " + extractTo.getPath());
try {
zos = new ZipOutputStream(new BufferedOutputStream(fos));
bis = new BufferedInputStream(in);
byte[] buffer = new byte[ShareConstants.BUFFER_SIZE];
ZipEntry entry = new ZipEntry(ShareConstants.DEX_IN_JAR);
zos.putNextEntry(entry);
int length = bis.read(buffer);
while (length != -1) {
zos.write(buffer, 0, length);
length = bis.read(buffer);
}
zos.closeEntry();
} finally {
SharePatchFileUtil.closeQuietly(bis);
SharePatchFileUtil.closeQuietly(zos);
}
isExtractionSuccessful = SharePatchFileUtil.verifyDexFileMd5(extractTo, targetMd5);
TinkerLog.i(TAG, "isExtractionSuccessful: %b", isExtractionSuccessful);
if (!isExtractionSuccessful) {
extractTo.delete();
if (extractTo.exists()) {
TinkerLog.e(TAG, "Failed to delete corrupted dex " + extractTo.getPath());
}
}
}
return isExtractionSuccessful;
}
use of java.util.zip.ZipEntry in project tinker by Tencent.
the class ResDiffPatchInternal method checkAndExtractResourceLargeFile.
private static boolean checkAndExtractResourceLargeFile(Context context, String apkPath, File directory, File patchFile, ShareResPatchInfo resPatchInfo, int type) {
long start = System.currentTimeMillis();
Tinker manager = Tinker.with(context);
ZipFile apkFile = null;
ZipFile patchZipFile = null;
try {
//recover resources.arsc first
apkFile = new ZipFile(apkPath);
ZipEntry arscEntry = apkFile.getEntry(ShareConstants.RES_ARSC);
File arscFile = new File(directory, ShareConstants.RES_ARSC);
if (arscEntry == null) {
TinkerLog.w(TAG, "resources apk entry is null. path:" + ShareConstants.RES_ARSC);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, arscFile, ShareConstants.RES_ARSC, type);
return false;
}
//use base resources.arsc crc to identify base.apk
String baseArscCrc = String.valueOf(arscEntry.getCrc());
if (!baseArscCrc.equals(resPatchInfo.arscBaseCrc)) {
TinkerLog.e(TAG, "resources.arsc's crc is not equal, expect crc: %s, got crc: %s", resPatchInfo.arscBaseCrc, baseArscCrc);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, arscFile, ShareConstants.RES_ARSC, type);
return false;
}
//resource arsc is not changed, just return true
if (resPatchInfo.largeModRes.isEmpty()) {
TinkerLog.i(TAG, "no large modify resources, just return");
return true;
}
for (String name : resPatchInfo.largeModRes) {
long largeStart = System.currentTimeMillis();
ShareResPatchInfo.LargeModeInfo largeModeInfo = resPatchInfo.largeModMap.get(name);
if (largeModeInfo == null) {
TinkerLog.w(TAG, "resource not found largeModeInfo, type:%s, name: %s", ShareTinkerInternals.getTypeString(type), name);
manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
return false;
}
largeModeInfo.file = new File(directory, name);
SharePatchFileUtil.ensureFileDirectory(largeModeInfo.file);
//we do not check the intermediate files' md5 to save time, use check whether it is 32 length
if (!SharePatchFileUtil.checkIfMd5Valid(largeModeInfo.md5)) {
TinkerLog.w(TAG, "resource meta file md5 mismatch, type:%s, name: %s, md5: %s", ShareTinkerInternals.getTypeString(type), name, largeModeInfo.md5);
manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
return false;
}
patchZipFile = new ZipFile(patchFile);
ZipEntry patchEntry = patchZipFile.getEntry(name);
if (patchEntry == null) {
TinkerLog.w(TAG, "large mod patch entry is null. path:" + name);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, largeModeInfo.file, name, type);
return false;
}
ZipEntry baseEntry = apkFile.getEntry(name);
if (baseEntry == null) {
TinkerLog.w(TAG, "resources apk entry is null. path:" + name);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, largeModeInfo.file, name, type);
return false;
}
InputStream oldStream = null;
InputStream newStream = null;
try {
oldStream = apkFile.getInputStream(baseEntry);
newStream = patchZipFile.getInputStream(patchEntry);
BSPatch.patchFast(oldStream, newStream, largeModeInfo.file);
} finally {
SharePatchFileUtil.closeQuietly(oldStream);
SharePatchFileUtil.closeQuietly(newStream);
}
//go go go bsdiff get the
if (!SharePatchFileUtil.verifyFileMd5(largeModeInfo.file, largeModeInfo.md5)) {
TinkerLog.w(TAG, "Failed to recover large modify file:%s", largeModeInfo.file.getPath());
SharePatchFileUtil.safeDeleteFile(largeModeInfo.file);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, largeModeInfo.file, name, type);
return false;
}
TinkerLog.w(TAG, "success recover large modify file:%s, file size:%d, use time:%d", largeModeInfo.file.getPath(), largeModeInfo.file.length(), (System.currentTimeMillis() - largeStart));
}
TinkerLog.w(TAG, "success recover all large modify use time:%d", (System.currentTimeMillis() - start));
} catch (Throwable e) {
// e.printStackTrace();
throw new TinkerRuntimeException("patch " + ShareTinkerInternals.getTypeString(type) + " extract failed (" + e.getMessage() + ").", e);
} finally {
SharePatchFileUtil.closeZip(apkFile);
SharePatchFileUtil.closeZip(patchZipFile);
}
return true;
}
use of java.util.zip.ZipEntry in project tinker by Tencent.
the class SharePatchFileUtil method verifyDexFileMd5.
/**
* Returns whether the dex file is a valid file.
* dex may wrap with jar
*/
public static boolean verifyDexFileMd5(File file, String md5) {
if (file == null || md5 == null) {
return false;
}
//if it is not the raw dex, we check the stream instead
String fileMd5;
if (isRawDexFile(file.getName())) {
fileMd5 = getMD5(file);
} else {
ZipFile dexJar = null;
try {
dexJar = new ZipFile(file);
ZipEntry classesDex = dexJar.getEntry(ShareConstants.DEX_IN_JAR);
// no code
if (null == classesDex) {
Log.e(TAG, "There's no entry named: " + ShareConstants.DEX_IN_JAR + " in " + file.getAbsolutePath());
return false;
}
fileMd5 = getMD5(dexJar.getInputStream(classesDex));
} catch (Throwable e) {
Log.e(TAG, "Bad dex jar file: " + file.getAbsolutePath(), e);
return false;
} finally {
// SharePatchFileUtil.closeZip(dexJar);
if (dexJar != null) {
try {
dexJar.close();
} catch (Throwable thr) {
// Ignored.
}
}
}
}
return md5.equals(fileMd5);
}
use of java.util.zip.ZipEntry in project tinker by Tencent.
the class SharePatchFileUtil method checkResourceArscMd5.
public static boolean checkResourceArscMd5(File resOutput, String destMd5) {
ZipFile resourceZip = null;
try {
resourceZip = new ZipFile(resOutput);
ZipEntry arscEntry = resourceZip.getEntry(ShareConstants.RES_ARSC);
if (arscEntry == null) {
Log.i(TAG, "checkResourceArscMd5 resources.arsc not found");
return false;
}
InputStream inputStream = null;
try {
inputStream = resourceZip.getInputStream(arscEntry);
String md5 = SharePatchFileUtil.getMD5(inputStream);
if (md5 != null && md5.equals(destMd5)) {
return true;
}
} finally {
SharePatchFileUtil.closeQuietly(inputStream);
}
} catch (Throwable e) {
Log.i(TAG, "checkResourceArscMd5 throwable:" + e.getMessage());
} finally {
SharePatchFileUtil.closeZip(resourceZip);
}
return false;
}
use of java.util.zip.ZipEntry in project tinker by Tencent.
the class FileUtil method differZip.
/**
* differ zip
*
* @param differentOutputFullFilename
* @param oldZipFullFilename
* @param newZipFullFilename
*/
public static void differZip(String differentOutputFullFilename, String oldZipFullFilename, String newZipFullFilename) {
Map<String, String> map = getZipEntryHashMap(oldZipFullFilename);
ZipFile newZipFile = null;
ZipOutputStream zipOutputStream = null;
try {
newZipFile = new ZipFile(newZipFullFilename);
Enumeration<? extends ZipEntry> entries = newZipFile.entries();
FileUtil.createFile(differentOutputFullFilename);
zipOutputStream = new ZipOutputStream(new FileOutputStream(differentOutputFullFilename));
while (entries.hasMoreElements()) {
ZipEntry zipEntry = entries.nextElement();
if (!zipEntry.isDirectory()) {
String zipEntryName = zipEntry.getName();
String oldZipEntryHash = map.get(zipEntryName);
String newZipEntryHash = zipEntry.getCrc() + Constant.Symbol.DOT + zipEntry.getSize();
// is a modified zip entry
if (oldZipEntryHash == null || (!newZipEntryHash.equals(oldZipEntryHash))) {
System.out.println(String.format("found modified entry, key=%s(%s/%s)", new Object[] { zipEntryName, oldZipEntryHash, newZipEntryHash }));
addZipEntry(zipOutputStream, zipEntry, newZipFile.getInputStream(zipEntry));
}
}
}
} catch (Exception e) {
throw new FileUtilException(e);
} finally {
if (newZipFile != null) {
try {
newZipFile.close();
} catch (IOException e) {
throw new FileUtilException(e);
}
}
if (zipOutputStream != null) {
try {
zipOutputStream.finish();
} catch (IOException e) {
throw new FileUtilException(e);
}
}
}
}
Aggregations