Apktool.yml file (MetaInfo) using object serialization

non-printable character more intuitive, does not affect printable
character view
This commit is contained in:
Rover12421 2016-01-07 15:35:56 +08:00 committed by Connor Tumbleson
parent 81404c8904
commit 123912d226
17 changed files with 411 additions and 138 deletions

View File

@ -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 <brut.alll@gmail.com>
@ -239,33 +237,21 @@ public class Androlib {
}
}
public void writeMetaFile(File mOutDir, Map<String, Object> 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<String, Object> readMetaFile(ExtFile appDir)
public MetaInfo readMetaFile(ExtFile appDir)
throws AndrolibException {
try(
InputStream in = appDir.getDirectory().getFileInput("apktool.yml")
) {
Yaml yaml = new Yaml();
Map<String, Object> result = (Map<String, Object>) 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<String, Object> 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<String>) meta.get("doNotCompress");
MetaInfo meta = readMetaFile(appDir);
apkOptions.isFramework = meta.isFrameworkApk;
apkOptions.resourcesAreCompressed = meta.compressionType;
apkOptions.doNotCompress = meta.doNotCompress;
mAndRes.setSdkInfo((Map<String, String>) meta.get("sdkInfo"));
mAndRes.setPackageId((Map<String, String>) meta.get("packageInfo"));
mAndRes.setPackageInfo((Map<String, String>) meta.get("packageInfo"));
mAndRes.setVersionInfo((Map<String, String>) 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<String, Object>) 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, String> files = (Map<String, String>)meta.get("unknownFiles");
Map<String, String> 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<String, Object> usesFramework)
private File[] parseUsesFramework(UsesFramework usesFramework)
throws AndrolibException {
if (usesFramework == null) {
return null;
}
List<Integer> ids = (List<Integer>) usesFramework.get("ids");
List<Integer> 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<String, String> getUnknownFiles(Map<String, Object> meta) {
Map<byte[], String> unknownFiles = (Map<byte[], String>) meta.get("unknownFiles");
Map<String, String> result = new LinkedHashMap<>();
for (Map.Entry<byte[], String> 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";

View File

@ -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<String, Object> meta = new LinkedHashMap<String, Object>();
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<String, Object> meta) throws AndrolibException {
private void putUsesFramework(MetaInfo meta) throws AndrolibException {
Set<ResPackage> pkgs = getResTable().listFramePackages();
if (pkgs.isEmpty()) {
return;
@ -329,24 +332,22 @@ public class ApkDecoder {
}
Arrays.sort(ids);
Map<String, Object> uses = new LinkedHashMap<String, Object>();
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<String, Object> meta) throws AndrolibException {
private void putSdkInfo(MetaInfo meta) throws AndrolibException {
Map<String, String> info = getResTable().getSdkInfo();
if (info.size() > 0) {
meta.put("sdkInfo", info);
meta.sdkInfo = info;
}
}
private void putPackageInfo(Map<String, Object> 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<String, String> packages = new HashMap<String, String>();
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<String, Object> meta) throws AndrolibException {
Map<String, String> 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<String, Object> meta) throws AndrolibException {
Map<byte[], String> 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<String, Object> meta) throws AndrolibException {
private void putFileCompressionInfo(MetaInfo meta) throws AndrolibException {
if (!mUncompressedFiles.isEmpty()) {
meta.put("doNotCompress", mUncompressedFiles);
meta.doNotCompress = mUncompressedFiles;
}
}
private void putSharedLibraryInfo(Map<String, Object> meta) throws AndrolibException {
meta.put("sharedLibrary", mResTable.getSharedLibrary());
private void putSharedLibraryInfo(MetaInfo meta) throws AndrolibException {
meta.sharedLibrary = mResTable.getSharedLibrary();
}
private final Androlib mAndrolib;

View File

@ -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<String, String> sdkInfo;
public PackageInfo packageInfo;
public VersionInfo versionInfo;
public boolean compressionType;
public boolean sharedLibrary;
public Map<String, String> unknownFiles;
public Collection<String> 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);
}
}
}

View File

@ -0,0 +1,9 @@
package brut.androlib.meta;
/**
* Created by rover12421 on 1/6/16.
*/
public class PackageInfo {
public String forcedPackageId;
public String renameManifestPackage;
}

View File

@ -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);
}
}
}

View File

@ -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()));
}
}
}

View File

@ -0,0 +1,11 @@
package brut.androlib.meta;
import java.util.List;
/**
* Created by rover12421 on 1/6/16.
*/
public class UsesFramework {
public List<Integer> ids;
public String tag;
}

View File

@ -0,0 +1,9 @@
package brut.androlib.meta;
/**
* Created by rover12421 on 1/6/16.
*/
public class VersionInfo {
public String versionCode;
public String versionName;
}

View File

@ -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 <code>true</code>
* @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 <code>true</code>
* @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;
}
}
}
}
/**
* <p>Unescapes any Java literals found in the <code>String</code>.
* For example, it will turn a sequence of <code>'\'</code> and
* <code>'n'</code> into a newline character, unless the <code>'\'</code>
* is preceded by another <code>'\'</code>.</p>
*
* @param str the <code>String</code> to unescape, may be null
* @return a new unescaped <code>String</code>, <code>null</code> if null string input
*/
public static String unescapeString(String str) {
return StringEscapeUtils.unescapeJava(str);
}
}

View File

@ -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 <brut.alll@gmail.com>
@ -268,22 +277,22 @@ final public class AndrolibResources {
}
}
public void setVersionInfo(Map<String, String> 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<String, String> 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<String, String> map) {
if (map != null) {
mPackageId = map.get("forced-package-id");
public void setPackageId(PackageInfo packageInfo) {
if (packageInfo != null) {
mPackageId = packageInfo.forcedPackageId;
}
}

View File

@ -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<String, String> mSdkInfo = new LinkedHashMap<String, String>();
private Map<String, String> mVersionInfo = new LinkedHashMap<String, String>();
private Map<String, String> 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<String, String> getVersionInfo() {
public void setVersionCode(String versionCode) {
mVersionInfo.versionCode = versionCode;
}
public VersionInfo getVersionInfo() {
return mVersionInfo;
}

View File

@ -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<byte[], String> mUnknownFiles = new LinkedHashMap<byte[], String>();
private final Map<String, String> mUnknownFiles = new LinkedHashMap<>();
public void addUnknownFileInfo(String file, String value) {
mUnknownFiles.put(file.getBytes(StandardCharsets.UTF_8), value);
mUnknownFiles.put(file, value);
}
public Map<byte[], String> getUnknownFiles() {
public Map<String, String> getUnknownFiles() {
return mUnknownFiles;
}
}

View File

@ -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 <brut.alll@gmail.com>
*/

View File

@ -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;

View File

@ -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 <brut.alll@gmail.com>
*/

View File

@ -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<String, Object> control = new Androlib().readMetaFile(sTestOrigDir);
Map<String, Object> 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<String, String> control_files = (Map<String, String>)control.get("unknownFiles");
Map<String, String> test_files = (Map<String, String>)test.get("unknownFiles");
Map<String, String> control_files = control.unknownFiles;
Map<String, String> test_files = test.unknownFiles;
assertTrue(control_files.size() == test_files.size());
// Make sure that the compression methods are still the same

View File

@ -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'
hidden.file: '8'
non\u007Fprintable.file: '8'
stored.file: '0'
unk_folder/unknown_file: '8'
lib_bug603/bug603: '8'