Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
b55975a3
Commit
b55975a3
authored
Dec 23, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: reformat code and fix small issues in BinaryXMLParser
parent
4cb34394
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
2081 additions
and
178 deletions
+2081
-178
build.gradle
build.gradle
+0
-1
JadxCLI.java
jadx-cli/src/main/java/jadx/cli/JadxCLI.java
+0
-7
JadxCLIArgs.java
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
+1
-1
JadxDecompiler.java
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+9
-6
InputFile.java
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
+4
-2
AndroidR.java
jadx-core/src/main/java/jadx/core/xmlgen/AndroidR.java
+1860
-0
BinaryXMLParser.java
...-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
+207
-161
No files found.
build.gradle
View file @
b55975a3
...
@@ -41,7 +41,6 @@ subprojects {
...
@@ -41,7 +41,6 @@ subprojects {
}
}
dependencies
{
dependencies
{
compile
'com.google.android:android:4.1.1.4'
compile
'org.slf4j:slf4j-api:1.7.7'
compile
'org.slf4j:slf4j-api:1.7.7'
testCompile
'ch.qos.logback:logback-classic:1.1.2'
testCompile
'ch.qos.logback:logback-classic:1.1.2'
...
...
jadx-cli/src/main/java/jadx/cli/JadxCLI.java
View file @
b55975a3
...
@@ -8,17 +8,10 @@ import java.io.File;
...
@@ -8,17 +8,10 @@ import java.io.File;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
//import jadx.core.xmlgen.BinaryXMLParser;
public
class
JadxCLI
{
public
class
JadxCLI
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
JadxCLI
.
class
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
JadxCLI
.
class
);
public
static
void
main
(
String
[]
args
)
throws
JadxException
{
public
static
void
main
(
String
[]
args
)
throws
JadxException
{
/*
BinaryXMLParser bxp = new BinaryXMLParser(args[0],args[1]);
bxp.parse();
System.exit(4);
*/
try
{
try
{
JadxCLIArgs
jadxArgs
=
new
JadxCLIArgs
();
JadxCLIArgs
jadxArgs
=
new
JadxCLIArgs
();
if
(
processArgs
(
jadxArgs
,
args
))
{
if
(
processArgs
(
jadxArgs
,
args
))
{
...
...
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
View file @
b55975a3
...
@@ -47,7 +47,7 @@ public final class JadxCLIArgs implements IJadxArgs {
...
@@ -47,7 +47,7 @@ public final class JadxCLIArgs implements IJadxArgs {
@Parameter
(
names
=
{
"-h"
,
"--help"
},
description
=
"print this help"
,
help
=
true
)
@Parameter
(
names
=
{
"-h"
,
"--help"
},
description
=
"print this help"
,
help
=
true
)
protected
boolean
printHelp
=
false
;
protected
boolean
printHelp
=
false
;
@Parameter
(
names
=
{
"-x"
,
"--xml"
},
description
=
"try to decode the AndroidManifest.xml
, save at current dir
"
)
@Parameter
(
names
=
{
"-x"
,
"--xml"
},
description
=
"try to decode the AndroidManifest.xml"
)
protected
boolean
xmlTest
=
false
;
protected
boolean
xmlTest
=
false
;
private
final
List
<
File
>
input
=
new
ArrayList
<
File
>(
1
);
private
final
List
<
File
>
input
=
new
ArrayList
<
File
>(
1
);
...
...
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
View file @
b55975a3
...
@@ -203,14 +203,17 @@ public final class JadxDecompiler {
...
@@ -203,14 +203,17 @@ public final class JadxDecompiler {
reset
();
reset
();
root
=
new
RootNode
();
root
=
new
RootNode
();
LOG
.
info
(
"loading ..."
);
LOG
.
info
(
"loading ..."
);
if
(
this
.
args
.
isXMLTest
())
{
if
(
this
.
args
.
isXMLTest
())
{
InputFile
inf
=
inputFiles
.
get
(
0
);
InputFile
inf
=
inputFiles
.
get
(
0
);
try
{
try
{
BinaryXMLParser
bxp
=
new
BinaryXMLParser
(
InputFile
.
loadXMLBuffer
(
inf
.
getFile
()),
"./AndroidManifest.xml"
);
byte
[]
buffer
=
InputFile
.
loadXMLBuffer
(
inf
.
getFile
());
//BinaryXMLParser bxp = new BinaryXMLParser(InputFile.loadXMLBuffer(inf.getFile()), "AndroidManifest.xml");
if
(
buffer
!=
null
)
{
bxp
.
parse
();
File
out
=
new
File
(
args
.
getOutDir
(),
"AndroidManifest.xml"
);
}
catch
(
IOException
ioe
)
{
BinaryXMLParser
bxp
=
new
BinaryXMLParser
();
LOG
.
info
(
"Decompiling AndroidManifest.xml failed!"
);
bxp
.
parse
(
buffer
,
out
);
}
}
catch
(
Exception
e
)
{
LOG
.
info
(
"Decompiling AndroidManifest.xml failed!"
,
e
);
}
}
}
}
root
.
load
(
inputFiles
);
root
.
load
(
inputFiles
);
...
...
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
View file @
b55975a3
...
@@ -77,7 +77,7 @@ public class InputFile {
...
@@ -77,7 +77,7 @@ public class InputFile {
public
static
byte
[]
loadXMLBuffer
(
File
file
)
throws
IOException
{
// FIXME: Public.. Please fix
public
static
byte
[]
loadXMLBuffer
(
File
file
)
throws
IOException
{
// FIXME: Public.. Please fix
ZipFile
zf
=
new
ZipFile
(
file
);
ZipFile
zf
=
new
ZipFile
(
file
);
ZipEntry
xml
=
zf
.
getEntry
(
"AndroidManifest.xml"
);
ZipEntry
xml
=
zf
.
getEntry
(
"AndroidManifest.xml"
);
if
(
null
==
xm
l
)
{
if
(
xml
==
nul
l
)
{
zf
.
close
();
zf
.
close
();
return
null
;
return
null
;
}
}
...
@@ -91,7 +91,9 @@ public class InputFile {
...
@@ -91,7 +91,9 @@ public class InputFile {
bytesOut
.
write
(
buffer
,
0
,
count
);
bytesOut
.
write
(
buffer
,
0
,
count
);
}
}
}
finally
{
}
finally
{
if
(
null
!=
in
)
in
.
close
();
if
(
null
!=
in
)
{
in
.
close
();
}
zf
.
close
();
zf
.
close
();
}
}
return
bytesOut
.
toByteArray
();
return
bytesOut
.
toByteArray
();
...
...
jadx-core/src/main/java/jadx/core/xmlgen/AndroidR.java
0 → 100644
View file @
b55975a3
This source diff could not be displayed because it is too large. You can
view the blob
instead.
jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
View file @
b55975a3
package
jadx
.
core
.
xmlgen
;
package
jadx
.
core
.
xmlgen
;
import
java.nio.ByteBuffer
;
import
jadx.core.codegen.CodeWriter
;
import
java.nio.charset.Charset
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.io.BufferedInputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileNotFoundException
;
import
java.io.InputStream
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.io.PrintWriter
;
import
java.io.File
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
java.nio.ByteBuffer
;
import
java.nio.charset.Charset
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
import
android.R.style
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/* TODO:
/* TODO:
Don't die when error occurs
Don't die when error occurs
Check error cases, maybe checked const values are not always the same
Check error cases, maybe checked const values are not always the same
Better error messages
Better error messages
What to do, when Binary XML Manifest is > size(int)?
What to do, when Binary XML Manifest is > size(int)?
Check for miss
u
ng chunk size types
Check for miss
i
ng chunk size types
Implement missing data types
Implement missing data types
Use linenumbers to recreate EXACT AndroidManifest
Use line
numbers to recreate EXACT AndroidManifest
Check Element chunk size
Check Element chunk size
*/
*/
public
class
BinaryXMLParser
{
public
class
BinaryXMLParser
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
BinaryXMLParser
.
class
);
private
byte
[]
bytes
;
private
byte
[]
bytes
;
private
String
[]
strings
;
private
String
[]
strings
;
private
int
count
;
private
int
count
;
private
String
nsPrefix
=
"ERROR"
;
private
String
nsURI
=
"ERROR"
;
private
String
nsPrefix
=
"ERROR"
;
private
String
currentTag
=
"ERROR"
;
private
String
nsURI
=
"ERROR"
;
private
int
numtabs
=-
1
;
private
String
currentTag
=
"ERROR"
;
private
boolean
wasOneLiner
=
false
;
private
PrintWriter
writer
;
private
boolean
firstElement
;
private
boolean
wasOneLiner
=
false
;
private
CodeWriter
writer
;
private
Map
<
Integer
,
String
>
styleMap
=
null
;
private
Map
<
Integer
,
String
>
styleMap
=
null
;
public
BinaryXMLParser
(
String
xmlfilepath
,
String
xmloutfilepath
)
{
public
BinaryXMLParser
()
{
try
{
writer
=
new
PrintWriter
(
xmloutfilepath
,
"UTF-8"
);
}
catch
(
FileNotFoundException
fnfe
)
{
die
(
"FNFE"
);
}
catch
(
UnsupportedEncodingException
uee
)
{
die
(
"UEE"
);
}
if
(
null
==
writer
)
die
(
"null==writer"
);
writer
.
println
(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
);
File
manifest
=
new
File
(
xmlfilepath
);
if
(
null
==
manifest
)
die
(
"null==manifest"
);
bytes
=
new
byte
[(
int
)
manifest
.
length
()];
try
{
InputStream
is
=
null
;
try
{
is
=
new
BufferedInputStream
(
new
FileInputStream
(
manifest
));
int
total
=
0
;
while
(
total
<
bytes
.
length
)
{
int
remain
=
bytes
.
length
-
total
;
int
read
=
is
.
read
(
bytes
,
total
,
remain
);
if
(
read
>
0
)
total
+=
read
;
}
}
finally
{
is
.
close
();
}
}
catch
(
FileNotFoundException
fnfe
)
{
die
(
"FILE NOT FOUND"
);
}
catch
(
IOException
ioe
)
{
die
(
"IOE"
);
}
count
=
0
;
styleMap
=
new
HashMap
<
Integer
,
String
>();
styleMap
=
new
HashMap
<
Integer
,
String
>();
if
(
null
==
styleMap
)
die
(
"null==styleMap"
);
try
{
for
(
Field
f
:
android
.
R
.
style
.
class
.
getFields
())
{
for
(
Field
f
:
AndroidR
.
style
.
class
.
getFields
())
{
try
{
styleMap
.
put
(
f
.
getInt
(
f
.
getType
()),
f
.
getName
());
styleMap
.
put
(
f
.
getInt
(
f
.
getType
()),
f
.
getName
());
}
catch
(
IllegalAccessException
iae
)
{
die
(
"IAE"
);
}
}
//TODO: also add application constant fields
}
catch
(
IllegalAccessException
e
)
{
throw
new
JadxRuntimeException
(
"BinaryXMLParser init error"
,
e
);
}
}
}
}
public
BinaryXMLParser
(
byte
[]
xmlfilebytes
,
String
xmloutfilepath
)
{
public
void
parse
(
byte
[]
xmlBytes
,
File
out
)
{
System
.
out
.
println
(
"XMLOUTFILEPATH: "
+
xmloutfilepath
);
LOG
.
debug
(
"Decoding AndroidManifest.xml, output: {}"
,
out
);
try
{
writer
=
new
PrintWriter
(
xmloutfilepath
,
"UTF-8"
);
writer
=
new
CodeWriter
();
}
catch
(
FileNotFoundException
fnfe
)
{
die
(
"FNFE"
);
}
writer
.
add
(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
);
catch
(
UnsupportedEncodingException
uee
)
{
die
(
"UEE"
);
}
bytes
=
xmlBytes
;
if
(
null
==
writer
)
die
(
"null==writer"
);
count
=
0
;
writer
.
println
(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
);
firstElement
=
true
;
bytes
=
xmlfilebytes
;
decode
();
count
=
0
;
writer
.
save
(
out
);
styleMap
=
new
HashMap
<
Integer
,
String
>();
if
(
null
==
styleMap
)
die
(
"null==styleMap"
);
for
(
Field
f
:
android
.
R
.
style
.
class
.
getFields
())
{
try
{
styleMap
.
put
(
f
.
getInt
(
f
.
getType
()),
f
.
getName
());
}
catch
(
IllegalAccessException
iae
)
{
die
(
"IAE"
);
}
}
}
}
public
void
parse
()
{
void
decode
()
{
if
(
cInt16
(
bytes
,
count
)
!=
0x0003
)
die
(
"Version is not 3"
);
if
(
cInt16
(
bytes
,
count
)
!=
0x0003
)
{
if
(
cInt16
(
bytes
,
count
)
!=
0x0008
)
die
(
"Size of header is not 8"
);
die
(
"Version is not 3"
);
if
(
cInt32
(
bytes
,
count
)
!=
bytes
.
length
)
die
(
"Size of manifest doesn't match"
);
}
while
((
count
+
2
)<=
bytes
.
length
)
{
if
(
cInt16
(
bytes
,
count
)
!=
0x0008
)
{
die
(
"Size of header is not 8"
);
}
if
(
cInt32
(
bytes
,
count
)
!=
bytes
.
length
)
{
die
(
"Size of manifest doesn't match"
);
}
while
((
count
+
2
)
<=
bytes
.
length
)
{
int
type
=
cInt16
(
bytes
,
count
);
int
type
=
cInt16
(
bytes
,
count
);
if
(
type
==
0x0001
)
parseStringPool
();
switch
(
type
)
{
else
if
(
type
==
0x0180
)
parseResourceMap
();
case
0x0001
:
else
if
(
type
==
0x0100
)
parseNameSpace
();
parseStringPool
();
else
if
(
type
==
0x0101
)
parseNameSpaceEnd
();
break
;
else
if
(
type
==
0x0102
)
parseElement
();
case
0x0180
:
else
if
(
type
==
0x0103
)
parseElementEnd
();
parseResourceMap
();
else
if
(
type
==
0x0000
)
continue
;
// NullType is just doing nothing
break
;
else
die
(
"Type: "
+
Integer
.
toHexString
(
type
)
+
" not yet implemented"
);
case
0x0100
:
parseNameSpace
();
break
;
case
0x0101
:
parseNameSpaceEnd
();
break
;
case
0x0102
:
parseElement
();
break
;
case
0x0103
:
parseElementEnd
();
break
;
case
0x0000
:
// NullType is just doing nothing
break
;
default
:
die
(
"Type: "
+
Integer
.
toHexString
(
type
)
+
" not yet implemented"
);
break
;
}
}
}
writer
.
close
();
}
}
private
void
parseStringPool
()
{
private
void
parseStringPool
()
{
if
(
cInt16
(
bytes
,
count
)
!=
0x001c
)
die
(
"Header header size not 28"
);
if
(
cInt16
(
bytes
,
count
)
!=
0x001c
)
{
die
(
"Header header size not 28"
);
}
int
hsize
=
cInt32
(
bytes
,
count
);
int
hsize
=
cInt32
(
bytes
,
count
);
int
stringCount
=
cInt32
(
bytes
,
count
);
int
stringCount
=
cInt32
(
bytes
,
count
);
int
styleCount
=
cInt32
(
bytes
,
count
);
int
styleCount
=
cInt32
(
bytes
,
count
);
...
@@ -126,161 +119,214 @@ public class BinaryXMLParser {
...
@@ -126,161 +119,214 @@ public class BinaryXMLParser {
int
stringsStart
=
cInt32
(
bytes
,
count
);
int
stringsStart
=
cInt32
(
bytes
,
count
);
int
stylesStart
=
cInt32
(
bytes
,
count
);
int
stylesStart
=
cInt32
(
bytes
,
count
);
int
[]
stringsOffsets
=
new
int
[
stringCount
];
int
[]
stringsOffsets
=
new
int
[
stringCount
];
for
(
int
i
=
0
;
i
<
stringCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
stringCount
;
i
++)
{
stringsOffsets
[
i
]
=
cInt32
(
bytes
,
count
);
stringsOffsets
[
i
]
=
cInt32
(
bytes
,
count
);
}
}
strings
=
new
String
[
stringCount
];
strings
=
new
String
[
stringCount
];
for
(
int
i
=
0
;
i
<
stringCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
stringCount
;
i
++)
{
int
off
=
8
+
stringsStart
+
stringsOffsets
[
i
];
int
off
=
8
+
stringsStart
+
stringsOffsets
[
i
];
int
strlen
=
cInt16
(
bytes
,
off
);
int
strlen
=
cInt16
(
bytes
,
off
);
byte
[]
str
=
new
byte
[
strlen
*
2
];
byte
[]
str
=
new
byte
[
strlen
*
2
];
System
.
arraycopy
(
bytes
,
count
,
str
,
0
,
strlen
*
2
);
System
.
arraycopy
(
bytes
,
count
,
str
,
0
,
strlen
*
2
);
count
+=
strlen
*
2
;
count
+=
strlen
*
2
;
strings
[
i
]
=
new
String
(
str
,
Charset
.
forName
(
"UTF-16LE"
));
strings
[
i
]
=
new
String
(
str
,
Charset
.
forName
(
"UTF-16LE"
));
count
+=
2
;
count
+=
2
;
}
}
}
}
private
void
parseResourceMap
()
{
private
void
parseResourceMap
()
{
if
(
cInt16
(
bytes
,
count
)
!=
0x8
)
die
(
"Header size of resmap is not 8!"
);
if
(
cInt16
(
bytes
,
count
)
!=
0x8
)
{
die
(
"Header size of resmap is not 8!"
);
}
int
rhsize
=
cInt32
(
bytes
,
count
);
int
rhsize
=
cInt32
(
bytes
,
count
);
int
[]
ids
=
new
int
[(
rhsize
-
8
)/
4
];
int
[]
ids
=
new
int
[(
rhsize
-
8
)
/
4
];
for
(
int
i
=
0
;
i
<
ids
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
ids
.
length
;
i
++)
{
ids
[
i
]
=
cInt32
(
bytes
,
count
);
ids
[
i
]
=
cInt32
(
bytes
,
count
);
}
}
}
}
private
void
parseNameSpace
()
{
private
void
parseNameSpace
()
{
if
(
cInt16
(
bytes
,
count
)
!=
0x0010
)
die
(
"NAMESPACE header is not 0x0010"
);
if
(
cInt16
(
bytes
,
count
)
!=
0x0010
)
{
if
(
cInt32
(
bytes
,
count
)
!=
0x18
)
die
(
"NAMESPACE header chunk is not 0x18 big"
);
die
(
"NAMESPACE header is not 0x0010"
);
}
if
(
cInt32
(
bytes
,
count
)
!=
0x18
)
{
die
(
"NAMESPACE header chunk is not 0x18 big"
);
}
int
beginLineNumber
=
cInt32
(
bytes
,
count
);
int
beginLineNumber
=
cInt32
(
bytes
,
count
);
int
comment
=
cInt32
(
bytes
,
count
);
int
comment
=
cInt32
(
bytes
,
count
);
int
beginPrefix
=
cInt32
(
bytes
,
count
);
int
beginPrefix
=
cInt32
(
bytes
,
count
);
nsPrefix
=
strings
[
beginPrefix
];
nsPrefix
=
strings
[
beginPrefix
];
int
beginURI
=
cInt32
(
bytes
,
count
);
int
beginURI
=
cInt32
(
bytes
,
count
);
nsURI
=
strings
[
beginURI
];
nsURI
=
strings
[
beginURI
];
}
}
private
void
parseNameSpaceEnd
()
{
private
void
parseNameSpaceEnd
()
{
if
(
cInt16
(
bytes
,
count
)
!=
0x0010
)
die
(
"NAMESPACE header is not 0x0010"
);
if
(
cInt16
(
bytes
,
count
)
!=
0x0010
)
{
if
(
cInt32
(
bytes
,
count
)
!=
0x18
)
die
(
"NAMESPACE header chunk is not 0x18 big"
);
die
(
"NAMESPACE header is not 0x0010"
);
}
if
(
cInt32
(
bytes
,
count
)
!=
0x18
)
{
die
(
"NAMESPACE header chunk is not 0x18 big"
);
}
int
endLineNumber
=
cInt32
(
bytes
,
count
);
int
endLineNumber
=
cInt32
(
bytes
,
count
);
int
comment
=
cInt32
(
bytes
,
count
);
int
comment
=
cInt32
(
bytes
,
count
);
int
endPrefix
=
cInt32
(
bytes
,
count
);
int
endPrefix
=
cInt32
(
bytes
,
count
);
nsPrefix
=
strings
[
endPrefix
];
nsPrefix
=
strings
[
endPrefix
];
int
endURI
=
cInt32
(
bytes
,
count
);
int
endURI
=
cInt32
(
bytes
,
count
);
nsURI
=
strings
[
endURI
];
nsURI
=
strings
[
endURI
];
}
}
private
void
parseElement
()
{
private
void
parseElement
()
{
numtabs
+=
1
;
if
(
firstElement
)
{
if
(
cInt16
(
bytes
,
count
)
!=
0x0010
)
die
(
"ELEMENT HEADER SIZE is not 0x10"
);
firstElement
=
false
;
count
+=
4
;
// TODO: Check element chunk size
}
else
{
writer
.
incIndent
();
}
if
(
cInt16
(
bytes
,
count
)
!=
0x0010
)
{
die
(
"ELEMENT HEADER SIZE is not 0x10"
);
}
count
+=
4
;
// TODO: Check element chunk size
int
elementBegLineNumber
=
cInt32
(
bytes
,
count
);
int
elementBegLineNumber
=
cInt32
(
bytes
,
count
);
int
comment
=
cInt32
(
bytes
,
count
);
int
comment
=
cInt32
(
bytes
,
count
);
int
startNS
=
cInt32
(
bytes
,
count
);
int
startNS
=
cInt32
(
bytes
,
count
);
int
startNSName
=
cInt32
(
bytes
,
count
);
// actually is elementName...
int
startNSName
=
cInt32
(
bytes
,
count
);
// actually is elementName...
if
(!
wasOneLiner
&&
!
"ERROR"
.
equals
(
currentTag
)
&&
!
currentTag
.
equals
(
strings
[
startNSName
]))
{
if
(!
wasOneLiner
&&
!
"ERROR"
.
equals
(
currentTag
)
&&
!
currentTag
.
equals
(
strings
[
startNSName
]))
{
writer
.
println
(
">"
);
writer
.
add
(
">"
);
}
}
wasOneLiner
=
false
;
wasOneLiner
=
false
;
currentTag
=
strings
[
startNSName
];
currentTag
=
strings
[
startNSName
];
for
(
int
i
=
0
;
i
<
numtabs
;
i
++)
writer
.
print
(
"\t"
);
writer
.
startLine
(
"<"
+
strings
[
startNSName
]);
writer
.
print
(
"<"
+
strings
[
startNSName
]);
int
attributeStart
=
cInt16
(
bytes
,
count
);
int
attributeStart
=
cInt16
(
bytes
,
count
);
if
(
attributeStart
!=
0x14
)
die
(
"startNS's attributeStart is not 0x14"
);
if
(
attributeStart
!=
0x14
)
{
die
(
"startNS's attributeStart is not 0x14"
);
}
int
attributeSize
=
cInt16
(
bytes
,
count
);
int
attributeSize
=
cInt16
(
bytes
,
count
);
if
(
attributeSize
!=
0x14
)
die
(
"startNS's attributeSize is not 0x14"
);
if
(
attributeSize
!=
0x14
)
{
int
attributeCount
=
cInt16
(
bytes
,
count
);
die
(
"startNS's attributeSize is not 0x14"
);
}
int
attributeCount
=
cInt16
(
bytes
,
count
);
int
idIndex
=
cInt16
(
bytes
,
count
);
int
idIndex
=
cInt16
(
bytes
,
count
);
int
classIndex
=
cInt16
(
bytes
,
count
);
int
classIndex
=
cInt16
(
bytes
,
count
);
int
styleIndex
=
cInt16
(
bytes
,
count
);
int
styleIndex
=
cInt16
(
bytes
,
count
);
if
(
"manifest"
.
equals
(
strings
[
startNSName
]))
writer
.
print
(
" xmlns:\""
+
nsURI
+
"\""
);
if
(
"manifest"
.
equals
(
strings
[
startNSName
]))
{
if
(
attributeCount
>
0
)
writer
.
print
(
" "
);
writer
.
add
(
" xmlns:\""
+
nsURI
+
"\""
);
for
(
int
i
=
0
;
i
<
attributeCount
;
i
++)
{
}
if
(
attributeCount
>
0
)
{
writer
.
add
(
" "
);
}
for
(
int
i
=
0
;
i
<
attributeCount
;
i
++)
{
int
attributeNS
=
cInt32
(
bytes
,
count
);
int
attributeNS
=
cInt32
(
bytes
,
count
);
int
attributeName
=
cInt32
(
bytes
,
count
);
int
attributeName
=
cInt32
(
bytes
,
count
);
int
attributeRawValue
=
cInt32
(
bytes
,
count
);
int
attributeRawValue
=
cInt32
(
bytes
,
count
);
int
attrValSize
=
cInt16
(
bytes
,
count
);
int
attrValSize
=
cInt16
(
bytes
,
count
);
if
(
attrValSize
!=
0x08
)
die
(
"attrValSize != 0x08 not supported"
);
if
(
attrValSize
!=
0x08
)
{
if
(
cInt8
(
bytes
,
count
)
!=
0
)
die
(
"res0 is not 0"
);
die
(
"attrValSize != 0x08 not supported"
);
}
if
(
cInt8
(
bytes
,
count
)
!=
0
)
{
die
(
"res0 is not 0"
);
}
int
attrValDataType
=
cInt8
(
bytes
,
count
);
int
attrValDataType
=
cInt8
(
bytes
,
count
);
int
attrValData
=
cInt32
(
bytes
,
count
);
int
attrValData
=
cInt32
(
bytes
,
count
);
if
(
attributeNS
!=
-
1
)
writer
.
print
(
nsPrefix
+
":"
);
if
(
attributeNS
!=
-
1
)
{
writer
.
print
(
strings
[
attributeName
]
+
"=\""
);
writer
.
add
(
nsPrefix
+
":"
);
if
(
attrValDataType
==
0x3
)
writer
.
print
(
strings
[
attrValData
]);
}
else
if
(
attrValDataType
==
0x10
)
writer
.
print
(
attrValData
);
writer
.
add
(
strings
[
attributeName
]
+
"=\""
);
else
if
(
attrValDataType
==
0x12
)
{
if
(
attrValDataType
==
0x3
)
{
writer
.
add
(
strings
[
attrValData
]);
}
else
if
(
attrValDataType
==
0x10
)
{
writer
.
add
(
String
.
valueOf
(
attrValData
));
}
else
if
(
attrValDataType
==
0x12
)
{
// FIXME: What to do, when data is always -1?
// FIXME: What to do, when data is always -1?
if
(
attrValData
==
0
)
writer
.
print
(
"false"
);
if
(
attrValData
==
0
)
{
else
if
(
attrValData
==
1
||
attrValData
==-
1
)
writer
.
print
(
"true"
);
writer
.
add
(
"false"
);
else
writer
.
print
(
"UNKNOWN_BOOLEAN_TYPE"
);
}
else
if
(
attrValData
==
1
||
attrValData
==
-
1
)
{
}
else
if
(
attrValDataType
==
0x1
)
{
writer
.
add
(
"true"
);
if
(
attrValData
<
0x7f000000
)
{
writer
.
print
(
"@*"
);
if
(
attributeNS
!=
-
1
)
writer
.
print
(
nsPrefix
+
":"
);
writer
.
print
(
"style/"
+
styleMap
.
get
(
attrValData
).
replaceAll
(
"_"
,
"."
));
}
else
{
}
else
{
writer
.
print
(
"0x"
+
Integer
.
toHexString
(
attrValData
)
);
writer
.
add
(
"UNKNOWN_BOOLEAN_TYPE"
);
}
}
}
}
else
if
(
attrValDataType
==
0x1
)
{
else
{
String
name
=
styleMap
.
get
(
attrValData
);
if
(
"configChanges"
.
equals
(
strings
[
attributeName
]))
{
if
(
name
!=
null
)
{
if
(
attrValData
==
1152
)
writer
.
print
(
"orientation"
);
writer
.
add
(
"@*"
);
else
if
(
attrValData
==
4016
)
writer
.
print
(
"keyboard|keyboardHidden|orientation|screenLayout|uiMode"
);
if
(
attributeNS
!=
-
1
)
{
else
if
(
attrValData
==
176
)
writer
.
print
(
"keyboard|keyboardHidden|orientation"
);
writer
.
add
(
nsPrefix
+
":"
);
else
if
(
attrValData
==
160
)
writer
.
print
(
"keyboardHidden|orientation"
);
}
else
writer
.
print
(
"UNKNOWN_DATA_"
+
Integer
.
toHexString
(
attrValData
));
writer
.
add
(
"style/"
+
name
.
replaceAll
(
"_"
,
"."
));
}
else
{
writer
.
add
(
"0x"
+
Integer
.
toHexString
(
attrValData
));
}
}
else
{
// TODO: extract values names from here:
// https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/attrs_manifest.xml
if
(
"configChanges"
.
equals
(
strings
[
attributeName
]))
{
if
(
attrValData
==
1152
)
{
writer
.
add
(
"orientation"
);
}
else
if
(
attrValData
==
4016
)
{
writer
.
add
(
"keyboard|keyboardHidden|orientation|screenLayout|uiMode"
);
}
else
if
(
attrValData
==
176
)
{
writer
.
add
(
"keyboard|keyboardHidden|orientation"
);
}
else
if
(
attrValData
==
160
)
{
writer
.
add
(
"keyboardHidden|orientation"
);
}
else
{
writer
.
add
(
"UNKNOWN_DATA_"
+
Integer
.
toHexString
(
attrValData
));
}
}
else
{
}
else
{
writer
.
print
(
"UNKNOWN_DATA_TYPE_"
+
attrValDataType
);
writer
.
add
(
"UNKNOWN_DATA_TYPE_"
+
attrValDataType
);
}
}
}
}
writer
.
print
(
"\""
);
writer
.
add
(
"\""
);
if
((
i
+
1
)<
attributeCount
)
writer
.
print
(
" "
);
if
((
i
+
1
)
<
attributeCount
)
{
writer
.
add
(
" "
);
}
}
}
}
}
private
void
parseElementEnd
()
{
private
void
parseElementEnd
()
{
if
(
cInt16
(
bytes
,
count
)
!=
0x0010
)
die
(
"ELEMENT END header is not 0x0010"
);
if
(
cInt16
(
bytes
,
count
)
!=
0x0010
)
{
if
(
cInt32
(
bytes
,
count
)
!=
0x18
)
die
(
"ELEMENT END header chunk is not 0x18 big"
);
die
(
"ELEMENT END header is not 0x0010"
);
}
if
(
cInt32
(
bytes
,
count
)
!=
0x18
)
{
die
(
"ELEMENT END header chunk is not 0x18 big"
);
}
int
endLineNumber
=
cInt32
(
bytes
,
count
);
int
endLineNumber
=
cInt32
(
bytes
,
count
);
int
comment
=
cInt32
(
bytes
,
count
);
int
comment
=
cInt32
(
bytes
,
count
);
int
elementNS
=
cInt32
(
bytes
,
count
);
int
elementNS
=
cInt32
(
bytes
,
count
);
int
elementName
=
cInt32
(
bytes
,
count
);
int
elementName
=
cInt32
(
bytes
,
count
);
if
(
currentTag
==
strings
[
elementName
]
)
{
if
(
currentTag
.
equals
(
strings
[
elementName
])
)
{
writer
.
println
(
"
/>"
);
writer
.
add
(
"
/>"
);
wasOneLiner
=
true
;
wasOneLiner
=
true
;
}
else
{
}
else
{
for
(
int
i
=
0
;
i
<
numtabs
;
i
++)
writer
.
print
(
"\t"
);
writer
.
startLine
(
"</"
);
writer
.
print
(
"</"
);
if
(
elementNS
!=
-
1
)
{
if
(
elementNS
!=
-
1
)
writer
.
print
(
strings
[
elementNS
]+
":"
);
writer
.
add
(
strings
[
elementNS
]
+
":"
);
writer
.
println
(
strings
[
elementName
]+
">"
);
}
writer
.
add
(
strings
[
elementName
]
+
">"
);
}
}
numtabs
-=
1
;
writer
.
decIndent
()
;
}
}
private
int
cInt8
(
byte
[]
bytes
,
int
offset
)
{
private
int
cInt8
(
byte
[]
bytes
,
int
offset
)
{
byte
[]
tmp
=
new
byte
[
4
];
byte
[]
tmp
=
new
byte
[
4
];
tmp
[
3
]
=
bytes
[
count
++];
tmp
[
3
]
=
bytes
[
count
++];
return
ByteBuffer
.
wrap
(
tmp
).
getInt
();
return
ByteBuffer
.
wrap
(
tmp
).
getInt
();
}
}
private
int
cInt16
(
byte
[]
bytes
,
int
offset
)
{
private
int
cInt16
(
byte
[]
bytes
,
int
offset
)
{
byte
[]
tmp
=
new
byte
[
4
];
byte
[]
tmp
=
new
byte
[
4
];
tmp
[
3
]
=
bytes
[
count
++];
tmp
[
3
]
=
bytes
[
count
++];
tmp
[
2
]
=
bytes
[
count
++];
tmp
[
2
]
=
bytes
[
count
++];
return
ByteBuffer
.
wrap
(
tmp
).
getInt
();
return
ByteBuffer
.
wrap
(
tmp
).
getInt
();
}
}
private
int
cInt32
(
byte
[]
bytes
,
int
offset
)
{
private
int
cInt32
(
byte
[]
bytes
,
int
offset
)
{
byte
[]
tmp
=
new
byte
[
4
];
byte
[]
tmp
=
new
byte
[
4
];
for
(
int
i
=
0
;
i
<
4
;
i
++)
tmp
[
3
-
i
]=
bytes
[
count
+
i
];
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
count
+=
4
;
tmp
[
3
-
i
]
=
bytes
[
count
+
i
];
}
count
+=
4
;
return
ByteBuffer
.
wrap
(
tmp
).
getInt
();
return
ByteBuffer
.
wrap
(
tmp
).
getInt
();
}
}
private
void
die
(
String
message
)
{
private
void
die
(
String
message
)
{
System
.
err
.
println
(
message
);
throw
new
JadxRuntimeException
(
"Decode error: "
+
message
);
System
.
exit
(
3
);
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment