该IPAUtil主要是两个功能。一是解析plist文件,获取版本号、名字、图标等信息。二是解析embedded.mobileprovision文件,获取证书的过期时间。
public class IPAUtil {
private static org.slf4j.Logger logger = LoggerFactory.getLogger(IPAUtil.class);
/**
* 读取ipa
*/
public static IPA readIPA(File ipaFile) throws Exception {
try (ZipFile zipFile = new ZipFile(ipaFile)) {
NSDictionary rootDict = null;
InputStream mobileProvision = null;
Enumeration e = zipFile.entries();
while (e.hasMoreElements()) {
ZipEntry ze = (ZipEntry) e.nextElement();
if (ze.isDirectory()) {
continue;
}
String name = ze.getName();
if (name != null && name.toLowerCase().contains(".app/info.plist")) {
rootDict = (NSDictionary) PropertyListParser.parse(zipFile.getInputStream(ze));
}
if (name != null && name.toLowerCase().contains(".app/embedded.mobileprovision")) {
mobileProvision = zipFile.getInputStream(ze);
}
}
if (rootDict == null) {
throw new WithOutPlistException("can't find info.plist");
}
if (mobileProvision == null) {
throw new WithOutMobileProvisionException("can't find embedded.mobileprovision");
}
IPA ipa = rootDict.toJavaObject(IPA.class)
.setIcons(getIcons(rootDict))
.setExpirationDate(getExpirationDate(mobileProvision));
return ipa;
}
}
public static void main(String[] args) throws Exception {
// IPAUtil ipaUtil = new IPAUtil();
//
// logger.info(ipaUtil.readIPA(new File("d:\\yl1794\\Desktop\\IOS_plist\\Odin-UC.ipa")).toString());
//
String time = "2019-07-22T13:38:07Z";
//
System.out.println(UTCToLong(time));
System.out.println(DateUtil.parseDate("2019-07-22T13:38:07Z"));
}
//----------------------------------private-----------------------------------------
private static List<String> getIcons(NSDictionary rootDict) {
NSDictionary iconDict = (NSDictionary) rootDict.get("CFBundleIcons");
if (iconDict == null) {
return Collections.emptyList();
}
NSDictionary CFBundlePrimaryIcon = (NSDictionary) iconDict.get("CFBundlePrimaryIcon");
if (CFBundlePrimaryIcon == null) {
return Collections.emptyList();
}
List<String> icons = new ArrayList<>();
NSArray CFBundleIconFiles = (NSArray) CFBundlePrimaryIcon.get("CFBundleIconFiles");
for (NSObject nsObject : CFBundleIconFiles.getArray()) {
icons.add(nsObject.toString().replace(".png", ""));
}
return icons;
}
private static Long getExpirationDate(InputStream mobileProvision) {
String key = "<key>ExpirationDate</key>";
String reg = "^<date>";
int regLength = reg.length();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(mobileProvision))) {
String line = null;
boolean flag = false;
while ((line = reader.readLine()) != null) {
if (!flag) {
flag = line.contains(key);
}
if (ValidateUtil.match(line.trim(), reg) && flag) {
return UTCToLong(line.substring(regLength, line.length() - regLength));
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* UTC时间转时间戳
*/
private static Long UTCToLong(String time) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
Date date = df.parse(time);
logger.info("ExpirationDate: {}", date.toString());
return date.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
其中IPA对象为:
@Data
@Accessors(chain = true)
public class IPA {
private String CFBundleIdentifier;
private String CFBundleShortVersionString;
private String CFBundleVersion;
private String CFBundleDisplayName;
private List<String> icons;
private Long ExpirationDate;
}