diff --git a/.gitignore b/.gitignore index fe7ff60a..07176cc0 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,7 @@ bin/ # IntelliJ *.iml .idea/* -/out +**/out/ # Patches *.patch \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index b7dad9c3..0a2330c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,28 +1,35 @@ env: - - TERM=dumb GROOVY_TURN_OFF_JAVA_WARNINGS=true + global: + - TERM=dumb + - GROOVY_TURN_OFF_JAVA_WARNINGS=true + language: java + dist: trusty + matrix: include: - os: linux jdk: openjdk8 -# - os: linux -# jdk: openjdk9 - os: linux jdk: oraclejdk8 -# - os: linux -# jdk: oraclejdk9 - os: osx osx_image: xcode9.2 -# - os: osx -# osx_image: xcode9.4 + - os: windows + language: shell cache: directories: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ -install: ./gradlew clean -script: ./gradlew build shadowJar proguard + +install: + - chmod +x ./scripts/travis-ci/clean-tests.sh + - ./scripts/travis-ci/clean-tests.sh + +script: + - chmod +x ./scripts/travis-ci/run-tests.sh + - ./scripts/travis-ci/run-tests.sh + branches: only: - - master - - stable + - master \ No newline at end of file diff --git a/INTERNAL.md b/INTERNAL.md index 2326f42c..c11729ca 100644 --- a/INTERNAL.md +++ b/INTERNAL.md @@ -194,7 +194,7 @@ is just a guideline but helps me to release a new version every 3 months. ### Social Spam The final step is to send this release into the wild via some social posting. Head to the blog -where the release post was and send that link to Twiter, Google and whatever else you use. +where the release post was and send that link to Twitter, Google and whatever else you use. Relax and watch the bug tracker. @@ -225,8 +225,8 @@ we aren't building the entire AOSP package, the initial build is to just see if We check out a certain tag. Currently we use - * aapt2 - `android-9.0.0_r3`. - * aapt1 - `android-9.0.0_r3`. + * aapt2 - `android-9.0.0_r22`. + * aapt1 - `android-9.0.0_r22`. ### Including our modified `frameworks/base` package. @@ -254,6 +254,7 @@ we lose the ability to quickly build just the aapt binary. So the Windows proced 1. `source build/envsetup.sh` 2. `lunch sdk-eng` 3. `make OUT_DIR=out-x64 LOCAL_MULTILIB=64 USE_NINJA=false aapt` +4. `strip out-x64/host/darwin-x86/bin/aapt_64` As of Android Oreo (API 26) all aapt binaries are 64 bit (With exception of Windows). @@ -274,7 +275,7 @@ we lose the ability to quickly build just the aapt2 binary. So the Windows proce 1. `export ANDROID_JAVA_HOME=/Path/To/Jdk` 2. `source build/envsetup.sh` 3. `make OUT_DIR=out-x64 LOCAL_MULTILIB=64 USE_NINJA=false aapt2` -4. `strip out-x64/host/darwin-x86/bin/aapt2` +4. `strip out-x64/host/darwin-x86/bin/aapt2_64` #### Confirming aapt/aapt2 builds are static diff --git a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java index 69c9c45c..88d27aa2 100644 --- a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java +++ b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java @@ -36,6 +36,9 @@ import java.util.logging.*; public class Main { public static void main(String[] args) throws IOException, InterruptedException, BrutException { + // headless + System.setProperty("java.awt.headless", "true"); + // set verbosity default Verbosity verbosity = Verbosity.NORMAL; @@ -218,12 +221,18 @@ public class Main { if (cli.hasOption("p") || cli.hasOption("frame-path")) { apkOptions.frameworkFolderLocation = cli.getOptionValue("p"); } + if (cli.hasOption("nc") || cli.hasOption("no-crunch")) { + apkOptions.noCrunch = true; + } // Temporary flag to enable the use of aapt2. This will tranform in time to a use-aapt1 flag, which will be // legacy and eventually removed. if (cli.hasOption("use-aapt2")) { apkOptions.useAapt2 = true; } + if (cli.hasOption("api") || cli.hasOption("api-level")) { + apkOptions.forceApi = Integer.parseInt(cli.getOptionValue("api")); + } if (cli.hasOption("o") || cli.hasOption("output")) { outFile = new File(cli.getOptionValue("o")); } else { @@ -397,6 +406,11 @@ public class Main { .desc("Copies original AndroidManifest.xml and META-INF. See project page for more info.") .build(); + Option noCrunchOption = Option.builder("nc") + .longOpt("no-crunch") + .desc("Disable crunching of resource files during the build step.") + .build(); + Option tagOption = Option.builder("t") .longOpt("tag") .desc("Tag frameworks using .") @@ -439,6 +453,7 @@ public class Main { BuildOptions.addOption(aaptOption); BuildOptions.addOption(originalOption); BuildOptions.addOption(aapt2Option); + BuildOptions.addOption(noCrunchOption); } // add global options @@ -492,6 +507,7 @@ public class Main { allOptions.addOption(verboseOption); allOptions.addOption(quietOption); allOptions.addOption(aapt2Option); + allOptions.addOption(noCrunchOption); } private static String verbosityHelp() { 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 ae52459b..c2499924 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 @@ -416,7 +416,7 @@ public class Androlib { if (apkOptions.forceBuildAll || isModified(smaliDir, dex)) { LOGGER.info("Smaling " + folder + " folder into " + filename + "..."); dex.delete(); - SmaliBuilder.build(smaliDir, dex, mMinSdkVersion); + SmaliBuilder.build(smaliDir, dex, apkOptions.forceApi > 0 ? apkOptions.forceApi : mMinSdkVersion); } return true; } 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 4bf5b001..aad70b9d 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 @@ -377,6 +377,25 @@ public class ApkDecoder { private void putSdkInfo(MetaInfo meta) throws AndrolibException { Map info = getResTable().getSdkInfo(); if (info.size() > 0) { + String refValue; + if (info.get("minSdkVersion") != null) { + refValue = ResXmlPatcher.pullValueFromIntegers(mOutDir, info.get("minSdkVersion")); + if (refValue != null) { + info.put("minSdkVersion", refValue); + } + } + if (info.get("targetSdkVersion") != null) { + refValue = ResXmlPatcher.pullValueFromIntegers(mOutDir, info.get("targetSdkVersion")); + if (refValue != null) { + info.put("targetSdkVersion", refValue); + } + } + if (info.get("maxSdkVersion") != null) { + refValue = ResXmlPatcher.pullValueFromIntegers(mOutDir, info.get("maxSdkVersion")); + if (refValue != null) { + info.put("maxSdkVersion", refValue); + } + } meta.sdkInfo = info; } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkOptions.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkOptions.java index 0a81ef07..9fff0bd2 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkOptions.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkOptions.java @@ -28,6 +28,8 @@ public class ApkOptions { public boolean isFramework = false; public boolean resourcesAreCompressed = false; public boolean useAapt2 = false; + public boolean noCrunch = false; + public int forceApi = 0; public Collection doNotCompress; public String frameworkFolderLocation = null; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/err/AXmlDecodingException.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/err/AXmlDecodingException.java new file mode 100644 index 00000000..cc28d000 --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/err/AXmlDecodingException.java @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2018 Ryszard Wiśniewski + * Copyright (C) 2018 Connor Tumbleson + * + * Licensed 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.err; + +import brut.androlib.AndrolibException; + +public class AXmlDecodingException extends AndrolibException { + + public AXmlDecodingException(Throwable cause) { + super(cause); + } + + public AXmlDecodingException(String message, Throwable cause) { + super(message, cause); + } + + public AXmlDecodingException(String message) { + super(message); + } + + public AXmlDecodingException() { + } +} \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/err/RawXmlEncounteredException.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/err/RawXmlEncounteredException.java new file mode 100644 index 00000000..762f1074 --- /dev/null +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/err/RawXmlEncounteredException.java @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2018 Ryszard Wiśniewski + * Copyright (C) 2018 Connor Tumbleson + * + * Licensed 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.err; + +import brut.androlib.AndrolibException; + +public class RawXmlEncounteredException extends AndrolibException { + + public RawXmlEncounteredException(Throwable cause) { + super(cause); + } + + public RawXmlEncounteredException(String message, Throwable cause) { + super(message, cause); + } + + public RawXmlEncounteredException(String message) { + super(message); + } + + public RawXmlEncounteredException() { + } +} diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java index 6af075fc..8f9988bf 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java @@ -29,14 +29,14 @@ import org.jf.smali.*; */ public class SmaliMod { - public static boolean assembleSmaliFile(String smali, DexBuilder dexBuilder, boolean verboseErrors, + public static boolean assembleSmaliFile(String smali, DexBuilder dexBuilder, int apiLevel, boolean verboseErrors, boolean printTokens, File smaliFile) throws IOException, RuntimeException, RecognitionException { InputStream is = new ByteArrayInputStream(smali.getBytes()); - return assembleSmaliFile(is, dexBuilder, verboseErrors, printTokens, smaliFile); + return assembleSmaliFile(is, dexBuilder, apiLevel, verboseErrors, printTokens, smaliFile); } - public static boolean assembleSmaliFile(InputStream is,DexBuilder dexBuilder, boolean verboseErrors, + public static boolean assembleSmaliFile(InputStream is,DexBuilder dexBuilder, int apiLevel, boolean verboseErrors, boolean printTokens, File smaliFile) throws IOException, RecognitionException { // copy our filestream into a tmp file, so we don't overwrite @@ -47,10 +47,10 @@ public class SmaliMod { IOUtils.copy(is, os); os.close(); - return assembleSmaliFile(tmp,dexBuilder, verboseErrors, printTokens); + return assembleSmaliFile(tmp,dexBuilder, apiLevel, verboseErrors, printTokens); } - public static boolean assembleSmaliFile(File smaliFile,DexBuilder dexBuilder, boolean verboseErrors, + public static boolean assembleSmaliFile(File smaliFile,DexBuilder dexBuilder, int apiLevel, boolean verboseErrors, boolean printTokens) throws IOException, RecognitionException { CommonTokenStream tokens; @@ -77,6 +77,7 @@ public class SmaliMod { } smaliParser parser = new smaliParser(tokens); + parser.setApiLevel(apiLevel); parser.setVerboseErrors(verboseErrors); smaliParser.smali_file_return result = parser.smali_file(); @@ -93,7 +94,7 @@ public class SmaliMod { treeStream.setTokenStream(tokens); smaliTreeWalker dexGen = new smaliTreeWalker(treeStream); - + dexGen.setApiLevel(apiLevel); dexGen.setVerboseErrors(verboseErrors); dexGen.setDexBuilder(dexBuilder); dexGen.smali_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 b8ceeec9..b4c3d44a 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 @@ -350,6 +350,10 @@ final public class AndrolibResources { cmd.add("-v"); } + if (apkOptions.noCrunch) { + cmd.add("--no-crunch"); + } + try { OS.exec(cmd.toArray(new String[0])); LOGGER.fine("aapt2 compile command ran: "); @@ -485,6 +489,9 @@ final public class AndrolibResources { if (apkOptions.debugMode) { // inject debuggable="true" into manifest cmd.add("--debug-mode"); } + if (apkOptions.noCrunch) { + cmd.add("--no-crunch"); + } // force package id so that some frameworks build with correct id // disable if user adds own aapt (can't know if they have this feature) if (mPackageId != null && ! customAapt && ! mSharedLibrary) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java index 0c2de96d..df07f7c8 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java @@ -24,6 +24,11 @@ import java.util.*; * @author Ryszard Wiśniewski */ public final class ResTypeSpec { + + public static final String RES_TYPE_NAME_ARRAY = "array"; + public static final String RES_TYPE_NAME_PLURALS = "plurals"; + public static final String RES_TYPE_NAME_STYLES = "style"; + private final String mName; private final Map mResSpecs = new LinkedHashMap(); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResScalarValue.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResScalarValue.java index 5deace0e..b396762a 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResScalarValue.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResScalarValue.java @@ -83,6 +83,13 @@ public abstract class ResScalarValue extends ResIntBasedValue implements } } + // Android does not allow values (false) for ids.xml anymore + // https://issuetracker.google.com/issues/80475496 + // But it decodes as a ResBoolean, which makes no sense. So force it to empty + if (type.equalsIgnoreCase("id") && !body.isEmpty()) { + body = ""; + } + // check for using attrib as node or item String tagName = item ? "item" : type; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java index ee21befd..d1b7e3a8 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java @@ -19,6 +19,7 @@ package brut.androlib.res.data.value; import android.util.TypedValue; import brut.androlib.AndrolibException; import brut.androlib.res.data.ResPackage; +import brut.androlib.res.data.ResTypeSpec; import brut.util.Duo; /** @@ -41,7 +42,7 @@ public class ResValueFactory { } return new ResReferenceValue(mPackage, 0, null); case TypedValue.TYPE_REFERENCE: - return newReference(value, rawValue); + return newReference(value, null); case TypedValue.TYPE_ATTRIBUTE: return newReference(value, rawValue, true); case TypedValue.TYPE_STRING: @@ -83,7 +84,7 @@ public class ResValueFactory { return new ResStringValue(value, rawValue); } - public ResBagValue bagFactory(int parent, Duo[] items) throws AndrolibException { + public ResBagValue bagFactory(int parent, Duo[] items, ResTypeSpec resTypeSpec) throws AndrolibException { ResReferenceValue parentVal = newReference(parent, null); if (items.length == 0) { @@ -93,14 +94,25 @@ public class ResValueFactory { if (key == ResAttr.BAG_KEY_ATTR_TYPE) { return ResAttr.factory(parentVal, items, this, mPackage); } - // Android O Preview added an unknown enum for ResTable_map. This is hardcoded as 0 for now. - if (key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) { + + String resTypeName = resTypeSpec.getName(); + + // Android O Preview added an unknown enum for c. This is hardcoded as 0 for now. + if (ResTypeSpec.RES_TYPE_NAME_ARRAY.equals(resTypeName) + || key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) { return new ResArrayValue(parentVal, items); } - if (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END) { + + if (ResTypeSpec.RES_TYPE_NAME_PLURALS.equals(resTypeName) || + (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END)) { return new ResPluralsValue(parentVal, items); } - return new ResStyleValue(parentVal, items, this); + + if (ResTypeSpec.RES_TYPE_NAME_STYLES.equals(resTypeName)) { + return new ResStyleValue(parentVal, items, this); + } + + throw new AndrolibException("unsupported res type name for bags. Found: " + resTypeName); } public ResReferenceValue newReference(int resID, String rawValue) { 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 290a6615..86efecff 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 @@ -347,7 +347,7 @@ public class ARSCDecoder { } } - return factory.bagFactory(parent, items); + return factory.bagFactory(parent, items, mTypeSpec); } private ResIntBasedValue readValue() throws IOException, AndrolibException { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AXmlResourceParser.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AXmlResourceParser.java index 5e64aaf4..d006a2c2 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AXmlResourceParser.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/AXmlResourceParser.java @@ -852,7 +852,7 @@ public class AXmlResourceParser implements XmlResourceParser { private final void doNext() throws IOException { // Delayed initialization. if (m_strings == null) { - m_reader.skipCheckInt(CHUNK_AXML_FILE); + m_reader.skipCheckInt(CHUNK_AXML_FILE, CHUNK_AXML_FILE_BROKEN); /* * chunkSize @@ -1004,7 +1004,7 @@ public class AXmlResourceParser implements XmlResourceParser { ATTRIBUTE_IX_VALUE_TYPE = 3, ATTRIBUTE_IX_VALUE_DATA = 4, ATTRIBUTE_LENGTH = 5; - private static final int CHUNK_AXML_FILE = 0x00080003, + private static final int CHUNK_AXML_FILE = 0x00080003, CHUNK_AXML_FILE_BROKEN = 0x00080001, CHUNK_RESOURCEIDS = 0x00080180, CHUNK_XML_FIRST = 0x00100100, CHUNK_XML_START_NAMESPACE = 0x00100100, CHUNK_XML_END_NAMESPACE = 0x00100101, diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/Res9patchStreamDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/Res9patchStreamDecoder.java index a4d4285e..a8ed5f16 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/Res9patchStreamDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/Res9patchStreamDecoder.java @@ -65,13 +65,21 @@ public class Res9patchStreamDecoder implements ResStreamDecoder { drawVLine(im2, w + 1, np.padTop + 1, h - np.padBottom); int[] xDivs = np.xDivs; - for (int i = 0; i < xDivs.length; i += 2) { - drawHLine(im2, 0, xDivs[i] + 1, xDivs[i + 1]); + if (xDivs.length == 0) { + drawHLine(im2, 0, 1, w); + } else { + for (int i = 0; i < xDivs.length; i += 2) { + drawHLine(im2, 0, xDivs[i] + 1, xDivs[i + 1]); + } } int[] yDivs = np.yDivs; - for (int i = 0; i < yDivs.length; i += 2) { - drawVLine(im2, 0, yDivs[i] + 1, yDivs[i + 1]); + if (yDivs.length == 0) { + drawVLine(im2, 0, 1, h); + } else { + for (int i = 0; i < yDivs.length; i += 2) { + drawVLine(im2, 0, yDivs[i] + 1, yDivs[i + 1]); + } } // Some images additionally use Optical Bounds diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java index 33a5fbc0..cc98c0b5 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java @@ -18,6 +18,7 @@ package brut.androlib.res.decoder; import brut.androlib.AndrolibException; import brut.androlib.err.CantFind9PatchChunk; +import brut.androlib.err.RawXmlEncounteredException; import brut.androlib.res.data.ResResource; import brut.androlib.res.data.value.ResBoolValue; import brut.androlib.res.data.value.ResFileValue; @@ -118,6 +119,11 @@ public class ResFileDecoder { } decode(inDir, inFileName, outDir, outFileName, "xml"); + } catch (RawXmlEncounteredException ex) { + // If we got an error to decode XML, lets assume the file is in raw format. + // This is a large assumption, that might increase runtime, but will save us for situations where + // XSD files are AXML`d on aapt1, but left in plaintext in aapt2. + decode(inDir, inFileName, outDir, outFileName, "raw"); } catch (AndrolibException ex) { LOGGER.log(Level.SEVERE, String.format( "Could not decode file, replacing by FALSE value: %s", 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 888e47c4..25ef81e6 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 @@ -19,8 +19,9 @@ package brut.androlib.res.decoder; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.logging.Logger; +import brut.androlib.err.AXmlDecodingException; +import brut.androlib.err.RawXmlEncounteredException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.wrapper.XmlPullParserWrapper; @@ -142,9 +143,9 @@ public class XmlPullStreamDecoder implements ResStreamDecoder { } ser.flush(); } catch (XmlPullParserException ex) { - throw new AndrolibException("Could not decode XML", ex); + throw new AXmlDecodingException("Could not decode XML", ex); } catch (IOException ex) { - throw new AndrolibException("Could not decode XML", ex); + throw new RawXmlEncounteredException("Could not decode XML", ex); } } @@ -155,6 +156,4 @@ public class XmlPullStreamDecoder implements ResStreamDecoder { private final XmlPullParser mParser; private final ExtXmlSerializer mSerial; - - private final static Logger LOGGER = Logger.getLogger(XmlPullStreamDecoder.class.getName()); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java index c1581340..8fd124c4 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java @@ -197,6 +197,41 @@ public final class ResXmlPatcher { return null; } + /** + * Finds key in integers.xml file and returns text value + * + * @param directory Root directory of apk + * @param key Integer reference (ie @integer/foo) + * @return String|null + * @throws AndrolibException + */ + public static String pullValueFromIntegers(File directory, String key) throws AndrolibException { + if (key == null || ! key.contains("@")) { + return null; + } + + File file = new File(directory, "/res/values/integers.xml"); + key = key.replace("@integer/", ""); + + if (file.exists()) { + try { + Document doc = loadDocument(file); + XPath xPath = XPathFactory.newInstance().newXPath(); + XPathExpression expression = xPath.compile("/resources/integer[@name=" + '"' + key + "\"]/text()"); + + Object result = expression.evaluate(doc, XPathConstants.STRING); + + if (result != null) { + return (String) result; + } + + } catch (SAXException | ParserConfigurationException | IOException | XPathExpressionException ignored) { + } + } + + return null; + } + /** * Removes attributes like "versionCode" and "versionName" from file. * 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 e61ba446..03c88db6 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 @@ -71,7 +71,7 @@ public class SmaliBuilder { if (fileName.endsWith(".smali")) { try { - if (!SmaliMod.assembleSmaliFile(inFile, dexBuilder, false, false)) { + if (!SmaliMod.assembleSmaliFile(inFile, dexBuilder, mApiLevel, false, false)) { throw new AndrolibException("Could not smali file: " + fileName); } } catch (IOException | RecognitionException ex) { diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/linux/aapt b/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/linux/aapt deleted file mode 100755 index 40d1c24c..00000000 Binary files a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/linux/aapt and /dev/null differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/macosx/aapt b/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/macosx/aapt deleted file mode 100755 index 1b94a3dc..00000000 Binary files a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/macosx/aapt and /dev/null differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/windows/aapt.exe b/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/windows/aapt.exe deleted file mode 100755 index a4e79b02..00000000 Binary files a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt/windows/aapt.exe and /dev/null differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/linux/aapt2 b/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/linux/aapt2 deleted file mode 100755 index 71ad03a3..00000000 Binary files a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/linux/aapt2 and /dev/null differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/macosx/aapt2 b/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/macosx/aapt2 deleted file mode 100755 index 3752ab2f..00000000 Binary files a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/macosx/aapt2 and /dev/null differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/windows/aapt2.exe b/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/windows/aapt2.exe deleted file mode 100755 index 5496a556..00000000 Binary files a/brut.apktool/apktool-lib/src/main/resources/prebuilt/aapt2/windows/aapt2.exe and /dev/null differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt b/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt new file mode 100755 index 00000000..e38e6374 Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2 b/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2 new file mode 100755 index 00000000..e218a739 Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2 differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2_64 b/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2_64 new file mode 100755 index 00000000..2e47d67e Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2_64 differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt_64 b/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt_64 new file mode 100755 index 00000000..913a85e2 Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt_64 differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt2_64 b/brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt2_64 new file mode 100755 index 00000000..4834c4b9 Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt2_64 differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt_64 b/brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt_64 new file mode 100755 index 00000000..ca8691b0 Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt_64 differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt.exe b/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt.exe new file mode 100755 index 00000000..4fbb2c93 Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt.exe differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2.exe b/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2.exe new file mode 100755 index 00000000..9b0a5464 Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2.exe differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2_64.exe b/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2_64.exe new file mode 100755 index 00000000..e9405110 Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2_64.exe differ diff --git a/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt_64.exe b/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt_64.exe new file mode 100755 index 00000000..d087babb Binary files /dev/null and b/brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt_64.exe differ diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java index 4a53ec25..7dc82d5c 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/BuildAndDecodeTest.java @@ -198,6 +198,16 @@ public class BuildAndDecodeTest extends BaseTest { compareXmlFiles("res/xml/references.xml"); } + @Test + public void xmlXsdFileTest() throws BrutException { + compareXmlFiles("res/xml/ww_box_styles_schema.xsd"); + } + + @Test + public void xmlIdsEmptyTest() throws BrutException { + compareXmlFiles("res/values/ids.xml"); + } + @Test public void xmlReferenceAttributeTest() throws BrutException { compareXmlFiles("res/layout/issue1040.xml"); @@ -231,7 +241,7 @@ public class BuildAndDecodeTest extends BaseTest { @Test public void qualifiersTest() throws BrutException { compareValuesFiles("values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp" - + "-xlarge-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key" + + "-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key" + "-navhidden-dpad-v26/strings.xml"); } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java index 68f555cb..98e82328 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/DebugTagRetainedTest.java @@ -77,8 +77,8 @@ public class DebugTagRetainedTest extends BaseTest { String expected = TestUtils.replaceNewlines("" + " "); + "android:compileSdkVersionCodename=\"6.0-2438415\" package=\"com.ibotpeaches.issue1235\" platformBuildVersionCode=\"20\" " + + "platformBuildVersionName=\"4.4W.2-1537038\"> "); byte[] encoded = Files.readAllBytes(Paths.get(sTmpDir + File.separator + apk + File.separator + "AndroidManifest.xml")); String obtained = TestUtils.replaceNewlines(new String(encoded)); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java index 642965f8..742f8c68 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt1/ProviderAttributeTest.java @@ -72,7 +72,7 @@ public class ProviderAttributeTest extends BaseTest { apkDecoder.decode(); String expected = TestUtils.replaceNewlines("\n" + - "\n" + + "\n" + " \n" + " \n" + " \n" + diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java index fd1054e5..f031f4da 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java @@ -84,6 +84,11 @@ public class BuildAndDecodeTest extends BaseTest { compareXmlFiles("res/navigation/nav_graph.xml"); } + @Test + public void xmlIdsEmptyTest() throws BrutException { + compareXmlFiles("res/values/ids.xml"); + } + @Test public void leadingDollarSignResourceNameTest() throws BrutException { compareXmlFiles("res/drawable/$avd_hide_password__0.xml"); @@ -93,4 +98,9 @@ public class BuildAndDecodeTest extends BaseTest { public void confirmManifestStructureTest() throws BrutException { compareXmlFiles("AndroidManifest.xml"); } + + @Test + public void xmlXsdFileTest() throws BrutException { + compareXmlFiles("res/xml/ww_box_styles_schema.xsd"); + } } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeArrayTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeArrayTest.java new file mode 100644 index 00000000..c2bdf5e4 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/DecodeArrayTest.java @@ -0,0 +1,55 @@ +package brut.androlib.decode; + +import brut.androlib.ApkDecoder; +import brut.androlib.BaseTest; +import brut.androlib.TestUtils; +import brut.androlib.res.data.ResTable; +import brut.androlib.res.data.value.ResArrayValue; +import brut.androlib.res.data.value.ResValue; +import brut.common.BrutException; +import brut.directory.ExtFile; +import brut.util.OS; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; + +import static junit.framework.Assert.assertTrue; + +public class DecodeArrayTest extends BaseTest { + + @BeforeClass + public static void beforeClass() throws Exception { + TestUtils.cleanFrameworkFile(); + sTmpDir = new ExtFile(OS.createTempDirectory()); + TestUtils.copyResourceDir(MissingVersionManifestTest.class, "decode/issue1994/", sTmpDir); + } + + @AfterClass + public static void afterClass() throws BrutException { + OS.rmdir(sTmpDir); + } + + @Test + public void decodeStringArray() throws BrutException { + String apk = "issue1994.apk"; + ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + + ResTable resTable = apkDecoder.getResTable(); + ResValue value = resTable.getResSpec(0x7f020001).getDefaultResource().getValue(); + + assertTrue("Not a ResArrayValue. Found: " + value.getClass(), value instanceof ResArrayValue); + } + + @Test + public void decodeArray() throws BrutException { + String apk = "issue1994.apk"; + ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk)); + + ResTable resTable = apkDecoder.getResTable(); + ResValue value = resTable.getResSpec(0x7f020000).getDefaultResource().getValue(); + + assertTrue("Not a ResArrayValue. Found: " + value.getClass(), value instanceof ResArrayValue); + } +} diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ExternalEntityTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ExternalEntityTest.java index 6cd58b5c..21e14679 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ExternalEntityTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/ExternalEntityTest.java @@ -64,7 +64,7 @@ public class ExternalEntityTest extends BaseTest { String expected = TestUtils.replaceNewlines("" + " "); diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MissingDiv9PatchTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MissingDiv9PatchTest.java new file mode 100644 index 00000000..da913026 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/decode/MissingDiv9PatchTest.java @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2018 Ryszard Wiśniewski + * Copyright (C) 2018 Connor Tumbleson + * + * Licensed 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.decode; + +import brut.androlib.BaseTest; +import brut.androlib.TestUtils; +import brut.androlib.res.decoder.Res9patchStreamDecoder; +import brut.common.BrutException; +import brut.directory.ExtFile; +import brut.util.OS; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.*; + +import static org.junit.Assert.*; + +public class MissingDiv9PatchTest extends BaseTest { + + @BeforeClass + public static void beforeClass() throws Exception { + TestUtils.cleanFrameworkFile(); + sTmpDir = new ExtFile(OS.createTempDirectory()); + TestUtils.copyResourceDir(MissingDiv9PatchTest.class, "decode/issue1522/", sTmpDir); + } + + @AfterClass + public static void afterClass() throws BrutException { + OS.rmdir(sTmpDir); + } + + @Test + public void assertMissingDivAdded() throws Exception { + InputStream inputStream = getFileInputStream(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + Res9patchStreamDecoder decoder = new Res9patchStreamDecoder(); + decoder.decode(inputStream, outputStream); + + BufferedImage image = ImageIO.read(new ByteArrayInputStream(outputStream.toByteArray())); + int height = image.getHeight() - 1; + + // First and last pixel will be invisible, so lets check the first column and ensure its all black + for (int y = 1; y < height; y++) { + assertEquals("y coordinate failed at: " + y, NP_COLOR, image.getRGB(0, y)); + } + + } + + private FileInputStream getFileInputStream() throws IOException { + File file = new File(sTmpDir, "pip_dismiss_scrim.9.png"); + return new FileInputStream(file.toPath().toString()); + } + + private static final int NP_COLOR = 0xff000000; +} diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp-xlarge-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key-navhidden-dpad-v26/strings.xml b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key-navhidden-dpad-v26/strings.xml similarity index 100% rename from brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp-xlarge-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key-navhidden-dpad-v26/strings.xml rename to brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key-navhidden-dpad-v26/strings.xml diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values/ids.xml b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values/ids.xml new file mode 100644 index 00000000..de166285 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values/public.xml b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values/public.xml index 4a0a3a39..86c77ede 100644 --- a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values/public.xml +++ b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/values/public.xml @@ -1,4 +1,5 @@ + \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/xml/ww_box_styles_schema.xsd b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/xml/ww_box_styles_schema.xsd new file mode 100644 index 00000000..70bfc6c3 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/aapt1/testapp/res/xml/ww_box_styles_schema.xsd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/attrs.xml b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/attrs.xml new file mode 100644 index 00000000..91ded550 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/attrs.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/ids.xml b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/ids.xml new file mode 100644 index 00000000..de166285 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/xml/ww_box_styles_schema.xsd b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/xml/ww_box_styles_schema.xsd new file mode 100644 index 00000000..70bfc6c3 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/xml/ww_box_styles_schema.xsd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/decode/issue1522/pip_dismiss_scrim.9.png b/brut.apktool/apktool-lib/src/test/resources/decode/issue1522/pip_dismiss_scrim.9.png new file mode 100644 index 00000000..8bd2220a Binary files /dev/null and b/brut.apktool/apktool-lib/src/test/resources/decode/issue1522/pip_dismiss_scrim.9.png differ diff --git a/brut.apktool/apktool-lib/src/test/resources/decode/issue1994/issue1994.apk b/brut.apktool/apktool-lib/src/test/resources/decode/issue1994/issue1994.apk new file mode 100644 index 00000000..2443f683 Binary files /dev/null and b/brut.apktool/apktool-lib/src/test/resources/decode/issue1994/issue1994.apk differ diff --git a/brut.j.util/src/main/java/brut/util/AaptManager.java b/brut.j.util/src/main/java/brut/util/AaptManager.java index a4b782a0..1d3f2efd 100644 --- a/brut.j.util/src/main/java/brut/util/AaptManager.java +++ b/brut.j.util/src/main/java/brut/util/AaptManager.java @@ -35,17 +35,20 @@ public class AaptManager { File aaptBinary; String aaptVersion = getAaptBinaryName(version); - if (! OSDetection.is64Bit() && ! OSDetection.isWindows()) { + if (! OSDetection.is64Bit() && OSDetection.isMacOSX()) { throw new BrutException("32 bit OS detected. No 32 bit binaries available."); } + // Set the 64 bit flag + aaptVersion += OSDetection.is64Bit() ? "_64" : ""; + try { if (OSDetection.isMacOSX()) { - aaptBinary = Jar.getResourceAsFile("/prebuilt/" + aaptVersion + "/macosx/" + aaptVersion, AaptManager.class); + aaptBinary = Jar.getResourceAsFile("/prebuilt/macosx/" + aaptVersion, AaptManager.class); } else if (OSDetection.isUnix()) { - aaptBinary = Jar.getResourceAsFile("/prebuilt/" + aaptVersion + "/linux/" + aaptVersion, AaptManager.class); + aaptBinary = Jar.getResourceAsFile("/prebuilt/linux/" + aaptVersion, AaptManager.class); } else if (OSDetection.isWindows()) { - aaptBinary = Jar.getResourceAsFile("/prebuilt/" + aaptVersion + "/windows/" + aaptVersion + ".exe", AaptManager.class); + aaptBinary = Jar.getResourceAsFile("/prebuilt/windows/" + aaptVersion + ".exe", AaptManager.class); } else { throw new BrutException("Could not identify platform: " + OSDetection.returnOS()); } diff --git a/brut.j.util/src/main/java/brut/util/ExtDataInput.java b/brut.j.util/src/main/java/brut/util/ExtDataInput.java index 4048eec4..be380a28 100644 --- a/brut.j.util/src/main/java/brut/util/ExtDataInput.java +++ b/brut.j.util/src/main/java/brut/util/ExtDataInput.java @@ -42,11 +42,11 @@ public class ExtDataInput extends DataInputDelegate { skipBytes(4); } - public void skipCheckInt(int expected) throws IOException { + public void skipCheckInt(int expected1, int expected2) throws IOException { int got = readInt(); - if (got != expected) { + if (got != expected1 && got != expected2) { throw new IOException(String.format( - "Expected: 0x%08x, got: 0x%08x", expected, got)); + "Expected: 0x%08x or 0x%08x, got: 0x%08x", expected1, expected2, got)); } } diff --git a/build.gradle b/build.gradle index 272f6fea..f6175b2b 100644 --- a/build.gradle +++ b/build.gradle @@ -107,7 +107,7 @@ subprojects { ext { depends = [ - baksmali: 'org.smali:baksmali:2.2.5', + baksmali: 'org.smali:baksmali:2.2.6', commons_cli: 'commons-cli:commons-cli:1.4', commons_io: 'commons-io:commons-io:2.4', commons_lang: 'org.apache.commons:commons-lang3:3.1', @@ -115,7 +115,7 @@ subprojects { junit: 'junit:junit:4.12', proguard_gradle: 'net.sf.proguard:proguard-gradle:6.0.3', snakeyaml: 'org.yaml:snakeyaml:1.18:android', - smali: 'org.smali:smali:2.2.5', + smali: 'org.smali:smali:2.2.6', xmlpull: 'xpp3:xpp3:1.1.4c', xmlunit: 'xmlunit:xmlunit:1.6', ] diff --git a/scripts/travis-ci/clean-tests.sh b/scripts/travis-ci/clean-tests.sh new file mode 100755 index 00000000..082fd792 --- /dev/null +++ b/scripts/travis-ci/clean-tests.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env sh + +if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then + export GRADLE_OPTS=-Dorg.gradle.daemon=false + choco install jdk8 + export PATH=$PATH:"/c/Program Files/Java/jdk1.8.0_201/bin" + ./gradlew.bat clean +else + ./gradlew clean +fi + +exit $? \ No newline at end of file diff --git a/scripts/travis-ci/run-tests.sh b/scripts/travis-ci/run-tests.sh index 563869ce..5f3616d8 100755 --- a/scripts/travis-ci/run-tests.sh +++ b/scripts/travis-ci/run-tests.sh @@ -1,2 +1,11 @@ #!/usr/bin/env sh -./gradlew build shadowJar + +if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then + export GRADLE_OPTS=-Dorg.gradle.daemon=false + export PATH=$PATH:"/c/Program Files/Java/jdk1.8.0_201/bin" + ./gradlew.bat build shadowJar proguard +else + ./gradlew build shadowJar proguard +fi + +exit $? \ No newline at end of file