Skip to content

Commit 07189f8

Browse files
committed
Support direct loading from an APK file
To disable APK loading pass -DENABLE_APK_LOADING=NO to CMake.
1 parent c336d00 commit 07189f8

File tree

7 files changed

+216
-75
lines changed

7 files changed

+216
-75
lines changed

CMakeLists.txt

+33-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
cmake_minimum_required(VERSION 2.8.11)
22

33
project(axmldec C CXX)
4+
option(ENABLE_APK_LOADING "enable loading from an APK file" ON)
45
set(AXMLDEC_VERSION_MAJOR 1)
56
set(AXMLDEC_VERSION_MINOR 1)
67
set(AXMLDEC_VERSION_PATCH 0)
@@ -38,15 +39,6 @@ add_definitions(
3839
include_directories("${PROJECT_BINARY_DIR}")
3940
include_directories("include")
4041

41-
set(BOOST_MIN_VERSION "1.53.0")
42-
find_package(Boost ${BOOST_MIN_VERSION}
43-
COMPONENTS system iostreams program_options locale REQUIRED)
44-
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
45-
add_definitions(
46-
-DBOOST_MAJOR_VERSION=${Boost_MAJOR_VERSION}
47-
-DBOOST_MINOR_VERSION=${Boost_MINOR_VERSION}
48-
)
49-
5042
#-------------------------------------------------------------------------------
5143
# axmldec
5244
#-------------------------------------------------------------------------------
@@ -57,8 +49,37 @@ add_executable(axmldec
5749
include/jitana/util/stream_reader.hpp
5850
lib/jitana/util/axml_parser.cpp
5951
)
52+
53+
set(BOOST_MIN_VERSION "1.53.0")
54+
find_package(Boost ${BOOST_MIN_VERSION}
55+
COMPONENTS system iostreams program_options locale REQUIRED)
56+
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
57+
add_definitions(
58+
-DBOOST_MAJOR_VERSION=${Boost_MAJOR_VERSION}
59+
-DBOOST_MINOR_VERSION=${Boost_MINOR_VERSION}
60+
)
6061
target_link_libraries(axmldec ${Boost_LIBRARIES})
6162

63+
if(ENABLE_APK_LOADING)
64+
find_package(ZLIB REQUIRED)
65+
include_directories(${ZLIB_INCLUDE_DIR})
66+
67+
add_definitions(
68+
-DENABLE_APK_LOADING=1
69+
)
70+
add_library(minizip STATIC
71+
${CMAKE_CURRENT_SOURCE_DIR}/external/minizip/unzip.c
72+
${CMAKE_CURRENT_SOURCE_DIR}/external/minizip/ioapi.c
73+
)
74+
set_target_properties(minizip PROPERTIES
75+
COMPILE_DEFINITIONS "NOUNCRYPT;NOCRYPT")
76+
target_link_libraries(minizip ${ZLIB_LIBRARIES})
77+
set(MINIZIP_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/external/minizip)
78+
set(MINIZIP_LIBRARIES minizip)
79+
include_directories(SYSTEM ${MINIZIP_INCLUDE_DIR})
80+
target_link_libraries(axmldec ${MINIZIP_LIBRARIES})
81+
endif()
82+
6283
#-------------------------------------------------------------------------------
6384
# Install
6485
#-------------------------------------------------------------------------------
@@ -70,7 +91,7 @@ install(TARGETS axmldec DESTINATION bin)
7091
#-------------------------------------------------------------------------------
7192

7293
add_custom_target(format
73-
find . \\\( -name "*.hpp" -or -name "*.cpp" \\\)
94+
find main.cpp include lib \\\( -name "*.hpp" -or -name "*.cpp" \\\)
7495
-type f -exec clang-format -i {} \\+
7596
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
7697
)
@@ -80,7 +101,7 @@ add_custom_target(format
80101
#-------------------------------------------------------------------------------
81102

82103
add_custom_target(count
83-
find . \\\( -name "*.hpp" -or -name -name "*.cpp" \\\)
104+
find main.cpp include lib \\\( -name "*.hpp" -or -name -name "*.cpp" \\\)
84105
-print0 | xargs -0 wc -l
85106
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
86107
)
@@ -112,4 +133,4 @@ if(DOXYGEN_FOUND)
112133
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
113134
COMMENT "Generating API documentation with Doxygen" VERBATIM
114135
)
115-
endif(DOXYGEN_FOUND)
136+
endif()

README.md

+35-21
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ axmldec: Android Binary XML Decoder
33

44
## 1 Overview
55

6-
[`AndroidManifest.xml`][Android App Manifest] in an [APK file][APK] can be
7-
binary encoded. This tool accepts either a binary or a text XML file and prints
8-
the decoded XML to the standard output or a file.
6+
[`AndroidManifest.xml`][Android App Manifest] in an [APK file][APK] is binary
7+
encoded. This tool accepts either a binary or a text XML file and prints the
8+
decoded XML to the standard output or a file. It also allows you to extract the
9+
decoded `AndroidManifest.xml` directly from an APK file.
910

1011
![](doc/overview.png)
1112

@@ -45,36 +46,49 @@ Build the tool from the source code (see below).
4546

4647
## 3 Usage
4748

48-
### 3.1 Retrieving `AndroidManifest.xml` from an APK File
49+
### 3.1 Decoding `AndroidManifest.xml`
4950

50-
1. Use `unzip` to extract the manifest file from an APK file:
51-
```sh
52-
unzip -j com.example.app.apk AndroidManifest.xml
53-
```
51+
Pass the manifest file (either binary or text) to decodedecode:
52+
```sh
53+
axmldec -o output.xml AndroidManifest.xml
54+
```
5455

55-
2. Pass the manifest file (either binary or text) to decode:
56-
```sh
57-
axmldec -o output.xml AndroidManifest.xml
58-
```
56+
This will write the decoded XML to `output.xml`. You can specify the same
57+
filename for input and output to decode the file in-place.
58+
59+
### 3.2 Decoding `AndroidManifest.xml` in an APK File
5960

60-
This will write the decoded XML to `output.xml`. You can specify the same
61-
filename for input and output to decode the file in-place.
61+
If an APK file is specified, axmldec automatically extracts and decodes
62+
`AndroidManifest.xml`:
63+
```sh
64+
axmldec -o output.xml com.example.app.apk
65+
```
6266

63-
### 3.2 Using the Standard Output
67+
### 3.3 Using the Standard Output
6468

6569
axmldec writes to the standard output if the `-o` option is not specified. This
6670
is useful when additional processing is required. For example, you can extract
67-
the package name using `xmllint`:
71+
the package name from an APK file using xmllint:
6872
```sh
69-
axmldec AndroidManifest.xml | xmllint --xpath 'string(/manifest/@package)' -
73+
axmldec com.example.app.apk | xmllint --xpath 'string(/manifest/@package)' -
7074
```
7175

7276
## 4 Building
7377

74-
Install Boost and CMake. Make sure you have a latest C++ compiler. Then compile:
75-
```sh
76-
cmake -DCMAKE_BUILD_TYPE=Release . && make
77-
```
78+
1. Install Boost, zlib, and CMake. Make sure you have a latest C++ compiler.
79+
80+
2. Clone axmldec and its submodule from GitHub:
81+
```sh
82+
git clone --recursive https://github.com/ytsutano/axmldec.git
83+
```
84+
85+
3. Compile axmldec:
86+
```sh
87+
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_APK_LOADING=YES . && make
88+
```
89+
90+
You can specify `-DENABLE_APK_LOADING=NO` to disable APK loading. In this
91+
case, zlib is not required.
7892

7993
## 5 Developer
8094

doc/overview.dot

+23-13
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,46 @@
11
digraph {
22
rankdir=LR;
3-
ranksep=0.6;
3+
ranksep=0.1
4+
5+
edge [fontsize=10];
6+
7+
{
8+
xml [label="AndroidManifest.xml\n(Binary/Text XML)", shape=none];
9+
apk [label="com.example.app.apk", shape=none];
10+
rank=same;
11+
}
12+
decoded_xml [label="output.xml\n(Text XML)", shape=none];
13+
14+
xml -> apk [style=invis];
415

516
subgraph cluster_axmldec {
617
{
7-
818
node [style=filled, color=gray87, shape=none, fontname=Courier, fontsize=12, fontcolor=midnightblue];
19+
extract_manifest [label="extract_manifest()", URL="https://github.com/ytsutano/axmldec/blob/master/main.cpp"];
920
{
10-
read_xml [label="boost_pt::read_xml()", URL="http://www.boost.org/doc/libs/1_64_0/doc/html/boost/property_tree/xml_parser/read_xml_idp683796192.html"];
11-
read_axml [label="jitana::read_axml()", URL="https://github.com/ytsutano/axmldec/blob/master/include/jitana/util/axml_parser.hpp"];
21+
read_xml [label="boost_pt::\nread_xml()", URL="http://www.boost.org/doc/libs/1_64_0/doc/html/boost/property_tree/xml_parser/read_xml_idp683796192.html"];
22+
read_axml [label="jitana::\nread_axml()", URL="https://github.com/ytsutano/axmldec/blob/master/include/jitana/util/axml_parser.hpp"];
1223
rank=same;
1324
}
14-
write_xml [label="boost_pt::write_xml()", URL="http://www.boost.org/doc/libs/1_64_0/doc/html/boost/property_tree/xml_parser/write_xml_idp683815200.html"];
25+
write_xml [label="boost_pt::\nwrite_xml()", URL="http://www.boost.org/doc/libs/1_64_0/doc/html/boost/property_tree/xml_parser/write_xml_idp683815200.html"];
26+
read_axml_xml [shape=point];
1527
}
16-
ptree [label="Boost\nProperty Tree", shape="none", URL="http://www.boost.org/doc/libs/1_64_0/doc/html/property_tree.html"];
28+
ptree [label="Boost\nProperty Tree", shape=none, URL="http://www.boost.org/doc/libs/1_64_0/doc/html/property_tree.html"];
1729

1830
read_axml -> ptree;
1931
read_xml -> ptree;
32+
extract_manifest -> read_axml [label="Binary", weight=1000];
2033
ptree -> write_xml;
2134

2235
style=filled;
2336
color=gray95;
24-
label="axmldec -o output.xml AndroidManifest.xml";
37+
label="axmldec -o output.xml AndroidManifest.xml\naxmldec -o output.xml com.example.app.apk\n ";
2538
fontname=Courier;
2639
fontcolor=midnightblue
2740
}
2841

29-
axml [label="Android\nBinary XML", shape="none"];
30-
txml [label="Standard\nText XML", shape="none"];
31-
decoded_xml [label="Decoded\nStandard\nText XML", shape="none"];
32-
33-
axml -> read_axml;
34-
txml -> read_xml;
42+
xml -> read_axml [xlabel="Binary"];
43+
xml -> read_xml [xlabel="Text"];
44+
apk -> extract_manifest;
3545
write_xml -> decoded_xml;
3646
}

doc/overview.png

30.1 KB
Loading

include/jitana/util/axml_parser.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ namespace jitana {
3535

3636
void read_axml(const std::string& filename,
3737
boost::property_tree::ptree& pt);
38+
39+
void read_axml(std::istream& stream, boost::property_tree::ptree& pt);
3840
}
3941

4042
#endif

lib/jitana/util/axml_parser.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1868,3 +1868,15 @@ void jitana::read_axml(const std::string& filename,
18681868
axml_parser p(reader, pt);
18691869
p.parse();
18701870
}
1871+
1872+
void jitana::read_axml(std::istream& stream, boost::property_tree::ptree& pt)
1873+
{
1874+
std::vector<uint8_t> buffer;
1875+
std::for_each(std::istreambuf_iterator<char>(stream),
1876+
std::istreambuf_iterator<char>(),
1877+
[&buffer](const char c) { buffer.push_back(c); });
1878+
1879+
stream_reader reader(buffer.data(), buffer.data() + buffer.size());
1880+
axml_parser p(reader, pt);
1881+
p.parse();
1882+
}

0 commit comments

Comments
 (0)