From e126a51b4bb8991042b48ec5bf916f396e75f6f0 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Wed, 18 Jun 2014 10:59:54 -0500 Subject: [PATCH] handles manifests with missing named attributes. - fixes #512 --- CHANGES | 1 + .../res/decoder/AXmlResourceParser.java | 34 +++++++++++++++++-- .../androlib/res/decoder/ResAttrDecoder.java | 15 ++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index f60e2e3f..0e51ad1b 100644 --- a/CHANGES +++ b/CHANGES @@ -40,6 +40,7 @@ v2.0.0 (TBA) -Fixed (issue #626) - Fixed handling strange characters with unknown files. -Fixed (issue #630) - Fixed handling renamed manifests with ("com.lge") -Fixed (issue #409) - Fixed array items incorrectly typed. +-Fixed (issue #512) - Fixed AndroidManifest missing attributes. -Fixed issue with non-URI standard characters in apk name (Thanks rover12421) -Added output to list Apktool version to help debugging. -Updated known bytes for configurations to 38 (from addition of layout direction) 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 6de78b35..526b5081 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 @@ -282,7 +282,22 @@ public class AXmlResourceParser implements XmlResourceParser { if (namespace == -1) { return ""; } - return m_strings.getString(namespace); + + // hacky: if the attribute names are proguarded, then so are the namespace + // I don't know where these are located yet in the file, but it is always + // this.android_ns in testing, so we will default to that for now. + // @todo figure out where proguarded namespaces are stored. + String value = m_strings.getString(namespace); + + if (value.length() == 0) { + int offsetName = getAttributeOffset(index); + int name = m_attributes[offsetName + ATTRIBUTE_IX_NAME]; + if (m_strings.getString(name).length() == 0) { + value = android_ns; + } + } + + return value; } @Override @@ -303,7 +318,21 @@ public class AXmlResourceParser implements XmlResourceParser { if (name == -1) { return ""; } - return m_strings.getString(name); + + String value = m_strings.getString(name); + + // some attributes will return "", we must rely on the resource_id and refer to the frameworks + // to match the resource id to the name. ex: 0x101021C = versionName + if (value.length() != 0) { + return value; + } else { + try { + value = mAttrDecoder.decodeManifestAttr(getAttributeNameResource(index)); + } catch (AndrolibException e) { + value = ""; + } + return value; + } } @Override @@ -941,6 +970,7 @@ public class AXmlResourceParser implements XmlResourceParser { private StringBlock m_strings; private int[] m_resourceIDs; private NamespaceStack m_namespaces = new NamespaceStack(); + private String android_ns = "http://schemas.android.com/apk/res/android"; private boolean m_decreaseDepth; private int m_event; private int m_lineNumber; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResAttrDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResAttrDecoder.java index dda44168..30dd350c 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResAttrDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResAttrDecoder.java @@ -18,6 +18,7 @@ package brut.androlib.res.decoder; import brut.androlib.AndrolibException; import brut.androlib.res.data.ResPackage; +import brut.androlib.res.data.ResResSpec; import brut.androlib.res.data.value.ResAttr; import brut.androlib.res.data.value.ResScalarValue; @@ -40,6 +41,20 @@ public class ResAttrDecoder { return decoded != null ? decoded : resValue.encodeAsResXmlAttr(); } + public String decodeManifestAttr(int attrResId) + throws AndrolibException { + + if (attrResId != 0) { + ResResSpec resResSpec = getCurrentPackage().getResTable().getResSpec(attrResId); + + if (resResSpec != null) { + return resResSpec.getName(); + } + } + + return null; + } + public ResPackage getCurrentPackage() throws AndrolibException { if (mCurrentPackage == null) { throw new AndrolibException("Current package not set");