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 3371a6c3..d563c8b4 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 @@ -47,17 +47,17 @@ import org.jf.util.ConsoleUtil; public class Main { public static void main(String[] args) throws IOException, InterruptedException, BrutException { - + // set verbosity default Verbosity verbosity = Verbosity.NORMAL; - + // cli parser CommandLineParser parser = new PosixParser(); CommandLine commandLine = null; - + // load options _Options(); - + try { commandLine = parser.parse(allOptions, args, false); } catch (ParseException ex) { @@ -65,7 +65,7 @@ public class Main { usage(commandLine); return; } - + // check for verbose / quiet if (commandLine.hasOption("-v") || commandLine.hasOption("--verbose")) { verbosity = Verbosity.VERBOSE; @@ -73,7 +73,7 @@ public class Main { verbosity = Verbosity.QUIET; } setupLogging(verbosity); - + // check for advance mode if (commandLine.hasOption("advance") || commandLine.hasOption("advanced")) { setAdvanceMode(true); @@ -81,7 +81,7 @@ public class Main { // @todo use new ability of apache-commons-cli to check hasOption for non-prefixed items boolean cmdFound = false; - for (String opt : commandLine.getArgs()) { + for (String opt : commandLine.getArgs()) { if (opt.equalsIgnoreCase("d") || opt.equalsIgnoreCase("decode")) { cmdDecode(commandLine); cmdFound = true; @@ -96,7 +96,7 @@ public class Main { cmdFound = true; } } - + // if no commands ran, run the version / usage check. if (cmdFound == false) { if (commandLine.hasOption("version") || commandLine.hasOption("version")) { @@ -109,11 +109,11 @@ public class Main { private static void cmdDecode(CommandLine cli) throws AndrolibException { ApkDecoder decoder = new ApkDecoder(); - + int paraCount = cli.getArgList().size(); String apkName = (String) cli.getArgList().get(paraCount - 1); File outDir = null; - + // check for options if (cli.hasOption("s") || cli.hasOption("no-src")) { decoder.setDecodeSources(ApkDecoder.DECODE_SOURCES_NONE); @@ -142,18 +142,18 @@ public class Main { if (cli.hasOption("o") || cli.hasOption("output")) { decoder.setOutDir(new File(cli.getOptionValue("o"))); } else { - + // make out folder manually using name of apk String outName = apkName; outName = outName.endsWith(".apk") ? outName.substring(0, outName.length() - 4) : outName + ".out"; - + // make file from path outName = new File(outName).getName(); outDir = new File(outName); decoder.setOutDir(outDir); } - + decoder.setApkFile(new File(apkName)); try { @@ -189,7 +189,7 @@ public class Main { String appDirName = "."; File outFile = null; Androlib instance = new Androlib(); - + // hold all the fields HashMap flags = new HashMap(); flags.put("forceBuildAll", false); @@ -223,11 +223,11 @@ public class Main { } else { outFile = null; } - + if (apkName != null) { appDirName = apkName; } - + // try and build apk instance.build(new File(appDirName), outFile, flags,mAaptPath); } @@ -238,7 +238,7 @@ public class Main { String apkName = (String) cli.getArgList().get(paraCount - 1); String tag = null; String frame_path = null; - + if (cli.hasOption("p") || cli.hasOption("frame-path")) { frame_path = cli.getOptionValue("p"); } @@ -262,112 +262,112 @@ public class Main { @SuppressWarnings("static-access") private static void _Options() { - + // create options Option versionOption = OptionBuilder.withLongOpt("version") .withDescription("prints the version then exits") .create("version"); - + Option advanceOption = OptionBuilder.withLongOpt("advanced") .withDescription("prints advance information.") .create("advance"); - + Option noSrcOption = OptionBuilder.withLongOpt("no-src") .withDescription("Do not decode sources.") .create("s"); - + Option noResOption = OptionBuilder.withLongOpt("no-res") .withDescription("Do not decode resources.") .create("r"); - + Option debugDecOption = OptionBuilder.withLongOpt("debug") .withDescription("Decode in debug mode. Check project page for more info.") .create("d"); - + Option debugBuiOption = OptionBuilder.withLongOpt("debug") .withDescription("Builds in debug mode. Check project page for more info.") .create("d"); - + Option noDbgOption = OptionBuilder.withLongOpt("no-debug-info") .withDescription("don't write out debug info (.local, .param, .line, etc.)") .create("b"); - + Option forceDecOption = OptionBuilder.withLongOpt("force") .withDescription("Force delete destination directory.") .create("f"); - + Option frameTagOption = OptionBuilder.withLongOpt("frame-tag") .withDescription("Uses framework files tagged by .") .hasArg(true) .withArgName("tag") .create("t"); - + Option frameDirOption = OptionBuilder.withLongOpt("frame-path") .withDescription("Uses framework files located in .") .hasArg(true) .withArgName("dir") .create("p"); - + Option keepResOption = OptionBuilder.withLongOpt("keep-broken-res") .withDescription("Use if there was an error and some resources were dropped, e.g.\n" + " \"Invalid config flags detected. Dropping resources\", but you\n" + " want to decode them anyway, even with errors. You will have to\n" + " fix them manually before building.") .create("k"); - + Option forceBuiOption = OptionBuilder.withLongOpt("force-all") .withDescription("Skip changes detection and build all files.") .create("f"); - + Option aaptOption = OptionBuilder.withLongOpt("aapt") .hasArg(true) .withArgName("loc") .withDescription("Loads aapt from specified location.") .create("a"); - + Option originalOption = OptionBuilder.withLongOpt("copy-original") .withDescription("Copies original AndroidManifest.xml and META-INF. See project page for more info.") .create("c"); - + Option tagOption = OptionBuilder.withLongOpt("tag") .withDescription("Tag frameworks using .") .hasArg(true) .withArgName("tag") .create("t"); - + Option outputBuiOption = OptionBuilder.withLongOpt("output") .withDescription("The name of apk that gets written. Default is dist/name.apk") .hasArg(true) .withArgName("dir") .create("o"); - + Option outputDecOption = OptionBuilder.withLongOpt("output") .withDescription("The name of folder that gets written. Default is apk.out") .hasArg(true) .withArgName("dir") .create("o"); - + Option quietOption = OptionBuilder.withLongOpt("quiet") .create("q"); - + Option verboseOption = OptionBuilder.withLongOpt("verbose") .create("v"); - + // check for advance mode if (advanceMode) { DecodeOptions.addOption(debugDecOption); DecodeOptions.addOption(noDbgOption); DecodeOptions.addOption(keepResOption); - + BuildOptions.addOption(debugBuiOption); BuildOptions.addOption(aaptOption); BuildOptions.addOption(originalOption); } - + // add global options normalOptions.addOption(versionOption); normalOptions.addOption(advanceOption); - + // add basic decode options DecodeOptions.addOption(frameTagOption); DecodeOptions.addOption(outputDecOption); @@ -375,16 +375,16 @@ public class Main { DecodeOptions.addOption(forceDecOption); DecodeOptions.addOption(noSrcOption); DecodeOptions.addOption(noResOption); - + // add basic build options BuildOptions.addOption(outputBuiOption); BuildOptions.addOption(frameDirOption); BuildOptions.addOption(forceBuiOption); - + // add basic framework options frameOptions.addOption(tagOption); frameOptions.addOption(frameDirOption); - + // add all, loop existing cats then manually add advance for (Object op : normalOptions.getOptions()) { allOptions.addOption((Option)op); @@ -415,20 +415,20 @@ public class Main { return ""; } } - + private static void usage(CommandLine commandLine) { - + // load basicOptions _Options(); HelpFormatter formatter = new HelpFormatter(); - + // max their window to 120, if small. int consoleWidth = ConsoleUtil.getConsoleWidth(); if (consoleWidth <= 0) { consoleWidth = 120; } formatter.setWidth(consoleWidth); - + // print out license info prior to formatter. System.out.println( "Apktool v" + Androlib.getVersion() + " - a tool for reengineering Android apk files\n" + @@ -441,19 +441,19 @@ public class Main { }else { System.out.println(""); } - + // 4 usage outputs (general, frameworks, decode, build) formatter.printHelp("apktool " + verbosityHelp(), normalOptions); formatter.printHelp("apktool " + verbosityHelp() + "if|install-framework [options] ", frameOptions); formatter.printHelp("apktool " + verbosityHelp() + "d[ecode] [options] ", DecodeOptions); formatter.printHelp("apktool " + verbosityHelp() + "b[uild] [options] ", BuildOptions); if (advanceMode) { - formatter.printHelp("apktool " + verbosityHelp() + "publicize-resources ", + formatter.printHelp("apktool " + verbosityHelp() + "publicize-resources ", "Make all framework resources public.", emptyOptions, null); } else { System.out.println(""); } - + // print out more information System.out.println( "For additional info, see: http://code.google.com/p/android-apktool/ \n" @@ -487,9 +487,9 @@ public class Main { } } - public static boolean isAdvanceMode() { - return advanceMode; - } + public static boolean isAdvanceMode() { + return advanceMode; + } public static void setAdvanceMode(boolean advanceMode) { Main.advanceMode = advanceMode; @@ -507,7 +507,7 @@ public class Main { private final static Options frameOptions; private final static Options allOptions; private final static Options emptyOptions; - + static { //normal and advance usage output normalOptions = new Options(); 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 d900ba50..0eee68b9 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 @@ -546,7 +546,9 @@ public class Androlib { // check if file exists if (new File(appDir,entry.getKey()).isFile()) { - // apkZipFile. + + // @todo read ZipFile and inject file into + // might need to use Zip4j } } } catch (IOException ex) { 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 aee643a5..337fccb9 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 @@ -31,17 +31,17 @@ import org.xmlpull.v1.XmlPullParserException; /** * @author Ryszard Wiśniewski * @author Dmitry Skiba - * + * * Binary xml files parser. - * + * * Parser has only two states: (1) Operational state, which parser * obtains after first successful call to next() and retains until * open(), close(), or failed call to next(). (2) Closed state, which * parser obtains after open(), close(), or failed call to next(). In * this state methods return invalid values or throw exceptions. - * + * * TODO: * check all methods in closed state - * + * */ public class AXmlResourceParser implements XmlResourceParser { @@ -283,7 +283,7 @@ public class AXmlResourceParser implements XmlResourceParser { if (m_event != START_TAG) { return -1; } - return m_attributes.length / ATTRIBUTE_LENGHT; + return m_attributes.length / ATTRIBUTE_LENGTH; } @Override @@ -362,13 +362,7 @@ public class AXmlResourceParser implements XmlResourceParser { getAttributePrefix(index), getAttributeName(index), valueData), ex); } - } else { - if (valueType == TypedValue.TYPE_STRING) { - return ResXmlEncoders.escapeXmlChars(m_strings - .getString(valueRaw)); - } } - return TypedValue.coerceToString(valueType, valueData); } @@ -574,9 +568,9 @@ public class AXmlResourceParser implements XmlResourceParser { * methods search all depth frames starting from the last namespace pair of * current depth frame. All functions that operate with int, use -1 as * 'invalid value'. - * + * * !! functions expect 'prefix'+'uri' pairs, not 'uri'+'prefix' !! - * + * */ private static final class NamespaceStack { @@ -830,7 +824,7 @@ public class AXmlResourceParser implements XmlResourceParser { throw new IndexOutOfBoundsException( "Current event is not START_TAG."); } - int offset = index * ATTRIBUTE_LENGHT; + int offset = index * ATTRIBUTE_LENGTH; if (offset >= m_attributes.length) { throw new IndexOutOfBoundsException("Invalid attribute index (" + index + ")."); @@ -847,11 +841,11 @@ public class AXmlResourceParser implements XmlResourceParser { return -1; } int uri = (namespace != null) ? m_strings.find(namespace) : -1; - for (int o = 0; o != m_attributes.length; o += ATTRIBUTE_LENGHT) { + for (int o = 0; o != m_attributes.length; o += ATTRIBUTE_LENGTH) { if (name == m_attributes[o + ATTRIBUTE_IX_NAME] && (uri == -1 || uri == m_attributes[o + ATTRIBUTE_IX_NAMESPACE_URI])) { - return o / ATTRIBUTE_LENGHT; + return o / ATTRIBUTE_LENGTH; } } return -1; @@ -874,7 +868,8 @@ public class AXmlResourceParser implements XmlResourceParser { m_reader.skipCheckInt(CHUNK_AXML_FILE); /* * chunkSize - */m_reader.skipInt(); + */ + m_reader.skipInt(); m_strings = StringBlock.read(m_reader); m_namespaces.increaseDepth(); m_operational = true; @@ -960,10 +955,10 @@ public class AXmlResourceParser implements XmlResourceParser { m_styleAttribute = (m_classAttribute >>> 16) - 1; m_classAttribute = (m_classAttribute & 0xFFFF) - 1; m_attributes = m_reader.readIntArray(attributeCount - * ATTRIBUTE_LENGHT); + * ATTRIBUTE_LENGTH); for (int i = ATTRIBUTE_IX_VALUE_TYPE; i < m_attributes.length;) { m_attributes[i] = (m_attributes[i] >>> 24); - i += ATTRIBUTE_LENGHT; + i += ATTRIBUTE_LENGTH; } m_namespaces.increaseDepth(); m_event = START_TAG; @@ -988,62 +983,6 @@ public class AXmlResourceParser implements XmlResourceParser { } } - private static String formatArray(int[] array, int min, int max) { - if (max > array.length) { - max = array.length; - } - if (min < 0) { - min = 0; - } - StringBuffer sb = new StringBuffer("["); - int i = min; - while (true) { - sb.append(array[i]); - i++; - if (i < max) { - sb.append(", "); - } else { - sb.append("]"); - break; - } - } - return sb.toString(); - } - - private boolean compareAttr(int[] attr1, int[] attr2) { - // TODO: sort Attrs - /* - * ATTRIBUTE_IX_VALUE_TYPE == TYPE_STRING : ATTRIBUTE_IX_VALUE_STRING : - * ATTRIBUTE_IX_NAMESPACE_URI ATTRIBUTE_IX_NAMESPACE_URI : - * ATTRIBUTE_IX_NAME id - */ - if (attr1[ATTRIBUTE_IX_VALUE_TYPE] == TypedValue.TYPE_STRING - && attr1[ATTRIBUTE_IX_VALUE_TYPE] == attr2[ATTRIBUTE_IX_VALUE_TYPE] - && // (m_strings.touch(attr1[ATTRIBUTE_IX_VALUE_STRING], m_name) - // || - // m_strings.touch(attr2[ATTRIBUTE_IX_VALUE_STRING], - // m_name)) && - // m_strings.touch(attr1[ATTRIBUTE_IX_VALUE_STRING], m_name) - // && - attr1[ATTRIBUTE_IX_VALUE_STRING] != attr2[ATTRIBUTE_IX_VALUE_STRING]) { - return (attr1[ATTRIBUTE_IX_VALUE_STRING] < attr2[ATTRIBUTE_IX_VALUE_STRING]); - } else if ((attr1[ATTRIBUTE_IX_NAMESPACE_URI] == attr2[ATTRIBUTE_IX_NAMESPACE_URI]) - && (attr1[ATTRIBUTE_IX_NAMESPACE_URI] != -1) && // (m_strings.touch(attr1[ATTRIBUTE_IX_NAME], - // m_name) || - // m_strings.touch(attr2[ATTRIBUTE_IX_NAME], - // m_name)) && - // m_strings.touch(attr1[ATTRIBUTE_IX_NAME], - // m_name) && - (attr1[ATTRIBUTE_IX_NAME] != attr2[ATTRIBUTE_IX_NAME])) { - return (attr1[ATTRIBUTE_IX_NAME] < attr2[ATTRIBUTE_IX_NAME]); - // } else if (attr1[ATTRIBUTE_IX_NAMESPACE_URI] < - // attr2[ATTRIBUTE_IX_NAMESPACE_URI]) { - // return true; - } else { - return false; - } - } - private void setFirstError(AndrolibException error) { if (mFirstError == null) { mFirstError = error; @@ -1079,7 +1018,7 @@ public class AXmlResourceParser implements XmlResourceParser { private static final int ATTRIBUTE_IX_NAMESPACE_URI = 0, ATTRIBUTE_IX_NAME = 1, ATTRIBUTE_IX_VALUE_STRING = 2, ATTRIBUTE_IX_VALUE_TYPE = 3, ATTRIBUTE_IX_VALUE_DATA = 4, - ATTRIBUTE_LENGHT = 5; + ATTRIBUTE_LENGTH = 5; private static final int CHUNK_AXML_FILE = 0x00080003, CHUNK_RESOURCEIDS = 0x00080180, CHUNK_XML_FIRST = 0x00100100, diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/StringBlock.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/StringBlock.java index d892e13b..19f571b0 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/StringBlock.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/StringBlock.java @@ -309,20 +309,6 @@ public class StringBlock { } } - public boolean touch(int index, int own) { - if (index < 0 || m_stringOwns == null || index >= m_stringOwns.length) { - return false; - } - if (m_stringOwns[index] == -1) { - m_stringOwns[index] = own; - return true; - } else if (m_stringOwns[index] == own) { - return true; - } else { - return false; - } - } - private int[] m_stringOffsets; private byte[] m_strings; private int[] m_styleOffsets; diff --git a/brut.j.util/build.gradle b/brut.j.util/build.gradle index c77404cd..0eddbf31 100644 --- a/brut.j.util/build.gradle +++ b/brut.j.util/build.gradle @@ -15,6 +15,8 @@ */ dependencies { - compile project(':brut.j.common'), "commons-io:commons-io:2.4" + compile project(':brut.j.common') + compile "commons-io:commons-io:2.4", + "org.apache.commons:commons-compress:1.4.1" testCompile "junit:junit:3.8.1" }