Merge branch 'master' into issue-1498

This commit is contained in:
Marvin Killing 2017-06-09 22:56:04 +02:00 committed by GitHub
commit 4ce8a00180
39 changed files with 376 additions and 59 deletions

View File

@ -200,7 +200,7 @@ to get the source downloaded. This is no small download, expect to use 40-60GB.
After that, you need to build AOSP via this [documentation](https://source.android.com/source/building.html) guide. Now
we aren't building the entire AOSP package, the initial build is to just see if you are capable of building it.
We check out a certain tag. Currently we use `android-7.1.1_r4`.
We check out a certain tag. Currently we use `android-7.1.2_r11`.
### Including our modified `frameworks/base` package.
@ -239,3 +239,22 @@ 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`
# Gradle Tips n Tricks
./gradlew build shadowJar proguard -x test
This skips the testing suite (which currently takes 2-4 minutes). Use this when making quick builds and save the testing
suite before pushing to GitHub.
./gradlew build shadowJar proguard -Dtest.debug
This enables debugging on the test suite. This starts the debugger on port 5005 which you can connect with IntelliJ.
./gradlew :brut.apktool:apktool-lib:test ---tests "*BuildAndDecodeTest"
This runs the library project of Apktool, selecting a specific test to run. Comes in handy when writing a new test and
only wanting to run that one. The asterisk is used to the full path to the test can be ignored. You can additionally
match this with the debugging parameter to debug a specific test. This command can be found below.
./gradlew :brut.apktool:apktool-lib:test --tests "*BuildAndDecodeTest" -Dtest.debug

View File

@ -13,6 +13,10 @@ It is NOT intended for piracy and other non-legal uses. It could be used for loc
- [Project Page](http://ibotpeaches.github.io/Apktool/)
- [#apktool on freenode](http://webchat.freenode.net/?channels=apktool)
#### Sponsored by
* [Sourcetoad](https://www.sourcetoad.com/cool-tools/apktool/) - helping with a weekly sponsorship for continued improvement and maintenance of the project.
#### Links
- [Downloads](https://bitbucket.org/iBotPeaches/apktool/downloads)
- [Downloads Mirror](http://connortumbleson.com/apktool/)

View File

@ -19,6 +19,7 @@ package brut.androlib;
import brut.androlib.meta.MetaInfo;
import brut.androlib.meta.UsesFramework;
import brut.androlib.res.AndrolibResources;
import brut.androlib.res.data.ResConfigFlags;
import brut.androlib.res.data.ResPackage;
import brut.androlib.res.data.ResTable;
import brut.androlib.res.data.ResUnknownFiles;
@ -279,7 +280,22 @@ public class Androlib {
mAndRes.setSharedLibrary(meta.sharedLibrary);
if (meta.sdkInfo != null && meta.sdkInfo.get("minSdkVersion") != null) {
mMinSdkVersion = Integer.parseInt(meta.sdkInfo.get("minSdkVersion"));
String minSdkVersion = meta.sdkInfo.get("minSdkVersion");
// Preview builds use short letter for API versions
switch (minSdkVersion) {
case "M":
mMinSdkVersion = ResConfigFlags.SDK_MNC;
break;
case "N":
mMinSdkVersion = ResConfigFlags.SDK_NOUGAT;
break;
case "O":
mMinSdkVersion = ResConfigFlags.SDK_O;
break;
default:
mMinSdkVersion = Integer.parseInt(meta.sdkInfo.get("minSdkVersion"));
}
}
if (outFile == null) {

View File

@ -507,6 +507,9 @@ public class ResConfigFlags {
public final static byte SDK_LOLLIPOP = 21;
public final static byte SDK_LOLLIPOP_MR1 = 22;
public final static byte SDK_MNC = 23;
public final static byte SDK_NOUGAT = 24;
public final static byte SDK_NOUGAT_MR1 = 25;
public final static byte SDK_O = 26;
public final static byte ORIENTATION_ANY = 0;
public final static byte ORIENTATION_PORT = 1;

View File

@ -90,7 +90,8 @@ public class ResValueFactory {
if (key == ResAttr.BAG_KEY_ATTR_TYPE) {
return ResAttr.factory(parentVal, items, this, mPackage);
}
if (key == ResArrayValue.BAG_KEY_ARRAY_START) {
// 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) {
return new ResArrayValue(parentVal, items);
}
if (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END) {

View File

@ -20,6 +20,8 @@ import brut.androlib.AndrolibException;
import brut.androlib.err.CantFind9PatchChunk;
import brut.util.ExtDataInput;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.*;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
@ -39,8 +41,24 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
BufferedImage im = ImageIO.read(new ByteArrayInputStream(data));
int w = im.getWidth(), h = im.getHeight();
BufferedImage im2 = new BufferedImage(w+2, h+2, BufferedImage.TYPE_INT_ARGB);
im2.createGraphics().drawImage(im, 1, 1, w, h, null);
BufferedImage im2 = new BufferedImage(w + 2, h + 2, BufferedImage.TYPE_INT_ARGB);
if (im.getType() == BufferedImage.TYPE_CUSTOM) {
//TODO: Ensure this is gray + alpha case?
Raster srcRaster = im.getRaster();
WritableRaster dstRaster = im2.getRaster();
int[] gray = null, alpha = null;
for (int y = 0; y < im.getHeight(); y++) {
gray = srcRaster.getSamples(0, y, w, 1, 0, gray);
alpha = srcRaster.getSamples(0, y, w, 1, 1, alpha);
dstRaster.setSamples(1, y + 1, w, 1, 0, gray);
dstRaster.setSamples(1, y + 1, w, 1, 1, gray);
dstRaster.setSamples(1, y + 1, w, 1, 2, gray);
dstRaster.setSamples(1, y + 1, w, 1, 3, alpha);
}
} else {
im2.createGraphics().drawImage(im, 1, 1, w, h, null);
}
NinePatch np = getNinePatch(data);
drawHLine(im2, h + 1, np.padLeft + 1, w - np.padRight);
@ -56,6 +74,34 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
drawVLine(im2, 0, yDivs[i] + 1, yDivs[i + 1]);
}
// Some images additionally use Optical Bounds
// https://developer.android.com/about/versions/android-4.3.html#OpticalBounds
try {
OpticalInset oi = getOpticalInset(data);
for (int i = 0; i < oi.layoutBoundsLeft; i++) {
int x = 1 + i;
im2.setRGB(x, h + 1, OI_COLOR);
}
for (int i = 0; i < oi.layoutBoundsRight; i++) {
int x = w - i;
im2.setRGB(x, h + 1, OI_COLOR);
}
for (int i = 0; i < oi.layoutBoundsTop; i++) {
int y = 1 + i;
im2.setRGB(w + 1, y, OI_COLOR);
}
for (int i = 0; i < oi.layoutBoundsBottom; i++) {
int y = h - i;
im2.setRGB(w + 1, y, OI_COLOR);
}
} catch (CantFind9PatchChunk t) {
// This chunk might not exist
}
ImageIO.write(im2, "png", out);
} catch (IOException ex) {
throw new AndrolibException(ex);
@ -70,11 +116,18 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
private NinePatch getNinePatch(byte[] data) throws AndrolibException,
IOException {
ExtDataInput di = new ExtDataInput(new ByteArrayInputStream(data));
find9patchChunk(di);
find9patchChunk(di, NP_CHUNK_TYPE);
return NinePatch.decode(di);
}
private void find9patchChunk(DataInput di) throws AndrolibException,
private OpticalInset getOpticalInset(byte[] data) throws AndrolibException,
IOException {
ExtDataInput di = new ExtDataInput(new ByteArrayInputStream(data));
find9patchChunk(di, OI_CHUNK_TYPE);
return OpticalInset.decode(di);
}
private void find9patchChunk(DataInput di, int magic) throws AndrolibException,
IOException {
di.skipBytes(8);
while (true) {
@ -84,7 +137,7 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
} catch (IOException ex) {
throw new CantFind9PatchChunk("Cant find nine patch chunk", ex);
}
if (di.readInt() == NP_CHUNK_TYPE) {
if (di.readInt() == magic) {
return;
}
di.skipBytes(size + 4);
@ -104,7 +157,9 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
}
private static final int NP_CHUNK_TYPE = 0x6e705463; // npTc
private static final int OI_CHUNK_TYPE = 0x6e704c62; // npLb
private static final int NP_COLOR = 0xff000000;
private static final int OI_COLOR = 0xffff0000;
private static class NinePatch {
public final int padLeft, padRight, padTop, padBottom;
@ -121,16 +176,16 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
}
public static NinePatch decode(ExtDataInput di) throws IOException {
di.skipBytes(1);
di.skipBytes(1); // wasDeserialized
byte numXDivs = di.readByte();
byte numYDivs = di.readByte();
di.skipBytes(1);
di.skipBytes(8);
di.skipBytes(1); // numColors
di.skipBytes(8); // xDivs/yDivs offset
int padLeft = di.readInt();
int padRight = di.readInt();
int padTop = di.readInt();
int padBottom = di.readInt();
di.skipBytes(4);
di.skipBytes(4); // colorsOffset
int[] xDivs = di.readIntArray(numXDivs);
int[] yDivs = di.readIntArray(numYDivs);
@ -138,4 +193,25 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
yDivs);
}
}
private static class OpticalInset {
public final int layoutBoundsLeft, layoutBoundsTop, layoutBoundsRight, layoutBoundsBottom;
public OpticalInset(int layoutBoundsLeft, int layoutBoundsTop,
int layoutBoundsRight, int layoutBoundsBottom) {
this.layoutBoundsLeft = layoutBoundsLeft;
this.layoutBoundsTop = layoutBoundsTop;
this.layoutBoundsRight = layoutBoundsRight;
this.layoutBoundsBottom = layoutBoundsBottom;
}
public static OpticalInset decode(ExtDataInput di) throws IOException {
int layoutBoundsLeft = Integer.reverseBytes(di.readInt());
int layoutBoundsTop = Integer.reverseBytes(di.readInt());
int layoutBoundsRight = Integer.reverseBytes(di.readInt());
int layoutBoundsBottom = Integer.reverseBytes(di.readInt());
return new OpticalInset(layoutBoundsLeft, layoutBoundsTop,
layoutBoundsRight, layoutBoundsBottom);
}
}
}

View File

@ -131,8 +131,14 @@ public class StringBlock {
if (style == null) {
return ResXmlEncoders.escapeXmlChars(raw);
}
// If the returned style is further in string, than string length. Lets skip it.
if (style[1] > raw.length()) {
return ResXmlEncoders.escapeXmlChars(raw);
}
StringBuilder html = new StringBuilder(raw.length() + 32);
int[] opened = new int[style.length / 3];
boolean[] unclosed = new boolean[style.length / 3];
int offset = 0, depth = 0;
while (true) {
int i = -1, j;
@ -149,6 +155,9 @@ public class StringBlock {
int last = opened[j];
int end = style[last + 2];
if (end >= start) {
if (style[last + 1] == -1 && end != -1) {
unclosed[j] = true;
}
break;
}
if (offset <= end) {
@ -160,6 +169,11 @@ public class StringBlock {
depth = j + 1;
if (offset < start) {
html.append(ResXmlEncoders.escapeXmlChars(raw.substring(offset, start)));
if (j >= 0 && unclosed.length >= j && unclosed[j]) {
if (unclosed.length > (j + 1) && unclosed[j + 1] || unclosed.length == 1) {
outputStyleTag(getString(style[opened[j]]), html, true);
}
}
offset = start;
}
if (i == -1) {

View File

@ -246,6 +246,8 @@ public final class ResXmlPatcher {
throws IOException, SAXException, ParserConfigurationException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
docFactory.setFeature(FEATURE_DISABLE_DOCTYPE_DECL, true);
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
return docBuilder.parse(file);
}
@ -264,10 +266,10 @@ public final class ResXmlPatcher {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.STANDALONE,"yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(file);
transformer.transform(source, result);
}
private static final String FEATURE_DISABLE_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
}

View File

@ -21,7 +21,6 @@ import brut.common.BrutException;
import brut.util.OS;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import org.junit.*;
import static org.junit.Assert.*;
@ -29,10 +28,10 @@ import static org.junit.Assert.*;
public class AndResGuardTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
TestUtils.copyResourceDir(LargeIntsInManifestTest.class, "brut/apktool/issue1170/", sTmpDir);
TestUtils.copyResourceDir(AndResGuardTest.class, "brut/apktool/issue1170/", sTmpDir);
}
@AfterClass
@ -62,6 +61,4 @@ public class AndResGuardTest {
private static ExtFile sTmpDir;
private static ExtFile sTestOrigDir;
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeTest.class.getName());
}
}

View File

@ -33,7 +33,7 @@ import static org.junit.Assert.assertTrue;
public class BuildAndDecodeJarTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
sTestOrigDir = new ExtFile(sTmpDir, "testjar-orig");
@ -66,4 +66,4 @@ public class BuildAndDecodeJarTest {
private static ExtFile sTestNewDir;
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeJarTest.class.getName());
}
}

View File

@ -44,7 +44,7 @@ import javax.imageio.ImageIO;
public class BuildAndDecodeTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
@ -253,6 +253,11 @@ public class BuildAndDecodeTest {
compareValuesFiles("values-ast/strings.xml");
}
@Test
public void androidOStringTest() throws BrutException, IOException {
compareValuesFiles("values-ast/strings.xml");
}
@Test
public void twoLetterNotHandledAsBcpTest() throws BrutException, IOException {
checkFolderExists("res/values-fr");
@ -345,6 +350,89 @@ public class BuildAndDecodeTest {
assertEquals(controlImage.getRGB(30, 30), testImage.getRGB(30, 30));
}
@Test
public void issue1508Test() throws BrutException, IOException {
char slash = File.separatorChar;
String location = slash + "res" + slash + "drawable-xhdpi" + slash;
File control = new File((sTestOrigDir + location), "btn_zoom_up_normal.9.png");
File test = new File((sTestNewDir + location), "btn_zoom_up_normal.9.png");
BufferedImage controlImage = ImageIO.read(control);
BufferedImage testImage = ImageIO.read(test);
// 0, 0 = clear
assertEquals(controlImage.getRGB(0, 0), testImage.getRGB(0, 0));
// 30, 0 = black line
assertEquals(controlImage.getRGB(0, 30), testImage.getRGB(0, 30));
// 30, 30 = greyish button
assertEquals(controlImage.getRGB(30, 30), testImage.getRGB(30, 30));
}
@Test
public void issue1511Test() throws BrutException, IOException {
char slash = File.separatorChar;
String location = slash + "res" + slash + "drawable-xxhdpi" + slash;
File control = new File((sTestOrigDir + location), "textfield_activated_holo_dark.9.png");
File test = new File((sTestNewDir + location), "textfield_activated_holo_dark.9.png");
BufferedImage controlImage = ImageIO.read(control);
BufferedImage testImage = ImageIO.read(test);
// Check entire image as we cannot mess this up
final int w = controlImage.getWidth(),
h = controlImage.getHeight();
final int[] controlImageGrid = controlImage.getRGB(0, 0, w, h, null, 0, w);
final int[] testImageGrid = testImage.getRGB(0, 0, w, h, null, 0, w);
for (int i = 0; i < controlImageGrid.length; i++) {
assertEquals("Image lost Optical Bounds at i = " + i, controlImageGrid[i], testImageGrid[i]);
}
}
@Test
public void robust9patchTest() throws BrutException, IOException {
String[] ninePatches = {"ic_notification_overlay.9.png", "status_background.9.png",
"search_bg_transparent.9.png", "screenshot_panel.9.png", "recents_lower_gradient.9.png"};
char slash = File.separatorChar;
String location = slash + "res" + slash + "drawable-xxhdpi" + slash;
for (String ninePatch : ninePatches) {
File control = new File((sTestOrigDir + location), ninePatch);
File test = new File((sTestNewDir + location), ninePatch);
BufferedImage controlImage = ImageIO.read(control);
BufferedImage testImage = ImageIO.read(test);
int w = controlImage.getWidth(), h = controlImage.getHeight();
// Check the entire horizontal line
for (int i = 1; i < w; i++) {
if (isTransparent(controlImage.getRGB(i, 0))) {
assertTrue(isTransparent(testImage.getRGB(i, 0)));
} else {
assertEquals("Image lost npTc chunk on image " + ninePatch + " at (x, y) (" + i + "," + 0 + ")",
controlImage.getRGB(i, 0), testImage.getRGB(i, 0));
}
}
// Check the entire vertical line
for (int i = 1; i < h; i++) {
if (isTransparent(controlImage.getRGB(0, i))) {
assertTrue(isTransparent(testImage.getRGB(0, i)));
} else {
assertEquals("Image lost npTc chunk on image " + ninePatch + " at (x, y) (" + 0 + "," + i + ")",
controlImage.getRGB(0, i), testImage.getRGB(0, i));
}
}
}
}
@Test
public void drawableXxhdpiTest() throws BrutException, IOException {
compareResFolder("drawable-xxhdpi");
@ -465,6 +553,10 @@ public class BuildAndDecodeTest {
assertTrue(f.isDirectory());
}
private boolean isTransparent(int pixel) {
return pixel >> 24 == 0x00;
}
private void compareXmlFiles(String path, ElementQualifier qualifier) throws BrutException {
DetailedDiff diff;
try {

View File

@ -37,7 +37,7 @@ import static org.junit.Assert.assertTrue;
public class DebugTagRetainedTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
sTestOrigDir = new ExtFile(sTmpDir, "issue1235-orig");

View File

@ -18,12 +18,12 @@ import static org.junit.Assert.assertEquals;
public class DefaultBaksmaliVariableTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
sTmpDir = new ExtFile(OS.createTempDirectory());
sTestOrigDir = new ExtFile(sTmpDir, "testjar-orig");
sTestNewDir = new ExtFile(sTmpDir, "testjar-new");
LOGGER.info("Unpacking testjar...");
TestUtils.copyResourceDir(BuildAndDecodeJarTest.class, "brut/apktool/issue1481/", sTestOrigDir);
TestUtils.copyResourceDir(DefaultBaksmaliVariableTest.class, "brut/apktool/issue1481/", sTestOrigDir);
LOGGER.info("Building issue1481.jar...");
File testJar = new File(sTmpDir, "issue1481.jar");
@ -99,5 +99,5 @@ public class DefaultBaksmaliVariableTest {
private static ExtFile sTestOrigDir;
private static ExtFile sTestNewDir;
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeJarTest.class.getName());
private final static Logger LOGGER = Logger.getLogger(DefaultBaksmaliVariableTest.class.getName());
}

View File

@ -27,7 +27,6 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import static org.junit.Assert.assertTrue;
@ -37,10 +36,10 @@ import static org.junit.Assert.assertTrue;
public class DoubleExtensionUnknownFileTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
TestUtils.copyResourceDir(LargeIntsInManifestTest.class, "brut/apktool/issue1244/", sTmpDir);
TestUtils.copyResourceDir(DoubleExtensionUnknownFileTest.class, "brut/apktool/issue1244/", sTmpDir);
}
@AfterClass
@ -67,6 +66,4 @@ public class DoubleExtensionUnknownFileTest {
}
private static ExtFile sTmpDir;
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeJarTest.class.getName());
}

View File

@ -0,0 +1,76 @@
/**
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright 2016 Connor Tumbleson <connor.tumbleson@gmail.com>
*
* 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;
import brut.directory.ExtFile;
import brut.common.BrutException;
import brut.util.OS;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;
/**
* @author Connor Tumbleson <connor.tumbleson@gmail.com>
*/
public class ExternalEntityTest {
@BeforeClass
public static void beforeClass() throws Exception {
sOrigDir = new ExtFile(OS.createTempDirectory());
TestUtils.copyResourceDir(ExternalEntityTest.class, "brut/apktool/doctype/", sOrigDir);
LOGGER.info("Building doctype.apk...");
File testApk = new File(sOrigDir, "doctype.apk");
new Androlib().build(sOrigDir, testApk);
LOGGER.info("Decoding doctype.apk...");
ApkDecoder apkDecoder = new ApkDecoder(testApk);
apkDecoder.setOutDir(new File(sOrigDir + File.separator + "output"));
apkDecoder.decode();
}
@AfterClass
public static void afterClass() throws BrutException {
OS.rmdir(sOrigDir);
}
@Test
public void doctypeTest() throws BrutException, IOException {
String expected = TestUtils.replaceNewlines("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<manifest android:versionCode=\"1\" android:versionName=\"1.0\" hardwareAccelerated=\"true\" package=\"com.ibotpeaches.doctype\" platformBuildVersionCode=\"23\" platformBuildVersionName=\"6.0-2438415\"\n" +
" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n" +
" <supports-screens android:anyDensity=\"true\" android:smallScreens=\"true\" android:normalScreens=\"true\" android:largeScreens=\"true\" android:resizeable=\"true\" android:xlargeScreens=\"true\" />\n" +
"</manifest>");
byte[] encoded = Files.readAllBytes(Paths.get(sOrigDir + File.separator + "output" + File.separator + "AndroidManifest.xml"));
String obtained = TestUtils.replaceNewlines(new String(encoded));
assertEquals(expected, obtained);
}
private static ExtFile sOrigDir;
private final static Logger LOGGER = Logger.getLogger(ExternalEntityTest.class.getName());
}

View File

@ -22,7 +22,6 @@ import brut.util.OS;
import java.io.*;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import org.custommonkey.xmlunit.*;
import org.junit.*;
@ -32,7 +31,7 @@ import org.xml.sax.SAXException;
public class LargeIntsInManifestTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
TestUtils.copyResourceDir(LargeIntsInManifestTest.class, "brut/apktool/issue767/", sTmpDir);
@ -94,6 +93,4 @@ public class LargeIntsInManifestTest {
private static ExtFile sTmpDir;
private static ExtFile sTestOrigDir;
private static ExtFile sTestNewDir;
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeTest.class.getName());
}

View File

@ -35,10 +35,10 @@ import static org.junit.Assert.assertEquals;
public class MissingVersionManifestTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
TestUtils.copyResourceDir(LargeIntsInManifestTest.class, "brut/apktool/issue1264/", sTmpDir);
TestUtils.copyResourceDir(MissingVersionManifestTest.class, "brut/apktool/issue1264/", sTmpDir);
}
@AfterClass
@ -61,6 +61,4 @@ public class MissingVersionManifestTest {
}
private static ExtFile sTmpDir;
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeJarTest.class.getName());
}

View File

@ -17,7 +17,6 @@ package brut.androlib;
import brut.androlib.res.xml.ResXmlEncoders;
import org.junit.Test;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;
@ -54,6 +53,4 @@ public class PositionalEnumerationTest {
private String enumerateArguments(String value) {
return ResXmlEncoders.enumerateNonPositionalSubstitutionsIfRequired(value);
}
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeJarTest.class.getName());
}

View File

@ -84,4 +84,4 @@ public class ProviderAttributeTest {
}
private static ExtFile sTmpDir;
}
}

View File

@ -25,7 +25,6 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;
@ -35,10 +34,10 @@ import static org.junit.Assert.assertEquals;
public class ReferenceVersionCodeTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
TestUtils.copyResourceDir(LargeIntsInManifestTest.class, "brut/apktool/issue1234/", sTmpDir);
TestUtils.copyResourceDir(ReferenceVersionCodeTest.class, "brut/apktool/issue1234/", sTmpDir);
}
@AfterClass
@ -61,6 +60,4 @@ public class ReferenceVersionCodeTest {
}
private static ExtFile sTmpDir;
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeJarTest.class.getName());
}

View File

@ -25,7 +25,6 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
@ -36,10 +35,10 @@ import static org.junit.Assert.assertNotSame;
public class UnknownCompressionTest {
@BeforeClass
public static void beforeClass() throws Exception, BrutException {
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
TestUtils.copyResourceDir(LargeIntsInManifestTest.class, "brut/apktool/unknown_compression/", sTmpDir);
TestUtils.copyResourceDir(UnknownCompressionTest.class, "brut/apktool/unknown_compression/", sTmpDir);
String apk = "deflated_unknowns.apk";
ApkOptions apkOptions = new ApkOptions();
@ -90,6 +89,4 @@ public class UnknownCompressionTest {
private static ExtFile sOriginalFile;
private static ExtFile sBuiltFile;
private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeJarTest.class.getName());
}

View File

@ -25,7 +25,6 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import static org.junit.Assert.assertTrue;
@ -66,6 +65,4 @@ public class VectorDrawableTest {
private static ExtFile sTmpDir;
private static ExtFile sTestOrigDir;
private final static Logger LOGGER = Logger.getLogger(VectorDrawableTest.class.getName());
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE manifest [<!ENTITY e1 SYSTEM 'http://ibotpeaches.com?z=APKTOOLXXE;'>]>
<manifest hardwareAccelerated="true" package="com.ibotpeaches.doctype" platformBuildVersionCode="24" platformBuildVersionName="6.0-2456767" xmlns:android="http://schemas.android.com/apk/res/android">
&e1;
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true"/>
</manifest>

View File

@ -0,0 +1,12 @@
version: 2.0.0
apkFileName: doctype.apk
isFrameworkApk: false
usesFramework:
ids:
- 1
packageInfo:
forced-package-id: '127'
versionInfo:
versionCode: '1'
versionName: '1.0'
compressionType: false

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="test1">"Forgot your username or password?\nVisit google.com/accounts/recovery."</string>
<string name="test2">Forgot your username or password?\n.Visit google.com/accounts/recovery</string>
<string name="test3"> (string8) "Forgot your username or password?\nVisit google.com/accounts/recovery."</string>
<string name="test4">Forgot your username or password?\nVisit google.com/accounts/recovery.</string>
<string name="test5">Forgot your username or password?
Visit google.com/accounts/recovery.</string>
</resources>

View File

@ -31,4 +31,14 @@ bar"</string>
<string name="test_string29" formatted="false">category=temp%temp%foo</string>
<string name="test_string30">res/foo/</string>
<string name="test_string31">res/foo</string>
<string name="test_string32">[<font size="17">TEST STRING</font>]</string>
<string name="test_string33"><font size="17">[TEST STRING]</font></string>
<string name="test_string34">[<font size="17">TEST STRING]</font></string>
<string name="test_string35"><font size="17">[TEST STRING</font>]</string>
<string name="test_string36"><font size="17">TEST STRING</font></string>
<string name="test_string37">[<font size="17">Ţåþ ţö ţýþé þåššŵöŕð one two three]</font></string>
<string name="test_string38">[<font size="17">Ţåþ ţö ţýþé þåššŵöŕð one two three</font>]</string>
<string name="test_string39"><font size="17">[Ţåþ ţö ţýþé þåššŵöŕð one two three</font>]</string>
<string name="test_string40">[<font size="17">]Ţåþ ţö ţýþé þåššŵöŕð one two three</font></string>
<string name="test_string41"><font size="17">[Ţåþ ţö ţýþé þåššŵöŕð one two three]</font></string>
</resources>

View File

@ -82,7 +82,7 @@ subprojects {
ext {
depends = [
baksmali: 'org.smali:baksmali:2.2.0',
baksmali: 'org.smali:baksmali:2.2.1',
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',
@ -91,7 +91,7 @@ subprojects {
junit: 'junit:junit:4.12',
proguard_gradle: 'net.sf.proguard:proguard-gradle:5.2.1',
snakeyaml: 'org.yaml:snakeyaml:1.17',
smali: 'org.smali:smali:2.2.0',
smali: 'org.smali:smali:2.2.1',
xmlpull: 'xpp3:xpp3:1.1.4c',
xmlunit: 'xmlunit:xmlunit:1.3',
]