Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
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
650cf315
Commit
650cf315
authored
Mar 22, 2019
by
tRuNKator
Committed by
skylot
Mar 22, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: resource qualifiers (PR #487)
parent
42b78437
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
772 additions
and
256 deletions
+772
-256
ParserStream.java
jadx-core/src/main/java/jadx/core/xmlgen/ParserStream.java
+18
-0
ResTableParser.java
jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java
+106
-98
ResXmlGen.java
jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java
+3
-3
EntryConfig.java
...ore/src/main/java/jadx/core/xmlgen/entry/EntryConfig.java
+645
-155
No files found.
jadx-core/src/main/java/jadx/core/xmlgen/ParserStream.java
View file @
650cf315
package
jadx
.
core
.
xmlgen
;
import
java.io.EOFException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.nio.charset.Charset
;
...
...
@@ -143,6 +144,23 @@ public class ParserStream {
input
.
reset
();
}
public
void
readFully
(
byte
[]
b
)
throws
IOException
{
readFully
(
b
,
0
,
b
.
length
);
}
public
void
readFully
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
readPos
+=
len
;
if
(
len
<
0
)
throw
new
IndexOutOfBoundsException
();
int
n
=
0
;
while
(
n
<
len
)
{
int
count
=
input
.
read
(
b
,
off
+
n
,
len
-
n
);
if
(
count
<
0
)
throw
new
EOFException
();
n
+=
count
;
}
}
@Override
public
String
toString
()
{
return
"pos: 0x"
+
Long
.
toHexString
(
readPos
);
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java
View file @
650cf315
...
...
@@ -2,6 +2,7 @@ package jadx.core.xmlgen;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.math.BigInteger
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
...
...
@@ -21,6 +22,8 @@ public class ResTableParser extends CommonBinaryParser {
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ResTableParser
.
class
);
private
static
final
int
KNOWN_CONFIG_BYTES
=
56
;
private
static
final
class
PackageChunk
{
private
final
int
id
;
private
final
String
name
;
...
...
@@ -194,6 +197,11 @@ public class ResTableParser extends CommonBinaryParser {
EntryConfig
config
=
parseConfig
();
if
(
config
.
isInvalid
)
{
String
typeName
=
pkg
.
getTypeStrings
()[
id
-
1
];
LOG
.
warn
(
"Invalid config flags detected: "
+
typeName
+
config
.
getQualifiers
());
}
int
[]
entryIndexes
=
new
int
[
entryCount
];
for
(
int
i
=
0
;
i
<
entryCount
;
i
++)
{
entryIndexes
[
i
]
=
is
.
readInt32
();
...
...
@@ -248,134 +256,134 @@ public class ResTableParser extends CommonBinaryParser {
}
private
EntryConfig
parseConfig
()
throws
IOException
{
long
start
=
is
.
getPos
();
int
size
=
is
.
readInt32
();
int
read
=
28
;
EntryConfig
config
=
new
EntryConfig
();
is
.
readInt16
();
//mcc
is
.
readInt16
();
//mnc
if
(
size
<
28
)
{
throw
new
IOException
(
"Config size < 28"
);
}
config
.
setLanguage
(
parseLocale
());
config
.
setCountry
(
parseLocale
());
boolean
isInvalid
=
false
;
int
orientation
=
is
.
readInt8
();
int
touchscreen
=
is
.
readInt8
();
int
density
=
is
.
readInt16
();
short
mcc
=
(
short
)
is
.
readInt16
();
short
mnc
=
(
short
)
is
.
readInt16
();
if
(
density
!=
0
)
{
config
.
setDensity
(
parseDensity
(
density
));
}
char
[]
language
=
unpackLocaleOrRegion
((
byte
)
is
.
readInt8
(),
(
byte
)
is
.
readInt8
(),
'a'
);
char
[]
country
=
unpackLocaleOrRegion
((
byte
)
is
.
readInt8
(),
(
byte
)
is
.
readInt8
(),
'0'
);
is
.
readInt8
();
// keyboard
is
.
readInt8
();
// navigation
is
.
readInt8
();
// inputFlags
is
.
readInt8
();
// inputPad0
byte
orientation
=
(
byte
)
is
.
readInt8
();
byte
touchscreen
=
(
byte
)
is
.
readInt8
();
int
screenWidth
=
is
.
readInt16
();
int
screenHeight
=
is
.
readInt16
();
int
density
=
is
.
readInt16
();
if
(
screenWidth
!=
0
&&
screenHeight
!=
0
)
{
config
.
setScreenSize
(
screenWidth
+
"x"
+
screenHeight
);
byte
keyboard
=
(
byte
)
is
.
readInt8
();
byte
navigation
=
(
byte
)
is
.
readInt8
();
byte
inputFlags
=
(
byte
)
is
.
readInt8
();
/* inputPad0 */
is
.
readInt8
();
short
screenWidth
=
(
short
)
is
.
readInt16
();
short
screenHeight
=
(
short
)
is
.
readInt16
();
short
sdkVersion
=
(
short
)
is
.
readInt16
();
/* minorVersion, now must always be 0 */
is
.
readInt16
();
byte
screenLayout
=
0
;
byte
uiMode
=
0
;
short
smallestScreenWidthDp
=
0
;
if
(
size
>=
32
)
{
screenLayout
=
(
byte
)
is
.
readInt8
();
uiMode
=
(
byte
)
is
.
readInt8
();
smallestScreenWidthDp
=
(
short
)
is
.
readInt16
();
read
=
32
;
}
int
sdkVersion
=
is
.
readInt16
();
if
(
sdkVersion
!=
0
)
{
config
.
setSdkVersion
(
"v"
+
sdkVersion
);
short
screenWidthDp
=
0
;
short
screenHeightDp
=
0
;
if
(
size
>=
36
)
{
screenWidthDp
=
(
short
)
is
.
readInt16
();
screenHeightDp
=
(
short
)
is
.
readInt16
();
read
=
36
;
}
int
minorVersion
=
is
.
readInt16
();
int
screenLayout
=
is
.
readInt8
();
int
uiMode
=
is
.
readInt8
();
int
smallestScreenWidthDp
=
is
.
readInt16
();
int
screenWidthDp
=
is
.
readInt16
();
int
screenHeightDp
=
is
.
readInt16
();
if
(
screenLayout
!=
0
)
{
config
.
setScreenLayout
(
parseScreenLayout
(
screenLayout
));
char
[]
localeScript
=
null
;
char
[]
localeVariant
=
null
;
if
(
size
>=
48
)
{
localeScript
=
readScriptOrVariantChar
(
4
).
toCharArray
();
localeVariant
=
readScriptOrVariantChar
(
8
).
toCharArray
();
read
=
48
;
}
if
(
smallestScreenWidthDp
!=
0
)
{
config
.
setSmallestScreenWidthDp
(
"sw"
+
smallestScreenWidthDp
+
"dp"
);
byte
screenLayout2
=
0
;
byte
colorMode
=
0
;
if
(
size
>=
52
)
{
screenLayout2
=
(
byte
)
is
.
readInt8
();
colorMode
=
(
byte
)
is
.
readInt8
();
is
.
readInt16
();
// reserved padding
read
=
52
;
}
if
(
orientation
!=
0
)
{
config
.
setOrientation
(
parseOrientation
(
orientation
));
if
(
size
>=
56
)
{
is
.
readInt32
();
read
=
56
;
}
if
(
screenWidthDp
!=
0
)
{
config
.
setScreenWidthDp
(
"w"
+
screenWidthDp
+
"dp"
);
int
exceedingSize
=
size
-
KNOWN_CONFIG_BYTES
;
if
(
exceedingSize
>
0
)
{
byte
[]
buf
=
new
byte
[
exceedingSize
];
read
+=
exceedingSize
;
is
.
readFully
(
buf
);
BigInteger
exceedingBI
=
new
BigInteger
(
1
,
buf
);
if
(
exceedingBI
.
equals
(
BigInteger
.
ZERO
))
{
LOG
.
info
(
String
.
format
(
"Config flags size > %d, but exceeding bytes are all zero, so it should be ok."
,
KNOWN_CONFIG_BYTES
));
}
else
{
LOG
.
warn
(
String
.
format
(
"Config flags size > %d. Size = %d. Exceeding bytes: 0x%X."
,
KNOWN_CONFIG_BYTES
,
size
,
exceedingBI
));
isInvalid
=
true
;
}
}
if
(
screenHeightDp
!=
0
)
{
config
.
setScreenHeightDp
(
"h"
+
screenHeightDp
+
"dp"
);
int
remainingSize
=
size
-
read
;
if
(
remainingSize
>
0
)
{
is
.
skip
(
remainingSize
);
}
is
.
skipToPos
(
start
+
size
,
"Skip config parsing"
);
return
config
;
return
new
EntryConfig
(
mcc
,
mnc
,
language
,
country
,
orientation
,
touchscreen
,
density
,
keyboard
,
navigation
,
inputFlags
,
screenWidth
,
screenHeight
,
sdkVersion
,
screenLayout
,
uiMode
,
smallestScreenWidthDp
,
screenWidthDp
,
screenHeightDp
,
localeScript
,
localeVariant
,
screenLayout2
,
colorMode
,
isInvalid
,
size
);
}
private
String
parseOrientation
(
int
orientation
)
{
if
(
orientation
==
1
)
{
return
"port"
;
}
else
if
(
orientation
==
2
)
{
return
"land"
;
}
else
{
return
"o"
+
orientation
;
}
}
private
char
[]
unpackLocaleOrRegion
(
byte
in0
,
byte
in1
,
char
base
)
throws
IOException
{
// check high bit, if so we have a packed 3 letter code
if
(((
in0
>>
7
)
&
1
)
==
1
)
{
int
first
=
in1
&
0x1F
;
int
second
=
((
in1
&
0xE0
)
>>
5
)
+
((
in0
&
0x03
)
<<
3
);
int
third
=
(
in0
&
0x7C
)
>>
2
;
private
String
parseScreenLayout
(
int
screenLayout
)
{
switch
(
screenLayout
)
{
case
1
:
return
"small"
;
case
2
:
return
"normal"
;
case
3
:
return
"large"
;
case
4
:
return
"xlarge"
;
case
64
:
return
"ldltr"
;
case
128
:
return
"ldrtl"
;
default
:
return
"sl"
+
screenLayout
;
// since this function handles languages & regions, we add the value(s) to the base char
// which is usually 'a' or '0' depending on language or region.
return
new
char
[]
{
(
char
)
(
first
+
base
),
(
char
)
(
second
+
base
),
(
char
)
(
third
+
base
)
};
}
return
new
char
[]
{
(
char
)
in0
,
(
char
)
in1
};
}
private
String
parseDensity
(
int
density
)
{
if
(
density
==
120
)
{
return
"ldpi"
;
}
else
if
(
density
==
160
)
{
return
"mdpi"
;
}
else
if
(
density
==
240
)
{
return
"hdpi"
;
}
else
if
(
density
==
320
)
{
return
"xhdpi"
;
}
else
if
(
density
==
480
)
{
return
"xxhdpi"
;
}
else
if
(
density
==
640
)
{
return
"xxxhdpi"
;
}
else
{
return
density
+
"dpi"
;
}
}
private
String
readScriptOrVariantChar
(
int
length
)
throws
IOException
{
StringBuilder
string
=
new
StringBuilder
(
16
);
private
String
parseLocale
()
throws
IOException
{
int
b1
=
is
.
readInt8
();
int
b2
=
is
.
readInt8
();
String
str
=
null
;
if
(
b1
!=
0
&&
b2
!=
0
)
{
if
((
b1
&
0x80
)
==
0
)
{
str
=
new
String
(
new
char
[]{(
char
)
b1
,
(
char
)
b2
});
}
else
{
LOG
.
warn
(
"TODO: parse locale: 0x{}{}"
,
Integer
.
toHexString
(
b1
),
Integer
.
toHexString
(
b2
));
while
(
length
--
!=
0
)
{
short
ch
=
(
short
)
is
.
readInt8
();
if
(
ch
==
0
)
{
break
;
}
string
.
append
((
char
)
ch
);
}
return
str
;
is
.
skip
(
length
);
return
string
.
toString
();
}
}
jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java
View file @
650cf315
...
...
@@ -202,10 +202,10 @@ public class ResXmlGen {
private
String
getFileName
(
ResourceEntry
ri
)
{
StringBuilder
sb
=
new
StringBuilder
();
String
locale
=
ri
.
getConfig
().
getLocale
();
String
qualifiers
=
ri
.
getConfig
().
getQualifiers
();
sb
.
append
(
"res/values"
);
if
(!
locale
.
isEmpty
())
{
sb
.
append
(
'-'
).
append
(
locale
);
if
(!
qualifiers
.
isEmpty
())
{
sb
.
append
(
qualifiers
);
}
sb
.
append
(
'/'
);
sb
.
append
(
ri
.
getTypeName
());
...
...
jadx-core/src/main/java/jadx/core/xmlgen/entry/EntryConfig.java
View file @
650cf315
This diff is collapsed.
Click to expand it.
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