diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java index b5f5e263..fca8c8e2 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java @@ -17,6 +17,8 @@ package brut.androlib; import brut.androlib.java.AndrolibJava; +import brut.androlib.meta.MetaInfo; +import brut.androlib.meta.UsesFramework; import brut.androlib.res.AndrolibResources; import brut.androlib.res.data.ResPackage; import brut.androlib.res.data.ResTable; @@ -30,7 +32,6 @@ import brut.directory.*; import brut.util.BrutIO; import brut.util.OS; import java.io.*; -import java.nio.charset.StandardCharsets; import java.util.*; import java.util.logging.Logger; import java.util.regex.Pattern; @@ -40,9 +41,6 @@ import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; /** * @author Ryszard Wiśniewski @@ -239,33 +237,21 @@ public class Androlib { } } - public void writeMetaFile(File mOutDir, Map meta) + public void writeMetaFile(File mOutDir, MetaInfo meta) throws AndrolibException { - DumperOptions options = new DumperOptions(); - options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - Yaml yaml = new Yaml(options); - - try ( - Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream( - new File(mOutDir, "apktool.yml")), "UTF-8")) - ) { - yaml.dump(meta, writer); + try{ + meta.save(new File(mOutDir, "apktool.yml")); } catch (IOException ex) { throw new AndrolibException(ex); } } - public Map readMetaFile(ExtFile appDir) + public MetaInfo readMetaFile(ExtFile appDir) throws AndrolibException { try( InputStream in = appDir.getDirectory().getFileInput("apktool.yml") ) { - Yaml yaml = new Yaml(); - Map result = (Map) yaml.load(in); - if (result.containsKey("unknownFiles")) { - result.put("unknownFiles", getUnknownFiles(result)); - } - return result; + return MetaInfo.load(in); } catch (DirectoryException | IOException ex) { throw new AndrolibException(ex); } @@ -279,22 +265,19 @@ public class Androlib { throws BrutException { LOGGER.info("Using Apktool " + Androlib.getVersion()); - Map meta = readMetaFile(appDir); - Object t1 = meta.get("isFrameworkApk"); - apkOptions.isFramework = (t1 == null ? false : (Boolean) t1); - apkOptions.resourcesAreCompressed = meta.get("compressionType") == null - ? false - : Boolean.valueOf(meta.get("compressionType").toString()); - apkOptions.doNotCompress = (Collection) meta.get("doNotCompress"); + MetaInfo meta = readMetaFile(appDir); + apkOptions.isFramework = meta.isFrameworkApk; + apkOptions.resourcesAreCompressed = meta.compressionType; + apkOptions.doNotCompress = meta.doNotCompress; - mAndRes.setSdkInfo((Map) meta.get("sdkInfo")); - mAndRes.setPackageId((Map) meta.get("packageInfo")); - mAndRes.setPackageInfo((Map) meta.get("packageInfo")); - mAndRes.setVersionInfo((Map) meta.get("versionInfo")); - mAndRes.setSharedLibrary((boolean) (meta.get("sharedLibrary") == null ? false : meta.get("sharedLibrary"))); + mAndRes.setSdkInfo(meta.sdkInfo); + mAndRes.setPackageId(meta.packageInfo); + mAndRes.setPackageRenamed(meta.packageInfo); + mAndRes.setVersionInfo(meta.versionInfo); + mAndRes.setSharedLibrary(meta.sharedLibrary); if (outFile == null) { - String outFileName = (String) meta.get("apkFileName"); + String outFileName = meta.apkFileName; outFile = new File(appDir, "dist" + File.separator + (outFileName == null ? "out.apk" : outFileName)); } @@ -302,7 +285,7 @@ public class Androlib { buildSources(appDir); buildNonDefaultSources(appDir); ResXmlPatcher.fixingPublicAttrsInProviderAttributes(new File(appDir, "AndroidManifest.xml")); - buildResources(appDir, (Map) meta.get("usesFramework")); + buildResources(appDir, meta.usesFramework); buildLib(appDir); buildLibs(appDir); @@ -412,7 +395,7 @@ public class Androlib { return true; } - public void buildResources(ExtFile appDir, Map usesFramework) + public void buildResources(ExtFile appDir, UsesFramework usesFramework) throws BrutException { if (!buildResourcesRaw(appDir) && !buildResourcesFull(appDir, usesFramework) && !buildManifest(appDir, usesFramework)) { @@ -441,7 +424,7 @@ public class Androlib { } } - public boolean buildResourcesFull(File appDir, Map usesFramework) + public boolean buildResourcesFull(File appDir, UsesFramework usesFramework) throws AndrolibException { try { if (!new File(appDir, "res").exists()) { @@ -492,7 +475,7 @@ public class Androlib { } } - public boolean buildManifest(ExtFile appDir, Map usesFramework) + public boolean buildManifest(ExtFile appDir, UsesFramework usesFramework) throws BrutException { try { if (!new File(appDir, "AndroidManifest.xml").exists()) { @@ -587,12 +570,12 @@ public class Androlib { } } - public void buildUnknownFiles(File appDir, File outFile, Map meta) + public void buildUnknownFiles(File appDir, File outFile, MetaInfo meta) throws AndrolibException { - if (meta.containsKey("unknownFiles")) { + if (meta.unknownFiles != null) { LOGGER.info("Copying unknown files/dir..."); - Map files = (Map)meta.get("unknownFiles"); + Map files = meta.unknownFiles; File tempFile = new File(outFile.getParent(), outFile.getName() + ".apktool_temp"); boolean renamed = outFile.renameTo(tempFile); if(!renamed) { @@ -703,18 +686,18 @@ public class Androlib { return ApktoolProperties.get("application.version"); } - private File[] parseUsesFramework(Map usesFramework) + private File[] parseUsesFramework(UsesFramework usesFramework) throws AndrolibException { if (usesFramework == null) { return null; } - List ids = (List) usesFramework.get("ids"); + List ids = usesFramework.ids; if (ids == null || ids.isEmpty()) { return null; } - String tag = (String) usesFramework.get("tag"); + String tag = usesFramework.tag; File[] files = new File[ids.size()]; int i = 0; for (int id : ids) { @@ -744,15 +727,6 @@ public class Androlib { return files; } - private static Map getUnknownFiles(Map meta) { - Map unknownFiles = (Map) meta.get("unknownFiles"); - Map result = new LinkedHashMap<>(); - for (Map.Entry entry : unknownFiles.entrySet()) { - result.put(new String(entry.getKey(), StandardCharsets.UTF_8), entry.getValue()); - } - return result; - } - private final static Logger LOGGER = Logger.getLogger(Androlib.class.getName()); private final static String SMALI_DIRNAME = "smali"; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index 03febf48..40965bb9 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -19,6 +19,9 @@ package brut.androlib; import brut.androlib.err.InFileNotFoundException; import brut.androlib.err.OutDirExistsException; import brut.androlib.err.UndefinedResObject; +import brut.androlib.meta.MetaInfo; +import brut.androlib.meta.PackageInfo; +import brut.androlib.meta.UsesFramework; import brut.androlib.res.AndrolibResources; import brut.androlib.res.data.ResPackage; import brut.androlib.res.data.ResTable; @@ -298,12 +301,12 @@ public class ApkDecoder { } private void writeMetaFile() throws AndrolibException { - Map meta = new LinkedHashMap(); - meta.put("version", Androlib.getVersion()); - meta.put("apkFileName", mApkFile.getName()); + MetaInfo meta = new MetaInfo(); + meta.version = Androlib.getVersion(); + meta.apkFileName = mApkFile.getName(); if (mDecodeResources != DECODE_RESOURCES_NONE && (hasManifest() || hasResources())) { - meta.put("isFrameworkApk", mAndrolib.isFrameworkApk(getResTable())); + meta.isFrameworkApk = mAndrolib.isFrameworkApk(getResTable()); putUsesFramework(meta); putSdkInfo(meta); putPackageInfo(meta); @@ -316,7 +319,7 @@ public class ApkDecoder { mAndrolib.writeMetaFile(mOutDir, meta); } - private void putUsesFramework(Map meta) throws AndrolibException { + private void putUsesFramework(MetaInfo meta) throws AndrolibException { Set pkgs = getResTable().listFramePackages(); if (pkgs.isEmpty()) { return; @@ -329,24 +332,22 @@ public class ApkDecoder { } Arrays.sort(ids); - Map uses = new LinkedHashMap(); - uses.put("ids", ids); + meta.usesFramework = new UsesFramework(); + meta.usesFramework.ids = Arrays.asList(ids); if (mAndrolib.apkOptions.frameworkTag != null) { - uses.put("tag", mAndrolib.apkOptions.frameworkTag); + meta.usesFramework.tag = mAndrolib.apkOptions.frameworkTag; } - - meta.put("usesFramework", uses); } - private void putSdkInfo(Map meta) throws AndrolibException { + private void putSdkInfo(MetaInfo meta) throws AndrolibException { Map info = getResTable().getSdkInfo(); if (info.size() > 0) { - meta.put("sdkInfo", info); + meta.sdkInfo = info; } } - private void putPackageInfo(Map meta) throws AndrolibException { + private void putPackageInfo(MetaInfo meta) throws AndrolibException { String renamed = getResTable().getPackageRenamed(); String original = getResTable().getPackageOriginal(); @@ -355,42 +356,35 @@ public class ApkDecoder { id = getResTable().getPackage(renamed).getId(); } catch (UndefinedResObject ignored) {} - HashMap packages = new HashMap(); - if (Strings.isNullOrEmpty(original)) { return; } + meta.packageInfo = new PackageInfo(); + // only put rename-manifest-package into apktool.yml, if the change will be required if (!renamed.equalsIgnoreCase(original)) { - packages.put("rename-manifest-package", renamed); + meta.packageInfo.renameManifestPackage = renamed; } - packages.put("forced-package-id", String.valueOf(id)); - meta.put("packageInfo", packages); + meta.packageInfo.forcedPackageId = String.valueOf(id); } - private void putVersionInfo(Map meta) throws AndrolibException { - Map info = getResTable().getVersionInfo(); - if (info.size() > 0) { - meta.put("versionInfo", info); - } + private void putVersionInfo(MetaInfo meta) throws AndrolibException { + meta.versionInfo = getResTable().getVersionInfo(); } - private void putUnknownInfo(Map meta) throws AndrolibException { - Map info = mAndrolib.mResUnknownFiles.getUnknownFiles(); - if (info.size() > 0) { - meta.put("unknownFiles", info); - } + private void putUnknownInfo(MetaInfo meta) throws AndrolibException { + meta.unknownFiles = mAndrolib.mResUnknownFiles.getUnknownFiles(); } - private void putFileCompressionInfo(Map meta) throws AndrolibException { + private void putFileCompressionInfo(MetaInfo meta) throws AndrolibException { if (!mUncompressedFiles.isEmpty()) { - meta.put("doNotCompress", mUncompressedFiles); + meta.doNotCompress = mUncompressedFiles; } } - private void putSharedLibraryInfo(Map meta) throws AndrolibException { - meta.put("sharedLibrary", mResTable.getSharedLibrary()); + private void putSharedLibraryInfo(MetaInfo meta) throws AndrolibException { + meta.sharedLibrary = mResTable.getSharedLibrary(); } private final Androlib mAndrolib; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/MetaInfo.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/MetaInfo.java new file mode 100644 index 00000000..95096d9d --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/MetaInfo.java @@ -0,0 +1,66 @@ +package brut.androlib.meta; + +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.introspector.PropertyUtils; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Map; + +/** + * Created by rover12421 on 1/6/16. + */ +public class MetaInfo { + public String version; + public String apkFileName; + public boolean isFrameworkApk; + public UsesFramework usesFramework; + public Map sdkInfo; + public PackageInfo packageInfo; + public VersionInfo versionInfo; + public boolean compressionType; + public boolean sharedLibrary; + public Map unknownFiles; + public Collection doNotCompress; + + private static Yaml getYaml() { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + + StringExRepresent representer = new StringExRepresent(); + PropertyUtils propertyUtils = representer.getPropertyUtils(); + propertyUtils.setSkipMissingProperties(true); + + return new Yaml(new StringExConstructor(), representer, options); + } + + public void save(Writer output) { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + getYaml().dump(this, output); + } + + public void save(File file) throws IOException { + try( + FileOutputStream fos = new FileOutputStream(file); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fos, StandardCharsets.UTF_8); + Writer writer = new BufferedWriter(outputStreamWriter) + ){ + save(writer); + } + } + + public static MetaInfo load(InputStream is) { + return getYaml().loadAs(is, MetaInfo.class); + } + + public static MetaInfo load(File file) throws IOException { + try ( + InputStream fis = new FileInputStream(file) + ){ + return load(fis); + } + } +} diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/PackageInfo.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/PackageInfo.java new file mode 100644 index 00000000..fff48594 --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/PackageInfo.java @@ -0,0 +1,9 @@ +package brut.androlib.meta; + +/** + * Created by rover12421 on 1/6/16. + */ +public class PackageInfo { + public String forcedPackageId; + public String renameManifestPackage; +} diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/StringExConstructor.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/StringExConstructor.java new file mode 100644 index 00000000..665c0a20 --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/StringExConstructor.java @@ -0,0 +1,23 @@ +package brut.androlib.meta; + +import org.yaml.snakeyaml.constructor.AbstractConstruct; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.nodes.Node; +import org.yaml.snakeyaml.nodes.ScalarNode; +import org.yaml.snakeyaml.nodes.Tag; + +/** + * Created by rover12421 on 1/7/16. + */ +public class StringExConstructor extends Constructor { + public StringExConstructor() { + this.yamlConstructors.put(Tag.STR, new ConstructStringEx()); + } + + private class ConstructStringEx extends AbstractConstruct { + public Object construct(Node node) { + String val = (String) constructScalar((ScalarNode)node); + return YamlStringEscapeUtils.unescapeString(val); + } + } +} \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/StringExRepresent.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/StringExRepresent.java new file mode 100644 index 00000000..5f7708c0 --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/StringExRepresent.java @@ -0,0 +1,23 @@ +package brut.androlib.meta; + +import org.yaml.snakeyaml.nodes.Node; +import org.yaml.snakeyaml.representer.Representer; + +/** + * Created by rover12421 on 1/7/16. + */ +public class StringExRepresent extends Representer { + public StringExRepresent() { + RepresentStringEx representStringEx = new RepresentStringEx(); + multiRepresenters.put(String.class, representStringEx); + representers.put(String.class, representStringEx); + } + + private class RepresentStringEx extends RepresentString { + + @Override + public Node representData(Object data) { + return super.representData(YamlStringEscapeUtils.escapeString(data.toString())); + } + } +} diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/UsesFramework.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/UsesFramework.java new file mode 100644 index 00000000..eac37534 --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/UsesFramework.java @@ -0,0 +1,11 @@ +package brut.androlib.meta; + +import java.util.List; + +/** + * Created by rover12421 on 1/6/16. + */ +public class UsesFramework { + public List ids; + public String tag; +} diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/VersionInfo.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/VersionInfo.java new file mode 100644 index 00000000..ae1a4f91 --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/VersionInfo.java @@ -0,0 +1,9 @@ +package brut.androlib.meta; + +/** + * Created by rover12421 on 1/6/16. + */ +public class VersionInfo { + public String versionCode; + public String versionName; +} diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/YamlStringEscapeUtils.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/YamlStringEscapeUtils.java new file mode 100644 index 00000000..86e1de6b --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/meta/YamlStringEscapeUtils.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package brut.androlib.meta; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.text.translate.CharSequenceTranslator; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; + +public class YamlStringEscapeUtils { + + public static String escapeString(String str) { + return escapeJavaStyleString(str, false, false); + } + + /** + * @param str String to escape values in, may be null + * @param escapeSingleQuotes escapes single quotes if true + * @param escapeForwardSlash TODO + * @return the escaped string + */ + private static String escapeJavaStyleString(String str, boolean escapeSingleQuotes, boolean escapeForwardSlash) { + if (str == null) { + return null; + } + try { + StringWriter writer = new StringWriter(str.length() * 2); + escapeJavaStyleString(writer, str, escapeSingleQuotes, escapeForwardSlash); + return writer.toString(); + } catch (IOException ioe) { + // this should never ever happen while writing to a StringWriter + throw new RuntimeException(ioe); + } + } + + /** + * @param out write to receieve the escaped string + * @param str String to escape values in, may be null + * @param escapeSingleQuote escapes single quotes if true + * @param escapeForwardSlash TODO + * @throws IOException if an IOException occurs + */ + private static void escapeJavaStyleString(Writer out, String str, boolean escapeSingleQuote, + boolean escapeForwardSlash) throws IOException { + if (out == null) { + throw new IllegalArgumentException("The Writer must not be null"); + } + if (str == null) { + return; + } + int sz; + sz = str.length(); + for (int i = 0; i < sz; i++) { + char ch = str.charAt(i); +// "[^\t\n\r\u0020-\u007E\u0085\u00A0-\uD7FF\uE000-\uFFFD]" + // handle unicode + if (ch > 0xFFFD) { + out.write("\\u" + CharSequenceTranslator.hex(ch)); + } else if (ch > 0xD7FF && ch < 0xE000) { + out.write("\\u" + CharSequenceTranslator.hex(ch)); + } else if (ch > 0x7E && ch != 0x85 && ch < 0xA0) { + out.write("\\u00" + CharSequenceTranslator.hex(ch)); + } else if (ch < 32) { + switch (ch) { + case '\t' : + out.write('\\'); + out.write('t'); + break; + case '\n' : + out.write('\\'); + out.write('n'); + break; + case '\r' : + out.write('\\'); + out.write('r'); + break; + default : + if (ch > 0xf) { + out.write("\\u00" + CharSequenceTranslator.hex(ch)); + } else { + out.write("\\u000" + CharSequenceTranslator.hex(ch)); + } + break; + } + } else { + switch (ch) { + case '\'' : + if (escapeSingleQuote) { + out.write('\\'); + } + out.write('\''); + break; + case '"' : + out.write('\\'); + out.write('"'); + break; + case '\\' : + out.write('\\'); + out.write('\\'); + break; + case '/' : + if (escapeForwardSlash) { + out.write('\\'); + } + out.write('/'); + break; + default : + out.write(ch); + break; + } + } + } + } + + /** + *

Unescapes any Java literals found in the String. + * For example, it will turn a sequence of '\' and + * 'n' into a newline character, unless the '\' + * is preceded by another '\'.

+ * + * @param str the String to unescape, may be null + * @return a new unescaped String, null if null string input + */ + public static String unescapeString(String str) { + return StringEscapeUtils.unescapeJava(str); + } +} \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java index 0edaff48..428e6752 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java @@ -19,26 +19,35 @@ package brut.androlib.res; import brut.androlib.AndrolibException; import brut.androlib.ApkOptions; import brut.androlib.err.CantFindFrameworkResException; +import brut.androlib.meta.PackageInfo; +import brut.androlib.meta.VersionInfo; import brut.androlib.res.data.*; import brut.androlib.res.decoder.*; import brut.androlib.res.decoder.ARSCDecoder.ARSCData; import brut.androlib.res.decoder.ARSCDecoder.FlagsOffset; -import brut.androlib.res.util.*; +import brut.androlib.res.util.ExtFile; +import brut.androlib.res.util.ExtMXSerializer; +import brut.androlib.res.util.ExtXmlSerializer; import brut.androlib.res.xml.ResValuesXmlSerializable; import brut.androlib.res.xml.ResXmlPatcher; import brut.common.BrutException; -import brut.directory.*; -import brut.util.*; +import brut.directory.Directory; +import brut.directory.DirectoryException; +import brut.directory.FileDirectory; +import brut.util.Duo; +import brut.util.Jar; +import brut.util.OS; +import brut.util.OSDetection; +import org.apache.commons.io.IOUtils; +import org.xmlpull.v1.XmlSerializer; + import java.io.*; import java.util.*; import java.util.logging.Logger; -import java.util.zip.*; - -import java.io.File; -import java.io.IOException; - -import org.apache.commons.io.IOUtils; -import org.xmlpull.v1.XmlSerializer; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; /** * @author Ryszard Wiśniewski @@ -268,22 +277,22 @@ final public class AndrolibResources { } } - public void setVersionInfo(Map map) { - if (map != null) { - mVersionCode = map.get("versionCode"); - mVersionName = map.get("versionName"); + public void setVersionInfo(VersionInfo versionInfo) { + if (versionInfo != null) { + mVersionCode = versionInfo.versionCode; + mVersionName = versionInfo.versionName; } } - public void setPackageInfo(Map map) { - if (map != null) { - mPackageRenamed = map.get("rename-manifest-package"); + public void setPackageRenamed(PackageInfo packageInfo) { + if (packageInfo != null) { + mPackageRenamed = packageInfo.renameManifestPackage; } } - public void setPackageId(Map map) { - if (map != null) { - mPackageId = map.get("forced-package-id"); + public void setPackageId(PackageInfo packageInfo) { + if (packageInfo != null) { + mPackageId = packageInfo.forcedPackageId; } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java index 2d56363a..b376973e 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java @@ -18,6 +18,7 @@ package brut.androlib.res.data; import brut.androlib.AndrolibException; import brut.androlib.err.UndefinedResObject; +import brut.androlib.meta.VersionInfo; import brut.androlib.res.AndrolibResources; import brut.androlib.res.data.value.ResValue; import java.util.*; @@ -39,8 +40,8 @@ public class ResTable { private boolean mAnalysisMode = false; private boolean mSharedLibrary = false; - private Map mSdkInfo = new LinkedHashMap(); - private Map mVersionInfo = new LinkedHashMap(); + private Map mSdkInfo = new LinkedHashMap<>(); + private VersionInfo mVersionInfo = new VersionInfo(); public ResTable() { mAndRes = null; @@ -174,11 +175,15 @@ public class ResTable { mSdkInfo.put(key, value); } - public void addVersionInfo(String key, String value) { - mVersionInfo.put(key, value); + public void setVersionName(String versionName) { + mVersionInfo.versionName = versionName; } - public Map getVersionInfo() { + public void setVersionCode(String versionCode) { + mVersionInfo.versionCode = versionCode; + } + + public VersionInfo getVersionInfo() { return mVersionInfo; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResUnknownFiles.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResUnknownFiles.java index 5d6f79f2..86ad11a0 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResUnknownFiles.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResUnknownFiles.java @@ -15,7 +15,6 @@ */ package brut.androlib.res.data; -import java.nio.charset.StandardCharsets; import java.util.LinkedHashMap; import java.util.Map; @@ -24,13 +23,13 @@ import java.util.Map; */ public class ResUnknownFiles { - private final Map mUnknownFiles = new LinkedHashMap(); + private final Map mUnknownFiles = new LinkedHashMap<>(); public void addUnknownFileInfo(String file, String value) { - mUnknownFiles.put(file.getBytes(StandardCharsets.UTF_8), value); + mUnknownFiles.put(file, value); } - public Map getUnknownFiles() { + public Map getUnknownFiles() { return mUnknownFiles; } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index 497433f3..0ac4d25b 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -21,15 +21,20 @@ import brut.androlib.AndrolibException; import brut.androlib.res.data.*; import brut.androlib.res.data.value.*; import brut.util.Duo; -import brut.androlib.res.data.ResTable; import brut.util.ExtDataInput; import com.mindprod.ledatastream.LEDataInputStream; -import java.io.*; -import java.math.BigInteger; -import java.util.*; -import java.util.logging.Logger; import org.apache.commons.io.input.CountingInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Logger; + /** * @author Ryszard Wiśniewski */ diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java index 6a72e406..671a7b6e 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java @@ -94,9 +94,9 @@ public class XmlPullStreamDecoder implements ResStreamDecoder { if (attr_name.equalsIgnoreCase(("package"))) { resTable.setPackageRenamed(pp.getAttributeValue(i)); } else if (attr_name.equalsIgnoreCase("versionCode")) { - resTable.addVersionInfo("versionCode", pp.getAttributeValue(i)); + resTable.setVersionCode(pp.getAttributeValue(i)); } else if (attr_name.equalsIgnoreCase("versionName")) { - resTable.addVersionInfo("versionName", pp.getAttributeValue(i)); + resTable.setVersionName(pp.getAttributeValue(i)); } } return true; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java index c497f442..bbdb7788 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java @@ -20,17 +20,19 @@ import brut.androlib.AndrolibException; import brut.androlib.mod.SmaliMod; import brut.androlib.res.util.ExtFile; import brut.directory.DirectoryException; -import java.io.*; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.logging.Logger; - import org.antlr.runtime.RecognitionException; import org.apache.commons.io.IOUtils; import org.jf.dexlib2.writer.builder.DexBuilder; import org.jf.dexlib2.writer.io.FileDataStore; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.ListIterator; +import java.util.logging.Logger; + /** * @author Ryszard Wiśniewski */ diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java index e6501655..0bf38b55 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java @@ -15,6 +15,7 @@ */ package brut.androlib; +import brut.androlib.meta.MetaInfo; import brut.androlib.res.util.ExtFile; import brut.common.BrutException; import brut.directory.FileDirectory; @@ -340,13 +341,13 @@ public class BuildAndDecodeTest { @SuppressWarnings("unchecked") private void compareUnknownFiles() throws BrutException, IOException { - Map control = new Androlib().readMetaFile(sTestOrigDir); - Map test = new Androlib().readMetaFile(sTestNewDir); - assertTrue(control.containsKey("unknownFiles")); - assertTrue(test.containsKey("unknownFiles")); + MetaInfo control = new Androlib().readMetaFile(sTestOrigDir); + MetaInfo test = new Androlib().readMetaFile(sTestNewDir); + assertNotNull(control.unknownFiles); + assertNotNull(test.unknownFiles); - Map control_files = (Map)control.get("unknownFiles"); - Map test_files = (Map)test.get("unknownFiles"); + Map control_files = control.unknownFiles; + Map test_files = test.unknownFiles; assertTrue(control_files.size() == test_files.size()); // Make sure that the compression methods are still the same diff --git a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/apktool.yml index f6c21e0e..6386e2ce 100644 --- a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/apktool.yml +++ b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/apktool.yml @@ -11,8 +11,8 @@ versionInfo: versionName: '1.0' compressionType: false unknownFiles: - !!binary "aGlkZGVuLmZpbGU=": '8' - !!binary "bm9uf3ByaW50YWJsZS5maWxl": '8' - !!binary "c3RvcmVkLmZpbGU=": '0' - !!binary "dW5rX2ZvbGRlci91bmtub3duX2ZpbGU=": '8' - !!binary "bGliX2J1ZzYwMy9idWc2MDM=": '8' \ No newline at end of file + hidden.file: '8' + non\u007Fprintable.file: '8' + stored.file: '0' + unk_folder/unknown_file: '8' + lib_bug603/bug603: '8' \ No newline at end of file