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
f02b99a1
Commit
f02b99a1
authored
Jan 06, 2018
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix some sonar warnings
parent
9132ef57
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
512 additions
and
611 deletions
+512
-611
ResourcesLoader.java
jadx-core/src/main/java/jadx/api/ResourcesLoader.java
+36
-59
Consts.java
jadx-core/src/main/java/jadx/core/Consts.java
+3
-0
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+14
-24
ConstStorage.java
jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
+8
-8
DebugInfoParser.java
...main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java
+4
-8
EncValueParser.java
.../main/java/jadx/core/dex/nodes/parser/EncValueParser.java
+8
-6
SaveCode.java
jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java
+5
-18
ErrorsCounter.java
jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java
+7
-8
Utils.java
jadx-core/src/main/java/jadx/core/utils/Utils.java
+2
-6
AndroidResourcesUtils.java
...n/java/jadx/core/utils/android/AndroidResourcesUtils.java
+9
-6
DataInputDelegate.java
.../main/java/jadx/core/utils/android/DataInputDelegate.java
+64
-64
ExtDataInput.java
...e/src/main/java/jadx/core/utils/android/ExtDataInput.java
+98
-101
Res9patchStreamDecoder.java
.../java/jadx/core/utils/android/Res9patchStreamDecoder.java
+119
-118
FileUtils.java
jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
+4
-13
InputFile.java
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
+34
-48
JavaToDex.java
jadx-core/src/main/java/jadx/core/utils/files/JavaToDex.java
+1
-4
ZipSecurity.java
...core/src/main/java/jadx/core/utils/files/ZipSecurity.java
+20
-20
BinaryXMLParser.java
...-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
+32
-28
ManifestAttributes.java
...re/src/main/java/jadx/core/xmlgen/ManifestAttributes.java
+1
-1
ResContainer.java
jadx-core/src/main/java/jadx/core/xmlgen/ResContainer.java
+13
-10
ResourceStorage.java
...-core/src/main/java/jadx/core/xmlgen/ResourceStorage.java
+4
-12
XmlSecurity.java
jadx-core/src/main/java/jadx/core/xmlgen/XmlSecurity.java
+11
-10
ValuesParser.java
...re/src/main/java/jadx/core/xmlgen/entry/ValuesParser.java
+11
-7
JRoot.java
jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java
+0
-8
CommonSearchDialog.java
jadx-gui/src/main/java/jadx/gui/ui/CommonSearchDialog.java
+4
-24
No files found.
jadx-core/src/main/java/jadx/api/ResourcesLoader.java
View file @
f02b99a1
package
jadx
.
api
;
package
jadx
.
api
;
import
jadx.api.ResourceFile.ZipRef
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.files.InputFile
;
import
jadx.core.utils.files.ZipSecurity
;
import
jadx.core.xmlgen.ResContainer
;
import
jadx.core.xmlgen.ResTableParser
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.File
;
import
java.io.File
;
...
@@ -24,8 +15,16 @@ import java.util.zip.ZipFile;
...
@@ -24,8 +15,16 @@ import java.util.zip.ZipFile;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.ResourceFile.ZipRef
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.files.InputFile
;
import
jadx.core.utils.files.ZipSecurity
;
import
jadx.core.xmlgen.ResContainer
;
import
jadx.core.xmlgen.ResTableParser
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
READ_BUFFER_SIZE
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
READ_BUFFER_SIZE
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
close
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
copyStream
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
copyStream
;
// TODO: move to core package
// TODO: move to core package
...
@@ -53,44 +52,30 @@ public final class ResourcesLoader {
...
@@ -53,44 +52,30 @@ public final class ResourcesLoader {
}
}
public
static
ResContainer
decodeStream
(
ResourceFile
rf
,
ResourceDecoder
decoder
)
throws
JadxException
{
public
static
ResContainer
decodeStream
(
ResourceFile
rf
,
ResourceDecoder
decoder
)
throws
JadxException
{
ZipFile
zipFile
=
null
;
InputStream
inputStream
=
null
;
ResContainer
result
;
try
{
try
{
long
size
;
ZipRef
zipRef
=
rf
.
getZipRef
();
ZipRef
zipRef
=
rf
.
getZipRef
();
if
(
zipRef
==
null
)
{
if
(
zipRef
==
null
)
{
File
file
=
new
File
(
rf
.
getName
());
File
file
=
new
File
(
rf
.
getName
());
inputStream
=
new
BufferedInputStream
(
new
FileInputStream
(
file
));
try
(
InputStream
inputStream
=
new
BufferedInputStream
(
new
FileInputStream
(
file
)))
{
size
=
file
.
length
();
return
decoder
.
decode
(
file
.
length
(),
inputStream
);
}
else
{
zipFile
=
new
ZipFile
(
zipRef
.
getZipFile
());
ZipEntry
entry
=
zipFile
.
getEntry
(
zipRef
.
getEntryName
());
if
(!
ZipSecurity
.
isValidZipEntry
(
entry
))
{
return
null
;
}
}
}
else
{
if
(
entry
==
null
)
{
try
(
ZipFile
zipFile
=
new
ZipFile
(
zipRef
.
getZipFile
()))
{
throw
new
IOException
(
"Zip entry not found: "
+
zipRef
);
ZipEntry
entry
=
zipFile
.
getEntry
(
zipRef
.
getEntryName
());
if
(
entry
==
null
)
{
throw
new
IOException
(
"Zip entry not found: "
+
zipRef
);
}
if
(!
ZipSecurity
.
isValidZipEntry
(
entry
))
{
return
null
;
}
try
(
InputStream
inputStream
=
new
BufferedInputStream
(
zipFile
.
getInputStream
(
entry
)))
{
return
decoder
.
decode
(
entry
.
getSize
(),
inputStream
);
}
}
}
inputStream
=
new
BufferedInputStream
(
zipFile
.
getInputStream
(
entry
));
size
=
entry
.
getSize
();
}
}
result
=
decoder
.
decode
(
size
,
inputStream
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
JadxException
(
"Error decode: "
+
rf
.
getName
(),
e
);
throw
new
JadxException
(
"Error decode: "
+
rf
.
getName
(),
e
);
}
finally
{
try
{
if
(
zipFile
!=
null
)
{
zipFile
.
close
();
}
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Error close zip file: {}"
,
rf
.
getName
(),
e
);
}
close
(
inputStream
);
}
}
return
result
;
}
}
static
ResContainer
loadContent
(
JadxDecompiler
jadxRef
,
ResourceFile
rf
)
{
static
ResContainer
loadContent
(
JadxDecompiler
jadxRef
,
ResourceFile
rf
)
{
...
@@ -106,7 +91,7 @@ public final class ResourcesLoader {
...
@@ -106,7 +91,7 @@ public final class ResourcesLoader {
}
}
private
static
ResContainer
loadContent
(
JadxDecompiler
jadxRef
,
ResourceFile
rf
,
private
static
ResContainer
loadContent
(
JadxDecompiler
jadxRef
,
ResourceFile
rf
,
InputStream
inputStream
,
long
size
)
throws
IOException
{
InputStream
inputStream
,
long
size
)
throws
IOException
{
switch
(
rf
.
getType
())
{
switch
(
rf
.
getType
())
{
case
MANIFEST:
case
MANIFEST:
case
XML:
case
XML:
...
@@ -118,39 +103,31 @@ public final class ResourcesLoader {
...
@@ -118,39 +103,31 @@ public final class ResourcesLoader {
case
IMG:
case
IMG:
return
ResContainer
.
singleImageFile
(
rf
.
getName
(),
inputStream
);
return
ResContainer
.
singleImageFile
(
rf
.
getName
(),
inputStream
);
default
:
if
(
size
>
LOAD_SIZE_LIMIT
)
{
return
ResContainer
.
singleFile
(
rf
.
getName
(),
new
CodeWriter
().
add
(
"File too big, size: "
+
String
.
format
(
"%.2f KB"
,
size
/
1024
.)));
}
return
ResContainer
.
singleFile
(
rf
.
getName
(),
loadToCodeWriter
(
inputStream
));
}
}
if
(
size
>
LOAD_SIZE_LIMIT
)
{
return
ResContainer
.
singleFile
(
rf
.
getName
(),
new
CodeWriter
().
add
(
"File too big, size: "
+
String
.
format
(
"%.2f KB"
,
size
/
1024
.)));
}
return
ResContainer
.
singleFile
(
rf
.
getName
(),
loadToCodeWriter
(
inputStream
));
}
}
private
void
loadFile
(
List
<
ResourceFile
>
list
,
File
file
)
{
private
void
loadFile
(
List
<
ResourceFile
>
list
,
File
file
)
{
if
(
file
==
null
)
{
if
(
file
==
null
)
{
return
;
return
;
}
}
ZipFile
zip
=
null
;
try
(
ZipFile
zip
=
new
ZipFile
(
file
))
{
try
{
zip
=
new
ZipFile
(
file
);
Enumeration
<?
extends
ZipEntry
>
entries
=
zip
.
entries
();
Enumeration
<?
extends
ZipEntry
>
entries
=
zip
.
entries
();
while
(
entries
.
hasMoreElements
())
{
while
(
entries
.
hasMoreElements
())
{
ZipEntry
entry
=
entries
.
nextElement
();
ZipEntry
entry
=
entries
.
nextElement
();
if
(
ZipSecurity
.
isValidZipEntry
(
entry
))
{
if
(
ZipSecurity
.
isValidZipEntry
(
entry
))
{
addEntry
(
list
,
file
,
entry
);
addEntry
(
list
,
file
,
entry
);
}
}
}
}
}
catch
(
IO
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
debug
(
"Not a zip file: {}"
,
file
.
getAbsolutePath
());
LOG
.
debug
(
"Not a zip file: {}"
,
file
.
getAbsolutePath
());
addResourceFile
(
list
,
file
);
addResourceFile
(
list
,
file
);
}
finally
{
if
(
zip
!=
null
)
{
try
{
zip
.
close
();
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Zip file close error: {}"
,
file
.
getAbsolutePath
(),
e
);
}
}
}
}
}
}
...
@@ -158,7 +135,7 @@ public final class ResourcesLoader {
...
@@ -158,7 +135,7 @@ public final class ResourcesLoader {
String
name
=
file
.
getAbsolutePath
();
String
name
=
file
.
getAbsolutePath
();
ResourceType
type
=
ResourceType
.
getFileType
(
name
);
ResourceType
type
=
ResourceType
.
getFileType
(
name
);
ResourceFile
rf
=
ResourceFile
.
createResourceFileInstance
(
jadxRef
,
name
,
type
);
ResourceFile
rf
=
ResourceFile
.
createResourceFileInstance
(
jadxRef
,
name
,
type
);
if
(
rf
!=
null
)
{
if
(
rf
!=
null
)
{
list
.
add
(
rf
);
list
.
add
(
rf
);
}
}
}
}
...
@@ -170,7 +147,7 @@ public final class ResourcesLoader {
...
@@ -170,7 +147,7 @@ public final class ResourcesLoader {
String
name
=
entry
.
getName
();
String
name
=
entry
.
getName
();
ResourceType
type
=
ResourceType
.
getFileType
(
name
);
ResourceType
type
=
ResourceType
.
getFileType
(
name
);
ResourceFile
rf
=
ResourceFile
.
createResourceFileInstance
(
jadxRef
,
name
,
type
);
ResourceFile
rf
=
ResourceFile
.
createResourceFileInstance
(
jadxRef
,
name
,
type
);
if
(
rf
!=
null
)
{
if
(
rf
!=
null
)
{
rf
.
setZipRef
(
new
ZipRef
(
zipFile
,
name
));
rf
.
setZipRef
(
new
ZipRef
(
zipFile
,
name
));
list
.
add
(
rf
);
list
.
add
(
rf
);
}
}
...
...
jadx-core/src/main/java/jadx/core/Consts.java
View file @
f02b99a1
...
@@ -21,4 +21,7 @@ public class Consts {
...
@@ -21,4 +21,7 @@ public class Consts {
public
static
final
String
ANONYMOUS_CLASS_PREFIX
=
"AnonymousClass"
;
public
static
final
String
ANONYMOUS_CLASS_PREFIX
=
"AnonymousClass"
;
public
static
final
String
MTH_TOSTRING_SIGNATURE
=
"toString()Ljava/lang/String;"
;
public
static
final
String
MTH_TOSTRING_SIGNATURE
=
"toString()Ljava/lang/String;"
;
private
Consts
()
{
}
}
}
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
f02b99a1
package
jadx
.
core
.
codegen
;
package
jadx
.
core
.
codegen
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Set
;
import
com.android.dx.rop.code.AccessFlags
;
import
jadx.api.IJadxArgs
;
import
jadx.api.IJadxArgs
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AttrNode
;
import
jadx.core.dex.attributes.AttrNode
;
import
jadx.core.dex.attributes.nodes.EnumClassAttr
;
import
jadx.core.dex.attributes.nodes.EnumClassAttr
;
import
jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField
;
import
jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField
;
import
jadx.core.dex.attributes.nodes.LineAttrNode
;
import
jadx.core.dex.attributes.nodes.SourceFileAttr
;
import
jadx.core.dex.attributes.nodes.SourceFileAttr
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.info.ClassInfo
;
...
@@ -23,30 +36,7 @@ import jadx.core.utils.ErrorsCounter;
...
@@ -23,30 +36,7 @@ import jadx.core.utils.ErrorsCounter;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.CodegenException
;
import
jadx.core.utils.exceptions.CodegenException
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.android.dx.rop.code.AccessFlags
;
public
class
ClassGen
{
public
class
ClassGen
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ClassGen
.
class
);
public
static
final
Comparator
<
MethodNode
>
METHOD_LINE_COMPARATOR
=
new
Comparator
<
MethodNode
>()
{
@Override
public
int
compare
(
MethodNode
a
,
MethodNode
b
)
{
return
Utils
.
compare
(
a
.
getSourceLine
(),
b
.
getSourceLine
());
}
};
private
final
ClassNode
cls
;
private
final
ClassNode
cls
;
private
final
ClassGen
parentGen
;
private
final
ClassGen
parentGen
;
...
@@ -276,7 +266,7 @@ public class ClassGen {
...
@@ -276,7 +266,7 @@ public class ClassGen {
private
static
List
<
MethodNode
>
sortMethodsByLine
(
List
<
MethodNode
>
methods
)
{
private
static
List
<
MethodNode
>
sortMethodsByLine
(
List
<
MethodNode
>
methods
)
{
List
<
MethodNode
>
out
=
new
ArrayList
<>(
methods
);
List
<
MethodNode
>
out
=
new
ArrayList
<>(
methods
);
Collections
.
sort
(
out
,
METHOD_LINE_COMPARATOR
);
out
.
sort
(
Comparator
.
comparingInt
(
LineAttrNode:
:
getSourceLine
)
);
return
out
;
return
out
;
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
View file @
f02b99a1
package
jadx
.
core
.
dex
.
info
;
package
jadx
.
core
.
dex
.
info
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
org.jetbrains.annotations.Nullable
;
import
jadx.api.IJadxArgs
;
import
jadx.api.IJadxArgs
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.instructions.args.LiteralArg
;
import
jadx.core.dex.instructions.args.LiteralArg
;
...
@@ -10,14 +18,6 @@ import jadx.core.dex.nodes.FieldNode;
...
@@ -10,14 +18,6 @@ import jadx.core.dex.nodes.FieldNode;
import
jadx.core.dex.nodes.ResRefField
;
import
jadx.core.dex.nodes.ResRefField
;
import
jadx.core.dex.nodes.parser.FieldInitAttr
;
import
jadx.core.dex.nodes.parser.FieldInitAttr
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
org.jetbrains.annotations.Nullable
;
public
class
ConstStorage
{
public
class
ConstStorage
{
private
static
final
class
ValueStorage
{
private
static
final
class
ValueStorage
{
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java
View file @
f02b99a1
package
jadx
.
core
.
dex
.
nodes
.
parser
;
package
jadx
.
core
.
dex
.
nodes
.
parser
;
import
java.util.List
;
import
com.android.dex.Dex.Section
;
import
jadx.core.dex.attributes.nodes.SourceFileAttr
;
import
jadx.core.dex.attributes.nodes.SourceFileAttr
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
...
@@ -9,16 +13,8 @@ import jadx.core.dex.nodes.InsnNode;
...
@@ -9,16 +13,8 @@ import jadx.core.dex.nodes.InsnNode;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.utils.exceptions.DecodeException
;
import
jadx.core.utils.exceptions.DecodeException
;
import
java.util.List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.android.dex.Dex.Section
;
public
class
DebugInfoParser
{
public
class
DebugInfoParser
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
DebugInfoParser
.
class
);
private
static
final
int
DBG_END_SEQUENCE
=
0x00
;
private
static
final
int
DBG_END_SEQUENCE
=
0x00
;
private
static
final
int
DBG_ADVANCE_PC
=
0x01
;
private
static
final
int
DBG_ADVANCE_PC
=
0x01
;
private
static
final
int
DBG_ADVANCE_LINE
=
0x02
;
private
static
final
int
DBG_ADVANCE_LINE
=
0x02
;
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/parser/EncValueParser.java
View file @
f02b99a1
package
jadx
.
core
.
dex
.
nodes
.
parser
;
package
jadx
.
core
.
dex
.
nodes
.
parser
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.utils.exceptions.DecodeException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
com.android.dex.Dex.Section
;
import
com.android.dex.Dex.Section
;
import
com.android.dex.Leb128
;
import
com.android.dex.Leb128
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.utils.exceptions.DecodeException
;
public
class
EncValueParser
{
public
class
EncValueParser
{
private
static
final
int
ENCODED_BYTE
=
0x00
;
private
static
final
int
ENCODED_BYTE
=
0x00
;
...
@@ -91,8 +91,10 @@ public class EncValueParser {
...
@@ -91,8 +91,10 @@ public class EncValueParser {
case
ENCODED_ANNOTATION:
case
ENCODED_ANNOTATION:
return
AnnotationsParser
.
readAnnotation
(
dex
,
in
,
false
);
return
AnnotationsParser
.
readAnnotation
(
dex
,
in
,
false
);
default
:
throw
new
DecodeException
(
"Unknown encoded value type: 0x"
+
Integer
.
toHexString
(
type
));
}
}
throw
new
DecodeException
(
"Unknown encoded value type: 0x"
+
Integer
.
toHexString
(
type
));
}
}
private
int
parseUnsignedInt
(
int
byteCount
)
{
private
int
parseUnsignedInt
(
int
byteCount
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java
View file @
f02b99a1
package
jadx
.
core
.
dex
.
visitors
;
package
jadx
.
core
.
dex
.
visitors
;
import
java.io.File
;
import
jadx.api.IJadxArgs
;
import
jadx.api.IJadxArgs
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.utils.exceptions.CodegenException
;
import
jadx.core.utils.files.ZipSecurity
;
import
java.io.File
;
public
class
SaveCode
extends
AbstractVisitor
{
public
class
SaveCode
{
private
final
File
dir
;
private
final
IJadxArgs
args
;
public
SaveCode
(
File
dir
,
IJadxArgs
args
)
{
private
SaveCode
()
{}
this
.
args
=
args
;
this
.
dir
=
dir
;
}
@Override
public
boolean
visit
(
ClassNode
cls
)
throws
CodegenException
{
save
(
dir
,
args
,
cls
);
return
false
;
}
public
static
void
save
(
File
dir
,
IJadxArgs
args
,
ClassNode
cls
)
{
public
static
void
save
(
File
dir
,
IJadxArgs
args
,
ClassNode
cls
)
{
CodeWriter
clsCode
=
cls
.
getCode
();
CodeWriter
clsCode
=
cls
.
getCode
();
String
fileName
=
cls
.
getClassInfo
().
getFullPath
()
+
".java"
;
String
fileName
=
cls
.
getClassInfo
().
getFullPath
()
+
".java"
;
if
(
args
.
isFallbackMode
())
{
if
(
args
.
isFallbackMode
())
{
fileName
+=
".jadx"
;
fileName
+=
".jadx"
;
}
}
clsCode
.
save
(
dir
,
fileName
);
clsCode
.
save
(
dir
,
fileName
);
...
...
jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java
View file @
f02b99a1
package
jadx
.
core
.
utils
;
package
jadx
.
core
.
utils
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.IAttributeNode
;
import
jadx.core.dex.attributes.nodes.JadxErrorAttr
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.utils.exceptions.JadxOverflowException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Set
;
...
@@ -17,6 +9,13 @@ import java.util.Set;
...
@@ -17,6 +9,13 @@ import java.util.Set;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.IAttributeNode
;
import
jadx.core.dex.attributes.nodes.JadxErrorAttr
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.utils.exceptions.JadxOverflowException
;
public
class
ErrorsCounter
{
public
class
ErrorsCounter
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ErrorsCounter
.
class
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ErrorsCounter
.
class
);
...
...
jadx-core/src/main/java/jadx/core/utils/Utils.java
View file @
f02b99a1
package
jadx
.
core
.
utils
;
package
jadx
.
core
.
utils
;
import
jadx.api.JadxDecompiler
;
import
java.io.PrintWriter
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.io.StringWriter
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
jadx.api.JadxDecompiler
;
public
class
Utils
{
public
class
Utils
{
public
static
final
String
JADX_API_PACKAGE
=
JadxDecompiler
.
class
.
getPackage
().
getName
();
public
static
final
String
JADX_API_PACKAGE
=
JadxDecompiler
.
class
.
getPackage
().
getName
();
...
@@ -95,8 +95,4 @@ public class Utils {
...
@@ -95,8 +95,4 @@ public class Utils {
th
.
setStackTrace
(
Arrays
.
copyOfRange
(
stackTrace
,
0
,
cutIndex
));
th
.
setStackTrace
(
Arrays
.
copyOfRange
(
stackTrace
,
0
,
cutIndex
));
}
}
}
}
public
static
int
compare
(
int
x
,
int
y
)
{
return
x
<
y
?
-
1
:
x
==
y
?
0
:
1
;
}
}
}
jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java
View file @
f02b99a1
package
jadx
.
core
.
utils
.
android
;
package
jadx
.
core
.
utils
.
android
;
import
java.util.List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.codegen.ClassGen
;
import
jadx.core.codegen.ClassGen
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.info.ClassInfo
;
...
@@ -7,17 +12,15 @@ import jadx.core.dex.nodes.ClassNode;
...
@@ -7,17 +12,15 @@ import jadx.core.dex.nodes.ClassNode;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.dex.nodes.RootNode
;
import
java.util.List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
/**
* Android resources specific handlers
* Android resources specific handlers
*/
*/
public
class
AndroidResourcesUtils
{
public
class
AndroidResourcesUtils
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
AndroidResourcesUtils
.
class
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
AndroidResourcesUtils
.
class
);
private
AndroidResourcesUtils
()
{
}
public
static
ClassNode
searchAppResClass
(
RootNode
root
)
{
public
static
ClassNode
searchAppResClass
(
RootNode
root
)
{
String
appPackage
=
root
.
getAppPackage
();
String
appPackage
=
root
.
getAppPackage
();
String
fullName
=
appPackage
!=
null
?
appPackage
+
".R"
:
"R"
;
String
fullName
=
appPackage
!=
null
?
appPackage
+
".R"
:
"R"
;
...
@@ -49,7 +52,7 @@ public class AndroidResourcesUtils {
...
@@ -49,7 +52,7 @@ public class AndroidResourcesUtils {
private
static
ClassNode
makeClass
(
RootNode
root
,
String
clsName
)
{
private
static
ClassNode
makeClass
(
RootNode
root
,
String
clsName
)
{
List
<
DexNode
>
dexNodes
=
root
.
getDexNodes
();
List
<
DexNode
>
dexNodes
=
root
.
getDexNodes
();
if
(
dexNodes
.
size
()
==
0
)
{
if
(
dexNodes
.
isEmpty
()
)
{
return
null
;
return
null
;
}
}
DexNode
firstDex
=
dexNodes
.
get
(
0
);
DexNode
firstDex
=
dexNodes
.
get
(
0
);
...
...
jadx-core/src/main/java/jadx/core/utils/android/DataInputDelegate.java
View file @
f02b99a1
/**
/**
*
Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
*
<p>
*
Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
*
you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
*
You may obtain a copy of the License at
* You may obtain a copy of the License at
*
*
<p>
*
http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
*
<p>
*
Unless required by applicable law or agreed to in writing, software
* Unless required by applicable law or agreed to in writing, software
*
distributed under the License is distributed on an "AS IS" BASIS,
* distributed under the License is distributed on an "AS IS" BASIS,
*
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
*
limitations under the License.
* limitations under the License.
*/
*/
package
jadx
.
core
.
utils
.
android
;
package
jadx
.
core
.
utils
.
android
;
...
@@ -22,70 +22,70 @@ import java.io.IOException;
...
@@ -22,70 +22,70 @@ import java.io.IOException;
/**
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
*/
abstract
public
class
DataInputDelegate
implements
DataInput
{
public
abstract
class
DataInputDelegate
implements
DataInput
{
protected
final
DataInput
mDelegate
;
protected
final
DataInput
mDelegate
;
public
DataInputDelegate
(
DataInput
delegate
)
{
public
DataInputDelegate
(
DataInput
delegate
)
{
this
.
mDelegate
=
delegate
;
this
.
mDelegate
=
delegate
;
}
}
public
int
skipBytes
(
int
n
)
throws
IOException
{
public
int
skipBytes
(
int
n
)
throws
IOException
{
return
mDelegate
.
skipBytes
(
n
);
return
mDelegate
.
skipBytes
(
n
);
}
}
public
int
readUnsignedShort
()
throws
IOException
{
public
int
readUnsignedShort
()
throws
IOException
{
return
mDelegate
.
readUnsignedShort
();
return
mDelegate
.
readUnsignedShort
();
}
}
public
int
readUnsignedByte
()
throws
IOException
{
public
int
readUnsignedByte
()
throws
IOException
{
return
mDelegate
.
readUnsignedByte
();
return
mDelegate
.
readUnsignedByte
();
}
}
public
String
readUTF
()
throws
IOException
{
public
String
readUTF
()
throws
IOException
{
return
mDelegate
.
readUTF
();
return
mDelegate
.
readUTF
();
}
}
public
short
readShort
()
throws
IOException
{
public
short
readShort
()
throws
IOException
{
return
mDelegate
.
readShort
();
return
mDelegate
.
readShort
();
}
}
public
long
readLong
()
throws
IOException
{
public
long
readLong
()
throws
IOException
{
return
mDelegate
.
readLong
();
return
mDelegate
.
readLong
();
}
}
public
String
readLine
()
throws
IOException
{
public
String
readLine
()
throws
IOException
{
return
mDelegate
.
readLine
();
return
mDelegate
.
readLine
();
}
}
public
int
readInt
()
throws
IOException
{
public
int
readInt
()
throws
IOException
{
return
mDelegate
.
readInt
();
return
mDelegate
.
readInt
();
}
}
public
void
readFully
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
public
void
readFully
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
mDelegate
.
readFully
(
b
,
off
,
len
);
mDelegate
.
readFully
(
b
,
off
,
len
);
}
}
public
void
readFully
(
byte
[]
b
)
throws
IOException
{
public
void
readFully
(
byte
[]
b
)
throws
IOException
{
mDelegate
.
readFully
(
b
);
mDelegate
.
readFully
(
b
);
}
}
public
float
readFloat
()
throws
IOException
{
public
float
readFloat
()
throws
IOException
{
return
mDelegate
.
readFloat
();
return
mDelegate
.
readFloat
();
}
}
public
double
readDouble
()
throws
IOException
{
public
double
readDouble
()
throws
IOException
{
return
mDelegate
.
readDouble
();
return
mDelegate
.
readDouble
();
}
}
public
char
readChar
()
throws
IOException
{
public
char
readChar
()
throws
IOException
{
return
mDelegate
.
readChar
();
return
mDelegate
.
readChar
();
}
}
public
byte
readByte
()
throws
IOException
{
public
byte
readByte
()
throws
IOException
{
return
mDelegate
.
readByte
();
return
mDelegate
.
readByte
();
}
}
public
boolean
readBoolean
()
throws
IOException
{
public
boolean
readBoolean
()
throws
IOException
{
return
mDelegate
.
readBoolean
();
return
mDelegate
.
readBoolean
();
}
}
}
}
\ No newline at end of file
jadx-core/src/main/java/jadx/core/utils/android/ExtDataInput.java
View file @
f02b99a1
/**
/**
*
Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
*
<p>
*
Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
*
you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
*
You may obtain a copy of the License at
* You may obtain a copy of the License at
*
*
<p>
*
http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
*
<p>
*
Unless required by applicable law or agreed to in writing, software
* Unless required by applicable law or agreed to in writing, software
*
distributed under the License is distributed on an "AS IS" BASIS,
* distributed under the License is distributed on an "AS IS" BASIS,
*
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
*
limitations under the License.
* limitations under the License.
*/
*/
package
jadx
.
core
.
utils
.
android
;
package
jadx
.
core
.
utils
.
android
;
import
java.io.*
;
import
java.io.DataInput
;
import
java.io.DataInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
/**
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
*/
public
class
ExtDataInput
extends
DataInputDelegate
{
public
class
ExtDataInput
extends
DataInputDelegate
{
public
ExtDataInput
(
InputStream
in
)
{
public
ExtDataInput
(
InputStream
in
)
{
this
((
DataInput
)
new
DataInputStream
(
in
));
this
((
DataInput
)
new
DataInputStream
(
in
));
}
}
public
ExtDataInput
(
DataInput
delegate
)
{
public
ExtDataInput
(
DataInput
delegate
)
{
super
(
delegate
);
super
(
delegate
);
}
}
public
int
[]
readIntArray
(
int
length
)
throws
IOException
{
public
int
[]
readIntArray
(
int
length
)
throws
IOException
{
int
[]
array
=
new
int
[
length
];
int
[]
array
=
new
int
[
length
];
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
array
[
i
]
=
readInt
();
array
[
i
]
=
readInt
();
}
}
return
array
;
return
array
;
}
}
public
void
skipInt
()
throws
IOException
{
public
void
skipInt
()
throws
IOException
{
skipBytes
(
4
);
skipBytes
(
4
);
}
}
public
void
skipCheckInt
(
int
expected
)
throws
IOException
{
public
void
skipCheckInt
(
int
expected
)
throws
IOException
{
int
got
=
readInt
();
int
got
=
readInt
();
if
(
got
!=
expected
)
{
if
(
got
!=
expected
)
{
throw
new
IOException
(
String
.
format
(
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
}
}
}
}
public
void
skipCheckShort
(
short
expected
)
throws
IOException
{
public
void
skipCheckShort
(
short
expected
)
throws
IOException
{
short
got
=
readShort
();
short
got
=
readShort
();
if
(
got
!=
expected
)
{
if
(
got
!=
expected
)
{
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
throw
new
IOException
(
String
.
format
(
}
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
}
}
}
public
void
skipCheckByte
(
byte
expected
)
throws
IOException
{
byte
got
=
readByte
();
public
void
skipCheckByte
(
byte
expected
)
throws
IOException
{
if
(
got
!=
expected
)
{
byte
got
=
readByte
();
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
if
(
got
!=
expected
)
{
}
throw
new
IOException
(
String
.
format
(
}
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
}
public
void
skipCheckChunkTypeInt
(
int
expected
,
int
possible
)
throws
IOException
{
}
int
got
=
readInt
();
if
(
got
==
possible
)
{
public
void
skipCheckChunkTypeInt
(
int
expected
,
int
possible
)
throws
IOException
{
skipCheckChunkTypeInt
(
expected
,
-
1
);
int
got
=
readInt
();
}
else
if
(
got
!=
expected
)
{
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
if
(
got
==
possible
)
{
}
skipCheckChunkTypeInt
(
expected
,
-
1
);
}
}
else
if
(
got
!=
expected
)
{
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
/**
}
* The general contract of DataInput doesn't guarantee all the bytes requested will be skipped
}
* and failure can occur for many reasons. We override this to try harder to skip all the bytes
* requested (this is similar to DataInputStream's wrapper).
/**
*/
* The general contract of DataInput doesn't guarantee all the bytes requested will be skipped
@Override
* and failure can occur for many reasons. We override this to try harder to skip all the bytes
public
final
int
skipBytes
(
int
n
)
throws
IOException
{
* requested (this is similar to DataInputStream's wrapper).
int
total
=
0
;
*/
int
cur
=
0
;
public
final
int
skipBytes
(
int
n
)
throws
IOException
{
int
total
=
0
;
while
((
total
<
n
)
&&
((
cur
=
super
.
skipBytes
(
n
-
total
))
>
0
))
{
int
cur
=
0
;
total
+=
cur
;
}
while
((
total
<
n
)
&&
((
cur
=
(
int
)
super
.
skipBytes
(
n
-
total
))
>
0
))
{
return
total
;
total
+=
cur
;
}
}
public
String
readNullEndedString
(
int
length
,
boolean
fixed
)
throws
IOException
{
return
total
;
StringBuilder
string
=
new
StringBuilder
(
16
);
}
while
(
length
--
!=
0
)
{
short
ch
=
readShort
();
public
String
readNullEndedString
(
int
length
,
boolean
fixed
)
if
(
ch
==
0
)
{
throws
IOException
{
break
;
StringBuilder
string
=
new
StringBuilder
(
16
);
}
while
(
length
--
!=
0
)
{
string
.
append
((
char
)
ch
);
short
ch
=
readShort
();
}
if
(
ch
==
0
)
{
if
(
fixed
)
{
break
;
skipBytes
(
length
*
2
);
}
}
string
.
append
((
char
)
ch
);
return
string
.
toString
();
}
}
if
(
fixed
)
{
}
skipBytes
(
length
*
2
);
}
return
string
.
toString
();
}
}
\ No newline at end of file
jadx-core/src/main/java/jadx/core/utils/android/Res9patchStreamDecoder.java
View file @
f02b99a1
/**
/**
*
Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
*
<p>
*
Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
*
you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
*
You may obtain a copy of the License at
* You may obtain a copy of the License at
*
*
<p>
*
http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
*
<p>
*
Unless required by applicable law or agreed to in writing, software
* Unless required by applicable law or agreed to in writing, software
*
distributed under the License is distributed on an "AS IS" BASIS,
* distributed under the License is distributed on an "AS IS" BASIS,
*
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
*
limitations under the License.
* limitations under the License.
*/
*/
package
jadx
.
core
.
utils
.
android
;
package
jadx
.
core
.
utils
.
android
;
import
org.apache.commons.io.IOUtils
;
import
javax.imageio.ImageIO
;
import
java.awt.image.BufferedImage
;
import
java.awt.image.BufferedImage
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.DataInput
;
import
java.io.DataInput
;
...
@@ -25,7 +24,7 @@ import java.io.IOException;
...
@@ -25,7 +24,7 @@ import java.io.IOException;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.OutputStream
;
import
javax.imageio.ImageIO
;
import
org.apache.commons.io.IOUtils
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxException
;
...
@@ -34,105 +33,107 @@ import jadx.core.utils.exceptions.JadxException;
...
@@ -34,105 +33,107 @@ import jadx.core.utils.exceptions.JadxException;
*/
*/
public
class
Res9patchStreamDecoder
{
public
class
Res9patchStreamDecoder
{
public
void
decode
(
InputStream
in
,
OutputStream
out
)
throws
JadxException
{
public
void
decode
(
InputStream
in
,
OutputStream
out
)
throws
JadxException
{
try
{
try
{
byte
[]
data
=
IOUtils
.
toByteArray
(
in
);
byte
[]
data
=
IOUtils
.
toByteArray
(
in
);
BufferedImage
im
=
ImageIO
.
read
(
new
ByteArrayInputStream
(
data
));
BufferedImage
im
=
ImageIO
.
read
(
new
ByteArrayInputStream
(
data
));
int
w
=
im
.
getWidth
(),
h
=
im
.
getHeight
();
int
w
=
im
.
getWidth
();
int
h
=
im
.
getHeight
();
BufferedImage
im2
=
new
BufferedImage
(
w
+
2
,
h
+
2
,
BufferedImage
.
TYPE_INT_ARGB
);
im2
.
createGraphics
().
drawImage
(
im
,
1
,
1
,
w
,
h
,
null
);
BufferedImage
im2
=
new
BufferedImage
(
w
+
2
,
h
+
2
,
BufferedImage
.
TYPE_INT_ARGB
);
im2
.
createGraphics
().
drawImage
(
im
,
1
,
1
,
w
,
h
,
null
);
NinePatch
np
=
getNinePatch
(
data
);
drawHLine
(
im2
,
h
+
1
,
np
.
padLeft
+
1
,
w
-
np
.
padRight
);
NinePatch
np
=
getNinePatch
(
data
);
drawVLine
(
im2
,
w
+
1
,
np
.
padTop
+
1
,
h
-
np
.
padBottom
);
drawHLine
(
im2
,
h
+
1
,
np
.
padLeft
+
1
,
w
-
np
.
padRight
);
drawVLine
(
im2
,
w
+
1
,
np
.
padTop
+
1
,
h
-
np
.
padBottom
);
int
[]
xDivs
=
np
.
xDivs
;
for
(
int
i
=
0
;
i
<
xDivs
.
length
;
i
+=
2
)
{
int
[]
xDivs
=
np
.
xDivs
;
drawHLine
(
im2
,
0
,
xDivs
[
i
]
+
1
,
xDivs
[
i
+
1
]);
for
(
int
i
=
0
;
i
<
xDivs
.
length
;
i
+=
2
)
{
}
drawHLine
(
im2
,
0
,
xDivs
[
i
]
+
1
,
xDivs
[
i
+
1
]);
}
int
[]
yDivs
=
np
.
yDivs
;
for
(
int
i
=
0
;
i
<
yDivs
.
length
;
i
+=
2
)
{
int
[]
yDivs
=
np
.
yDivs
;
drawVLine
(
im2
,
0
,
yDivs
[
i
]
+
1
,
yDivs
[
i
+
1
]);
for
(
int
i
=
0
;
i
<
yDivs
.
length
;
i
+=
2
)
{
}
drawVLine
(
im2
,
0
,
yDivs
[
i
]
+
1
,
yDivs
[
i
+
1
]);
}
ImageIO
.
write
(
im2
,
"png"
,
out
);
}
catch
(
IOException
|
NullPointerException
ex
)
{
ImageIO
.
write
(
im2
,
"png"
,
out
);
throw
new
JadxException
(
ex
.
toString
());
}
catch
(
IOException
|
NullPointerException
ex
)
{
}
throw
new
JadxException
(
ex
.
toString
());
}
}
}
private
NinePatch
getNinePatch
(
byte
[]
data
)
throws
JadxException
,
IOException
{
private
NinePatch
getNinePatch
(
byte
[]
data
)
throws
JadxException
,
IOException
{
ExtDataInput
di
=
new
ExtDataInput
(
new
ByteArrayInputStream
(
data
));
ExtDataInput
di
=
new
ExtDataInput
(
new
ByteArrayInputStream
(
data
));
find9patchChunk
(
di
);
find9patchChunk
(
di
);
return
NinePatch
.
decode
(
di
);
return
NinePatch
.
decode
(
di
);
}
}
private
void
find9patchChunk
(
DataInput
di
)
throws
JadxException
,
private
void
find9patchChunk
(
DataInput
di
)
throws
JadxException
,
IOException
{
IOException
{
di
.
skipBytes
(
8
);
di
.
skipBytes
(
8
);
while
(
true
)
{
while
(
true
)
{
int
size
;
int
size
;
try
{
try
{
size
=
di
.
readInt
();
size
=
di
.
readInt
();
}
catch
(
IOException
ex
)
{
}
catch
(
IOException
ex
)
{
throw
new
JadxException
(
"Cant find nine patch chunk"
,
ex
);
throw
new
JadxException
(
"Cant find nine patch chunk"
,
ex
);
}
}
if
(
di
.
readInt
()
==
NP_CHUNK_TYPE
)
{
if
(
di
.
readInt
()
==
NP_CHUNK_TYPE
)
{
return
;
return
;
}
}
di
.
skipBytes
(
size
+
4
);
di
.
skipBytes
(
size
+
4
);
}
}
}
}
private
void
drawHLine
(
BufferedImage
im
,
int
y
,
int
x1
,
int
x2
)
{
private
void
drawHLine
(
BufferedImage
im
,
int
y
,
int
x1
,
int
x2
)
{
for
(
int
x
=
x1
;
x
<=
x2
;
x
++)
{
for
(
int
x
=
x1
;
x
<=
x2
;
x
++)
{
im
.
setRGB
(
x
,
y
,
NP_COLOR
);
im
.
setRGB
(
x
,
y
,
NP_COLOR
);
}
}
}
}
private
void
drawVLine
(
BufferedImage
im
,
int
x
,
int
y1
,
int
y2
)
{
private
void
drawVLine
(
BufferedImage
im
,
int
x
,
int
y1
,
int
y2
)
{
for
(
int
y
=
y1
;
y
<=
y2
;
y
++)
{
for
(
int
y
=
y1
;
y
<=
y2
;
y
++)
{
im
.
setRGB
(
x
,
y
,
NP_COLOR
);
im
.
setRGB
(
x
,
y
,
NP_COLOR
);
}
}
}
}
private
static
final
int
NP_CHUNK_TYPE
=
0x6e705463
;
// npTc
private
static
final
int
NP_CHUNK_TYPE
=
0x6e705463
;
// npTc
private
static
final
int
NP_COLOR
=
0xff000000
;
private
static
final
int
NP_COLOR
=
0xff000000
;
private
static
class
NinePatch
{
private
static
class
NinePatch
{
public
final
int
padLeft
;
public
final
int
padLeft
,
padRight
,
padTop
,
padBottom
;
public
final
int
padRight
;
public
final
int
[]
xDivs
,
yDivs
;
public
final
int
padTop
;
public
final
int
padBottom
;
public
NinePatch
(
int
padLeft
,
int
padRight
,
int
padTop
,
int
padBottom
,
public
final
int
[]
xDivs
;
int
[]
xDivs
,
int
[]
yDivs
)
{
public
final
int
[]
yDivs
;
this
.
padLeft
=
padLeft
;
this
.
padRight
=
padRight
;
public
NinePatch
(
int
padLeft
,
int
padRight
,
int
padTop
,
int
padBottom
,
this
.
padTop
=
padTop
;
int
[]
xDivs
,
int
[]
yDivs
)
{
this
.
padBottom
=
padBottom
;
this
.
padLeft
=
padLeft
;
this
.
xDivs
=
xDivs
;
this
.
padRight
=
padRight
;
this
.
yDivs
=
yDivs
;
this
.
padTop
=
padTop
;
}
this
.
padBottom
=
padBottom
;
this
.
xDivs
=
xDivs
;
public
static
NinePatch
decode
(
ExtDataInput
di
)
throws
IOException
{
this
.
yDivs
=
yDivs
;
di
.
skipBytes
(
1
);
}
byte
numXDivs
=
di
.
readByte
();
byte
numYDivs
=
di
.
readByte
();
public
static
NinePatch
decode
(
ExtDataInput
di
)
throws
IOException
{
di
.
skipBytes
(
1
);
di
.
skipBytes
(
1
);
di
.
skipBytes
(
8
);
byte
numXDivs
=
di
.
readByte
();
int
padLeft
=
di
.
readInt
();
byte
numYDivs
=
di
.
readByte
();
int
padRight
=
di
.
readInt
();
di
.
skipBytes
(
1
);
int
padTop
=
di
.
readInt
();
di
.
skipBytes
(
8
);
int
padBottom
=
di
.
readInt
();
int
padLeft
=
di
.
readInt
();
di
.
skipBytes
(
4
);
int
padRight
=
di
.
readInt
();
int
[]
xDivs
=
di
.
readIntArray
(
numXDivs
);
int
padTop
=
di
.
readInt
();
int
[]
yDivs
=
di
.
readIntArray
(
numYDivs
);
int
padBottom
=
di
.
readInt
();
di
.
skipBytes
(
4
);
return
new
NinePatch
(
padLeft
,
padRight
,
padTop
,
padBottom
,
xDivs
,
int
[]
xDivs
=
di
.
readIntArray
(
numXDivs
);
yDivs
);
int
[]
yDivs
=
di
.
readIntArray
(
numYDivs
);
}
}
return
new
NinePatch
(
padLeft
,
padRight
,
padTop
,
padBottom
,
xDivs
,
yDivs
);
}
}
\ No newline at end of file
}
}
jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
View file @
f02b99a1
...
@@ -7,6 +7,7 @@ import java.io.FileInputStream;
...
@@ -7,6 +7,7 @@ import java.io.FileInputStream;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.OutputStream
;
import
java.nio.file.Files
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Enumeration
;
import
java.util.Enumeration
;
import
java.util.List
;
import
java.util.List
;
...
@@ -179,20 +180,10 @@ public class FileUtils {
...
@@ -179,20 +180,10 @@ public class FileUtils {
}
}
private
static
boolean
isZipFileCanBeOpen
(
File
file
)
{
private
static
boolean
isZipFileCanBeOpen
(
File
file
)
{
ZipFile
zipFile
=
null
;
try
(
ZipFile
zipFile
=
new
ZipFile
(
file
))
{
try
{
zipFile
=
new
ZipFile
(
file
);
return
zipFile
.
entries
().
hasMoreElements
();
return
zipFile
.
entries
().
hasMoreElements
();
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
return
false
;
return
false
;
}
finally
{
if
(
zipFile
!=
null
)
{
try
{
zipFile
.
close
();
}
catch
(
IOException
e
)
{
LOG
.
error
(
e
.
getMessage
());
}
}
}
}
}
}
...
@@ -214,8 +205,8 @@ public class FileUtils {
...
@@ -214,8 +205,8 @@ public class FileUtils {
LOG
.
debug
(
"Failed to detect filesystem case-sensitivity by file creation"
,
e
);
LOG
.
debug
(
"Failed to detect filesystem case-sensitivity by file creation"
,
e
);
}
finally
{
}
finally
{
try
{
try
{
caseCheckUpper
.
delete
(
);
Files
.
deleteIfExists
(
caseCheckUpper
.
toPath
()
);
caseCheckLow
.
delete
(
);
Files
.
deleteIfExists
(
caseCheckLow
.
toPath
()
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
// ignore
// ignore
}
}
...
...
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
View file @
f02b99a1
package
jadx
.
core
.
utils
.
files
;
package
jadx
.
core
.
utils
.
files
;
import
jadx.core.utils.AsmUtils
;
import
jadx.core.utils.exceptions.DecodeException
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
...
@@ -16,13 +11,16 @@ import java.util.jar.JarOutputStream;
...
@@ -16,13 +11,16 @@ import java.util.jar.JarOutputStream;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipFile
;
import
java.util.zip.ZipFile
;
import
com.android.dex.Dex
;
import
org.apache.commons.io.IOUtils
;
import
org.apache.commons.io.IOUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
com.android.dex.Dex
;
import
jadx.core.utils.AsmUtils
;
import
jadx.core.utils.exceptions.DecodeException
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
close
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
isApkFile
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
isApkFile
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
isZipDexFile
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
isZipDexFile
;
...
@@ -30,7 +28,7 @@ public class InputFile {
...
@@ -30,7 +28,7 @@ public class InputFile {
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
InputFile
.
class
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
InputFile
.
class
);
private
final
File
file
;
private
final
File
file
;
private
final
List
<
DexFile
>
dexFiles
=
new
ArrayList
<
DexFile
>();
private
final
List
<
DexFile
>
dexFiles
=
new
ArrayList
<>();
public
static
void
addFilesFrom
(
File
file
,
List
<
InputFile
>
list
,
boolean
...
skipSources
)
throws
IOException
,
DecodeException
{
public
static
void
addFilesFrom
(
File
file
,
List
<
InputFile
>
list
,
boolean
...
skipSources
)
throws
IOException
,
DecodeException
{
InputFile
inputFile
=
new
InputFile
(
file
);
InputFile
inputFile
=
new
InputFile
(
file
);
...
@@ -38,7 +36,7 @@ public class InputFile {
...
@@ -38,7 +36,7 @@ public class InputFile {
list
.
add
(
inputFile
);
list
.
add
(
inputFile
);
}
}
private
InputFile
(
File
file
)
throws
IOException
,
DecodeException
{
private
InputFile
(
File
file
)
throws
IOException
{
if
(!
file
.
exists
())
{
if
(!
file
.
exists
())
{
throw
new
IOException
(
"File not found: "
+
file
.
getAbsolutePath
());
throw
new
IOException
(
"File not found: "
+
file
.
getAbsolutePath
());
}
}
...
@@ -80,11 +78,11 @@ public class InputFile {
...
@@ -80,11 +78,11 @@ public class InputFile {
throw
new
DecodeException
(
"Unsupported input file format: "
+
file
);
throw
new
DecodeException
(
"Unsupported input file format: "
+
file
);
}
}
private
void
addDexFile
(
Dex
dexBuf
)
throws
IOException
{
private
void
addDexFile
(
Dex
dexBuf
)
{
addDexFile
(
""
,
dexBuf
);
addDexFile
(
""
,
dexBuf
);
}
}
private
void
addDexFile
(
String
fileName
,
Dex
dexBuf
)
throws
IOException
{
private
void
addDexFile
(
String
fileName
,
Dex
dexBuf
)
{
dexFiles
.
add
(
new
DexFile
(
this
,
fileName
,
dexBuf
));
dexFiles
.
add
(
new
DexFile
(
this
,
fileName
,
dexBuf
));
}
}
...
@@ -92,44 +90,41 @@ public class InputFile {
...
@@ -92,44 +90,41 @@ public class InputFile {
int
index
=
0
;
int
index
=
0
;
try
(
ZipFile
zf
=
new
ZipFile
(
file
))
{
try
(
ZipFile
zf
=
new
ZipFile
(
file
))
{
// Input file could be .apk or .zip files
// Input file could be .apk or .zip files
// we should consider the input file could contain only one single dex, multi-dex, or instantRun support dex for Android .apk files
// we should consider the input file could contain only one single dex, multi-dex,
// or instantRun support dex for Android .apk files
String
instantRunDexSuffix
=
"classes"
+
ext
;
String
instantRunDexSuffix
=
"classes"
+
ext
;
for
(
Enumeration
<?
extends
ZipEntry
>
e
=
zf
.
entries
();
e
.
hasMoreElements
();
)
{
for
(
Enumeration
<?
extends
ZipEntry
>
e
=
zf
.
entries
();
e
.
hasMoreElements
();
)
{
ZipEntry
entry
=
e
.
nextElement
();
ZipEntry
entry
=
e
.
nextElement
();
String
entryName
=
entry
.
getName
();
if
(!
ZipSecurity
.
isValidZipEntry
(
entry
))
{
// security check
if
(!
ZipSecurity
.
isValidZipEntry
(
entry
))
{
continue
;
continue
;
}
}
InputStream
inputStream
=
zf
.
getInputStream
(
entry
);
String
entryName
=
entry
.
getName
(
);
try
{
try
(
InputStream
inputStream
=
zf
.
getInputStream
(
entry
))
{
if
((
entryName
.
startsWith
(
"classes"
)
&&
entryName
.
endsWith
(
ext
))
if
((
entryName
.
startsWith
(
"classes"
)
&&
entryName
.
endsWith
(
ext
))
||
entryName
.
endsWith
(
instantRunDexSuffix
))
{
||
entryName
.
endsWith
(
instantRunDexSuffix
))
{
if
(
ext
.
equals
(
".dex"
))
{
switch
(
ext
)
{
index
++;
case
".dex"
:
addDexFile
(
entryName
,
new
Dex
(
inputStream
));
index
++;
}
else
if
(
ext
.
equals
(
".jar"
))
{
addDexFile
(
entryName
,
new
Dex
(
inputStream
));
index
++;
break
;
File
jarFile
=
FileUtils
.
createTempFile
(
entryName
);
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
);
case
".jar"
:
try
{
index
++;
IOUtils
.
copy
(
inputStream
,
fos
);
File
jarFile
=
FileUtils
.
createTempFile
(
entryName
);
}
finally
{
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
))
{
close
(
fos
);
IOUtils
.
copy
(
inputStream
,
fos
);
}
}
addDexFile
(
entryName
,
loadFromJar
(
jarFile
));
addDexFile
(
entryName
,
loadFromJar
(
jarFile
));
}
else
{
break
;
throw
new
JadxRuntimeException
(
"Unexpected extension in zip: "
+
ext
);
default
:
throw
new
JadxRuntimeException
(
"Unexpected extension in zip: "
+
ext
);
}
}
}
else
if
(
entryName
.
equals
(
"instant-run.zip"
)
&&
ext
.
equals
(
".dex"
))
{
}
else
if
(
entryName
.
equals
(
"instant-run.zip"
)
&&
ext
.
equals
(
".dex"
))
{
File
jarFile
=
FileUtils
.
createTempFile
(
"instant-run.zip"
);
File
jarFile
=
FileUtils
.
createTempFile
(
"instant-run.zip"
);
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
);
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
))
{
try
{
IOUtils
.
copy
(
inputStream
,
fos
);
IOUtils
.
copy
(
inputStream
,
fos
);
}
finally
{
close
(
fos
);
}
}
InputFile
tempFile
=
new
InputFile
(
jarFile
);
InputFile
tempFile
=
new
InputFile
(
jarFile
);
tempFile
.
loadFromZip
(
ext
);
tempFile
.
loadFromZip
(
ext
);
...
@@ -139,8 +134,6 @@ public class InputFile {
...
@@ -139,8 +134,6 @@ public class InputFile {
this
.
dexFiles
.
addAll
(
dexFiles
);
this
.
dexFiles
.
addAll
(
dexFiles
);
}
}
}
}
}
finally
{
close
(
inputStream
);
}
}
}
}
}
}
...
@@ -156,7 +149,7 @@ public class InputFile {
...
@@ -156,7 +149,7 @@ public class InputFile {
throw
new
JadxException
(
"Empty dx output"
);
throw
new
JadxException
(
"Empty dx output"
);
}
}
return
new
Dex
(
ba
);
return
new
Dex
(
ba
);
}
catch
(
Throwable
e
)
{
}
catch
(
Exception
e
)
{
throw
new
DecodeException
(
"java class to dex conversion error:\n "
+
e
.
getMessage
(),
e
);
throw
new
DecodeException
(
"java class to dex conversion error:\n "
+
e
.
getMessage
(),
e
);
}
finally
{
}
finally
{
if
(
j2d
.
isError
())
{
if
(
j2d
.
isError
())
{
...
@@ -167,19 +160,12 @@ public class InputFile {
...
@@ -167,19 +160,12 @@ public class InputFile {
private
static
Dex
loadFromClassFile
(
File
file
)
throws
IOException
,
DecodeException
{
private
static
Dex
loadFromClassFile
(
File
file
)
throws
IOException
,
DecodeException
{
File
outFile
=
FileUtils
.
createTempFile
(
"cls.jar"
);
File
outFile
=
FileUtils
.
createTempFile
(
"cls.jar"
);
FileOutputStream
out
=
null
;
try
(
JarOutputStream
jo
=
new
JarOutputStream
(
new
FileOutputStream
(
outFile
)))
{
JarOutputStream
jo
=
null
;
try
{
out
=
new
FileOutputStream
(
outFile
);
jo
=
new
JarOutputStream
(
out
);
String
clsName
=
AsmUtils
.
getNameFromClassFile
(
file
);
String
clsName
=
AsmUtils
.
getNameFromClassFile
(
file
);
if
(
clsName
==
null
||
ZipSecurity
.
isValidZipEntryName
(
clsName
))
{
if
(
clsName
==
null
||
ZipSecurity
.
isValidZipEntryName
(
clsName
))
{
throw
new
IOException
(
"Can't read class name from file: "
+
file
);
throw
new
IOException
(
"Can't read class name from file: "
+
file
);
}
}
FileUtils
.
addFileToJar
(
jo
,
file
,
clsName
+
".class"
);
FileUtils
.
addFileToJar
(
jo
,
file
,
clsName
+
".class"
);
}
finally
{
close
(
jo
);
close
(
out
);
}
}
return
loadFromJar
(
outFile
);
return
loadFromJar
(
outFile
);
}
}
...
...
jadx-core/src/main/java/jadx/core/utils/files/JavaToDex.java
View file @
f02b99a1
...
@@ -5,17 +5,14 @@ import java.io.ByteArrayOutputStream;
...
@@ -5,17 +5,14 @@ import java.io.ByteArrayOutputStream;
import
com.android.dx.command.dexer.DxContext
;
import
com.android.dx.command.dexer.DxContext
;
import
com.android.dx.command.dexer.Main
;
import
com.android.dx.command.dexer.Main
;
import
com.android.dx.command.dexer.Main.Arguments
;
import
com.android.dx.command.dexer.Main.Arguments
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxException
;
public
class
JavaToDex
{
public
class
JavaToDex
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
JavaToDex
.
class
);
private
static
final
String
CHARSET_NAME
=
"UTF-8"
;
private
static
final
String
CHARSET_NAME
=
"UTF-8"
;
p
ublic
static
class
DxArgs
extends
Arguments
{
p
rivate
static
class
DxArgs
extends
Arguments
{
public
DxArgs
(
DxContext
context
,
String
dexFile
,
String
[]
input
)
{
public
DxArgs
(
DxContext
context
,
String
dexFile
,
String
[]
input
)
{
super
(
context
);
super
(
context
);
outName
=
dexFile
;
outName
=
dexFile
;
...
...
jadx-core/src/main/java/jadx/core/utils/files/ZipSecurity.java
View file @
f02b99a1
...
@@ -8,55 +8,55 @@ import org.slf4j.LoggerFactory;
...
@@ -8,55 +8,55 @@ import org.slf4j.LoggerFactory;
public
class
ZipSecurity
{
public
class
ZipSecurity
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ZipSecurity
.
class
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ZipSecurity
.
class
);
// size of uncompressed zip entry shouldn't be bigger of compressed in MAX_SIZE_DIFF times
// size of uncompressed zip entry shouldn't be bigger of compressed in MAX_SIZE_DIFF times
private
static
final
int
MAX_SIZE_DIFF
=
25
;
private
static
final
int
MAX_SIZE_DIFF
=
25
;
private
static
boolean
isInSubDirectory
(
File
base
,
File
file
)
{
if
(
file
==
null
)
{
return
false
;
}
if
(
file
.
equals
(
base
))
{
return
true
;
}
return
isInSubDirectory
(
base
,
file
.
getParentFile
());
private
ZipSecurity
()
{}
private
static
boolean
isInSubDirectory
(
File
base
,
File
file
)
{
if
(
file
==
null
)
{
return
false
;
}
if
(
file
.
equals
(
base
))
{
return
true
;
}
return
isInSubDirectory
(
base
,
file
.
getParentFile
());
}
}
// checks that entry name contains no any traversals
// checks that entry name contains no any traversals
// and prevents cases like "../classes.dex", to limit output only to the specified directory
// and prevents cases like "../classes.dex", to limit output only to the specified directory
public
static
boolean
isValidZipEntryName
(
String
entryName
)
{
public
static
boolean
isValidZipEntryName
(
String
entryName
)
{
try
{
try
{
File
currentPath
=
new
File
(
"."
).
getCanonicalFile
();
File
currentPath
=
new
File
(
"."
).
getCanonicalFile
();
File
canonical
=
new
File
(
currentPath
,
entryName
).
getCanonicalFile
();
File
canonical
=
new
File
(
currentPath
,
entryName
).
getCanonicalFile
();
if
(
isInSubDirectory
(
currentPath
,
canonical
))
{
if
(
isInSubDirectory
(
currentPath
,
canonical
))
{
return
true
;
return
true
;
}
}
LOG
.
error
(
"Path traversal attack detected, invalid name: {}"
,
entryName
);
LOG
.
error
(
"Path traversal attack detected, invalid name: {}"
,
entryName
);
return
false
;
return
false
;
}
}
catch
(
Exception
e
)
{
catch
(
Exception
e
)
{
LOG
.
error
(
"Path traversal attack detected, invalid name: {}"
,
entryName
);
LOG
.
error
(
"Path traversal attack detected, invalid name: {}"
,
entryName
);
return
false
;
return
false
;
}
}
}
}
public
static
boolean
isZipBomb
(
ZipEntry
entry
)
{
public
static
boolean
isZipBomb
(
ZipEntry
entry
)
{
long
compressedSize
=
entry
.
getCompressedSize
();
long
compressedSize
=
entry
.
getCompressedSize
();
long
uncompressedSize
=
entry
.
getSize
();
long
uncompressedSize
=
entry
.
getSize
();
if
(
compressedSize
<
0
||
uncompressedSize
<
0
)
{
if
(
compressedSize
<
0
||
uncompressedSize
<
0
)
{
LOG
.
error
(
"Zip bomp attack detected, invalid sizes: compressed {}, uncompressed {}, name {}"
,
LOG
.
error
(
"Zip bomp attack detected, invalid sizes: compressed {}, uncompressed {}, name {}"
,
compressedSize
,
uncompressedSize
,
entry
.
getName
());
compressedSize
,
uncompressedSize
,
entry
.
getName
());
return
true
;
return
true
;
}
}
if
(
compressedSize
*
MAX_SIZE_DIFF
<
uncompressedSize
)
{
if
(
compressedSize
*
MAX_SIZE_DIFF
<
uncompressedSize
)
{
LOG
.
error
(
"Zip bom
p
attack detected, invalid sizes: compressed {}, uncompressed {}, name {}"
,
LOG
.
error
(
"Zip bom
b
attack detected, invalid sizes: compressed {}, uncompressed {}, name {}"
,
compressedSize
,
uncompressedSize
,
entry
.
getName
());
compressedSize
,
uncompressedSize
,
entry
.
getName
());
return
true
;
return
true
;
}
}
return
false
;
return
false
;
}
}
public
static
boolean
isValidZipEntry
(
ZipEntry
entry
)
{
public
static
boolean
isValidZipEntry
(
ZipEntry
entry
)
{
return
isValidZipEntryName
(
entry
.
getName
())
return
isValidZipEntryName
(
entry
.
getName
())
&&
!
isZipBomb
(
entry
);
&&
!
isZipBomb
(
entry
);
...
...
jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
View file @
f02b99a1
package
jadx
.
core
.
xmlgen
;
package
jadx
.
core
.
xmlgen
;
import
jadx.api.ResourcesLoader
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.info.ConstStorage
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.core.xmlgen.entry.ValuesParser
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
...
@@ -18,6 +9,16 @@ import java.util.Map;
...
@@ -18,6 +9,16 @@ import java.util.Map;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.ResourcesLoader
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.info.ConstStorage
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.utils.StringUtils
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.core.xmlgen.entry.ValuesParser
;
/* 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
...
@@ -34,10 +35,12 @@ public class BinaryXMLParser extends CommonBinaryParser {
...
@@ -34,10 +35,12 @@ public class BinaryXMLParser extends CommonBinaryParser {
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
BinaryXMLParser
.
class
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
BinaryXMLParser
.
class
);
private
static
final
String
ANDROID_R_STYLE_CLS
=
"android.R$style"
;
private
static
final
String
ANDROID_R_STYLE_CLS
=
"android.R$style"
;
private
static
final
boolean
ATTR_NEW_LINE
=
false
;
private
static
final
boolean
ATTR_NEW_LINE
=
false
;
private
final
Map
<
Integer
,
String
>
styleMap
=
new
HashMap
<
Integer
,
String
>();
private
final
Map
<
Integer
,
FieldNode
>
localStyleMap
=
new
HashMap
<
Integer
,
FieldNode
>();
private
final
Map
<
Integer
,
String
>
styleMap
=
new
HashMap
<>();
private
final
Map
<
Integer
,
FieldNode
>
localStyleMap
=
new
HashMap
<>();
private
final
Map
<
Integer
,
String
>
resNames
;
private
final
Map
<
Integer
,
String
>
resNames
;
private
final
Map
<
String
,
String
>
nsMap
=
new
HashMap
<>();
private
final
Map
<
String
,
String
>
nsMap
=
new
HashMap
<>();
private
CodeWriter
writer
;
private
CodeWriter
writer
;
private
String
[]
strings
;
private
String
[]
strings
;
private
String
currentTag
=
"ERROR"
;
private
String
currentTag
=
"ERROR"
;
...
@@ -48,14 +51,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
...
@@ -48,14 +51,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
public
BinaryXMLParser
(
RootNode
root
)
{
public
BinaryXMLParser
(
RootNode
root
)
{
try
{
try
{
try
{
readAndroidRStyleClass
();
Class
<?>
rStyleCls
=
Class
.
forName
(
ANDROID_R_STYLE_CLS
);
for
(
Field
f
:
rStyleCls
.
getFields
())
{
styleMap
.
put
(
f
.
getInt
(
f
.
getType
()),
f
.
getName
());
}
}
catch
(
Throwable
th
)
{
LOG
.
error
(
"R class loading failed"
,
th
);
}
// add application constants
// add application constants
ConstStorage
constStorage
=
root
.
getConstValues
();
ConstStorage
constStorage
=
root
.
getConstValues
();
Map
<
Object
,
FieldNode
>
constFields
=
constStorage
.
getGlobalConstFields
();
Map
<
Object
,
FieldNode
>
constFields
=
constStorage
.
getGlobalConstFields
();
...
@@ -72,6 +68,17 @@ public class BinaryXMLParser extends CommonBinaryParser {
...
@@ -72,6 +68,17 @@ public class BinaryXMLParser extends CommonBinaryParser {
}
}
}
}
private
void
readAndroidRStyleClass
()
{
try
{
Class
<?>
rStyleCls
=
Class
.
forName
(
ANDROID_R_STYLE_CLS
);
for
(
Field
f
:
rStyleCls
.
getFields
())
{
styleMap
.
put
(
f
.
getInt
(
f
.
getType
()),
f
.
getName
());
}
}
catch
(
Exception
th
)
{
LOG
.
error
(
"Android R class loading failed"
,
th
);
}
}
public
synchronized
CodeWriter
parse
(
InputStream
inputStream
)
throws
IOException
{
public
synchronized
CodeWriter
parse
(
InputStream
inputStream
)
throws
IOException
{
is
=
new
ParserStream
(
inputStream
);
is
=
new
ParserStream
(
inputStream
);
if
(!
isBinaryXml
())
{
if
(!
isBinaryXml
())
{
...
@@ -186,13 +193,11 @@ public class BinaryXMLParser extends CommonBinaryParser {
...
@@ -186,13 +193,11 @@ public class BinaryXMLParser extends CommonBinaryParser {
int
strIndex
=
is
.
readInt32
();
int
strIndex
=
is
.
readInt32
();
String
str
=
strings
[
strIndex
];
String
str
=
strings
[
strIndex
];
writer
.
startLine
().
addIndent
();
writer
.
attachSourceLine
(
lineNumber
);
writer
.
add
(
StringUtils
.
escapeXML
(
str
.
trim
()));
//TODO: what's this for?
long
size
=
is
.
readInt16
();
/*writer.startLine().addIndent();
writer.attachSourceLine(lineNumber);
writer.add(StringUtils.escapeXML(str.trim()));*/
int
size
=
is
.
readInt16
();
is
.
skip
(
size
-
2
);
is
.
skip
(
size
-
2
);
}
}
...
@@ -236,7 +241,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
...
@@ -236,7 +241,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
writer
.
add
(
" xmlns:"
+
entry
.
getValue
()
+
"=\""
).
add
(
entry
.
getKey
()).
add
(
"\""
);
writer
.
add
(
" xmlns:"
+
entry
.
getValue
()
+
"=\""
).
add
(
entry
.
getKey
()).
add
(
"\""
);
}
}
}
}
boolean
attrNewLine
=
attributeCount
==
1
?
false
:
ATTR_NEW_LINE
;
boolean
attrNewLine
=
attributeCount
!=
1
&&
ATTR_NEW_LINE
;
for
(
int
i
=
0
;
i
<
attributeCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
attributeCount
;
i
++)
{
parseAttribute
(
i
,
attrNewLine
);
parseAttribute
(
i
,
attrNewLine
);
}
}
...
@@ -284,7 +289,6 @@ public class BinaryXMLParser extends CommonBinaryParser {
...
@@ -284,7 +289,6 @@ public class BinaryXMLParser extends CommonBinaryParser {
if
(
attributeNS
!=
-
1
)
{
if
(
attributeNS
!=
-
1
)
{
writer
.
add
(
nsMap
.
get
(
strings
[
attributeNS
])).
add
(
':'
);
writer
.
add
(
nsMap
.
get
(
strings
[
attributeNS
])).
add
(
':'
);
}
}
LOG
.
debug
(
"decodeAttribute: "
+
attributeNS
+
" "
+
name
);
writer
.
add
(
"style/"
).
add
(
name
.
replaceAll
(
"_"
,
"."
));
writer
.
add
(
"style/"
).
add
(
name
.
replaceAll
(
"_"
,
"."
));
}
else
{
}
else
{
FieldNode
field
=
localStyleMap
.
get
(
attrValData
);
FieldNode
field
=
localStyleMap
.
get
(
attrValData
);
...
@@ -304,7 +308,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
...
@@ -304,7 +308,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
}
}
writer
.
add
(
resName
);
writer
.
add
(
resName
);
}
else
{
}
else
{
resName
=
ValuesParser
.
androidResMap
.
get
(
attrValData
);
resName
=
ValuesParser
.
getAndroidResMap
()
.
get
(
attrValData
);
if
(
resName
!=
null
)
{
if
(
resName
!=
null
)
{
writer
.
add
(
"@android:"
).
add
(
resName
);
writer
.
add
(
"@android:"
).
add
(
resName
);
}
else
if
(
attrValData
==
0
)
{
}
else
if
(
attrValData
==
0
)
{
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ManifestAttributes.java
View file @
f02b99a1
...
@@ -56,7 +56,7 @@ public class ManifestAttributes {
...
@@ -56,7 +56,7 @@ public class ManifestAttributes {
try
{
try
{
instance
=
new
ManifestAttributes
();
instance
=
new
ManifestAttributes
();
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
);
LOG
.
error
(
"Failed to create ManifestAttributes"
,
e
);
}
}
}
}
return
instance
;
return
instance
;
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ResContainer.java
View file @
f02b99a1
package
jadx
.
core
.
xmlgen
;
package
jadx
.
core
.
xmlgen
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.utils.android.Res9patchStreamDecoder
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
javax.imageio.ImageIO
;
import
javax.imageio.ImageIO
;
import
java.awt.image.BufferedImage
;
import
java.awt.image.BufferedImage
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayInputStream
;
...
@@ -17,9 +12,17 @@ import java.util.List;
...
@@ -17,9 +12,17 @@ import java.util.List;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.utils.android.Res9patchStreamDecoder
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
public
class
ResContainer
implements
Comparable
<
ResContainer
>
{
public
class
ResContainer
implements
Comparable
<
ResContainer
>
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ResContainer
.
class
);
private
final
String
name
;
private
final
String
name
;
private
final
List
<
ResContainer
>
subFiles
;
private
final
List
<
ResContainer
>
subFiles
;
...
@@ -34,21 +37,21 @@ public class ResContainer implements Comparable<ResContainer> {
...
@@ -34,21 +37,21 @@ public class ResContainer implements Comparable<ResContainer> {
}
}
public
static
ResContainer
singleFile
(
String
name
,
CodeWriter
content
)
{
public
static
ResContainer
singleFile
(
String
name
,
CodeWriter
content
)
{
ResContainer
resContainer
=
new
ResContainer
(
name
,
Collections
.
<
ResContainer
>
emptyList
());
ResContainer
resContainer
=
new
ResContainer
(
name
,
Collections
.
emptyList
());
resContainer
.
content
=
content
;
resContainer
.
content
=
content
;
return
resContainer
;
return
resContainer
;
}
}
public
static
ResContainer
singleImageFile
(
String
name
,
InputStream
content
)
{
public
static
ResContainer
singleImageFile
(
String
name
,
InputStream
content
)
{
ResContainer
resContainer
=
new
ResContainer
(
name
,
Collections
.
<
ResContainer
>
emptyList
());
ResContainer
resContainer
=
new
ResContainer
(
name
,
Collections
.
emptyList
());
InputStream
newContent
=
content
;
InputStream
newContent
=
content
;
if
(
name
.
endsWith
(
".9.png"
))
{
if
(
name
.
endsWith
(
".9.png"
))
{
Res9patchStreamDecoder
decoder
=
new
Res9patchStreamDecoder
();
Res9patchStreamDecoder
decoder
=
new
Res9patchStreamDecoder
();
ByteArrayOutputStream
os
=
new
ByteArrayOutputStream
();
ByteArrayOutputStream
os
=
new
ByteArrayOutputStream
();
try
{
try
{
decoder
.
decode
(
content
,
os
);
decoder
.
decode
(
content
,
os
);
}
catch
(
Jadx
Exception
e
)
{
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
);
LOG
.
error
(
"Failed to decode 9-patch png image"
,
e
);
}
}
newContent
=
new
ByteArrayInputStream
(
os
.
toByteArray
());
newContent
=
new
ByteArrayInputStream
(
os
.
toByteArray
());
}
}
...
@@ -61,7 +64,7 @@ public class ResContainer implements Comparable<ResContainer> {
...
@@ -61,7 +64,7 @@ public class ResContainer implements Comparable<ResContainer> {
}
}
public
static
ResContainer
multiFile
(
String
name
)
{
public
static
ResContainer
multiFile
(
String
name
)
{
return
new
ResContainer
(
name
,
new
ArrayList
<
ResContainer
>());
return
new
ResContainer
(
name
,
new
ArrayList
<>());
}
}
public
String
getName
()
{
public
String
getName
()
{
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ResourceStorage.java
View file @
f02b99a1
package
jadx
.
core
.
xmlgen
;
package
jadx
.
core
.
xmlgen
;
import
jadx.core.utils.Utils
;
import
jadx.core.xmlgen.entry.ResourceEntry
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
...
@@ -11,14 +8,9 @@ import java.util.HashMap;
...
@@ -11,14 +8,9 @@ import java.util.HashMap;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
public
class
ResourceStorage
{
import
jadx.core.xmlgen.entry.ResourceEntry
;
private
static
final
Comparator
<
ResourceEntry
>
COMPARATOR
=
new
Comparator
<
ResourceEntry
>()
{
public
class
ResourceStorage
{
@Override
public
int
compare
(
ResourceEntry
a
,
ResourceEntry
b
)
{
return
Utils
.
compare
(
a
.
getId
(),
b
.
getId
());
}
};
private
final
List
<
ResourceEntry
>
list
=
new
ArrayList
<>();
private
final
List
<
ResourceEntry
>
list
=
new
ArrayList
<>();
private
String
appPackage
;
private
String
appPackage
;
...
@@ -32,12 +24,12 @@ public class ResourceStorage {
...
@@ -32,12 +24,12 @@ public class ResourceStorage {
}
}
public
void
finish
()
{
public
void
finish
()
{
Collections
.
sort
(
list
,
COMPARATOR
);
list
.
sort
(
Comparator
.
comparingInt
(
ResourceEntry:
:
getId
)
);
}
}
public
ResourceEntry
getByRef
(
int
refId
)
{
public
ResourceEntry
getByRef
(
int
refId
)
{
ResourceEntry
key
=
new
ResourceEntry
(
refId
);
ResourceEntry
key
=
new
ResourceEntry
(
refId
);
int
index
=
Collections
.
binarySearch
(
list
,
key
,
C
OMPARATOR
);
int
index
=
Collections
.
binarySearch
(
list
,
key
,
C
omparator
.
comparingInt
(
ResourceEntry:
:
getId
)
);
if
(
index
<
0
)
{
if
(
index
<
0
)
{
return
null
;
return
null
;
}
}
...
...
jadx-core/src/main/java/jadx/core/xmlgen/XmlSecurity.java
View file @
f02b99a1
...
@@ -4,23 +4,24 @@ import javax.xml.parsers.DocumentBuilderFactory;
...
@@ -4,23 +4,24 @@ import javax.xml.parsers.DocumentBuilderFactory;
import
javax.xml.parsers.ParserConfigurationException
;
import
javax.xml.parsers.ParserConfigurationException
;
public
class
XmlSecurity
{
public
class
XmlSecurity
{
private
static
DocumentBuilderFactory
secureDbf
=
null
;
private
static
DocumentBuilderFactory
secureDbf
=
null
;
private
XmlSecurity
()
{}
public
static
DocumentBuilderFactory
getSecureDbf
()
throws
ParserConfigurationException
{
public
static
DocumentBuilderFactory
getSecureDbf
()
throws
ParserConfigurationException
{
synchronized
(
XmlSecurity
.
class
)
{
synchronized
(
XmlSecurity
.
class
)
{
if
(
secureDbf
==
null
)
{
if
(
secureDbf
==
null
)
{
secureDbf
=
DocumentBuilderFactory
.
newInstance
();
secureDbf
=
DocumentBuilderFactory
.
newInstance
();
secureDbf
.
setFeature
(
"http://apache.org/xml/features/disallow-doctype-decl"
,
true
);
secureDbf
.
setFeature
(
"http://apache.org/xml/features/disallow-doctype-decl"
,
true
);
secureDbf
.
setFeature
(
"http://apache.org/xml/features/nonvalidating/load-external-dtd"
,
false
);
secureDbf
.
setFeature
(
"http://apache.org/xml/features/nonvalidating/load-external-dtd"
,
false
);
secureDbf
.
setFeature
(
"http://xml.org/sax/features/external-general-entities"
,
false
);
secureDbf
.
setFeature
(
"http://xml.org/sax/features/external-general-entities"
,
false
);
secureDbf
.
setFeature
(
"http://xml.org/sax/features/external-parameter-entities"
,
false
);
secureDbf
.
setFeature
(
"http://xml.org/sax/features/external-parameter-entities"
,
false
);
secureDbf
.
setFeature
(
"http://apache.org/xml/features/dom/create-entity-ref-nodes"
,
false
);
secureDbf
.
setFeature
(
"http://apache.org/xml/features/dom/create-entity-ref-nodes"
,
false
);
secureDbf
.
setXIncludeAware
(
false
);
secureDbf
.
setXIncludeAware
(
false
);
secureDbf
.
setExpandEntityReferences
(
false
);
secureDbf
.
setExpandEntityReferences
(
false
);
}
}
}
}
return
secureDbf
;
return
secureDbf
;
}
}
}
}
jadx-core/src/main/java/jadx/core/xmlgen/entry/ValuesParser.java
View file @
f02b99a1
...
@@ -18,12 +18,12 @@ import jadx.core.xmlgen.ResTableParser;
...
@@ -18,12 +18,12 @@ import jadx.core.xmlgen.ResTableParser;
public
class
ValuesParser
extends
ParserConstants
{
public
class
ValuesParser
extends
ParserConstants
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ValuesParser
.
class
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ValuesParser
.
class
);
private
static
String
[]
androidStrings
;
private
static
Map
<
Integer
,
String
>
androidResMap
;
private
final
String
[]
strings
;
private
final
String
[]
strings
;
private
final
Map
<
Integer
,
String
>
resMap
;
private
final
Map
<
Integer
,
String
>
resMap
;
public
static
String
[]
androidStrings
;
public
static
Map
<
Integer
,
String
>
androidResMap
;
public
ValuesParser
(
String
[]
strings
,
Map
<
Integer
,
String
>
resMap
)
{
public
ValuesParser
(
String
[]
strings
,
Map
<
Integer
,
String
>
resMap
)
{
this
.
strings
=
strings
;
this
.
strings
=
strings
;
this
.
resMap
=
resMap
;
this
.
resMap
=
resMap
;
...
@@ -31,14 +31,14 @@ public class ValuesParser extends ParserConstants {
...
@@ -31,14 +31,14 @@ public class ValuesParser extends ParserConstants {
if
(
androidStrings
==
null
&&
androidResMap
==
null
)
{
if
(
androidStrings
==
null
&&
androidResMap
==
null
)
{
try
{
try
{
decodeAndroid
();
decodeAndroid
();
}
catch
(
IO
Exception
e
)
{
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
);
LOG
.
error
(
"Failed to decode Android Resource file"
,
e
);
}
}
}
}
}
}
private
void
decodeAndroid
()
throws
IOException
{
private
static
void
decodeAndroid
()
throws
IOException
{
InputStream
inputStream
=
new
BufferedInputStream
(
getClass
()
.
getResourceAsStream
(
"/resources.arsc"
));
InputStream
inputStream
=
new
BufferedInputStream
(
ValuesParser
.
class
.
getResourceAsStream
(
"/resources.arsc"
));
ResTableParser
androidParser
=
new
ResTableParser
();
ResTableParser
androidParser
=
new
ResTableParser
();
androidParser
.
decode
(
inputStream
);
androidParser
.
decode
(
inputStream
);
androidStrings
=
androidParser
.
getStrings
();
androidStrings
=
androidParser
.
getStrings
();
...
@@ -212,4 +212,8 @@ public class ValuesParser extends ParserConstants {
...
@@ -212,4 +212,8 @@ public class ValuesParser extends ParserConstants {
f
.
setMinimumIntegerDigits
(
1
);
f
.
setMinimumIntegerDigits
(
1
);
return
f
.
format
(
value
);
return
f
.
format
(
value
);
}
}
public
static
Map
<
Integer
,
String
>
getAndroidResMap
()
{
return
androidResMap
;
}
}
}
jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java
View file @
f02b99a1
...
@@ -7,19 +7,11 @@ import java.util.Enumeration;
...
@@ -7,19 +7,11 @@ import java.util.Enumeration;
import
java.util.List
;
import
java.util.List
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
import
javax.swing.Icon
;
import
javax.swing.ImageIcon
;
import
jadx.api.ResourceFile
;
import
jadx.gui.JadxWrapper
;
import
jadx.api.ResourceFile
;
import
jadx.api.ResourceFile
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.treemodel.JResource.JResType
;
import
jadx.gui.treemodel.JResource.JResType
;
import
jadx.gui.utils.Utils
;
import
jadx.gui.utils.Utils
;
import
jadx.gui.treemodel.JResource.JResType
;
import
jadx.gui.utils.Utils
;
public
class
JRoot
extends
JNode
{
public
class
JRoot
extends
JNode
{
private
static
final
long
serialVersionUID
=
8888495789773527342L
;
private
static
final
long
serialVersionUID
=
8888495789773527342L
;
...
...
jadx-gui/src/main/java/jadx/gui/ui/CommonSearchDialog.java
View file @
f02b99a1
...
@@ -6,8 +6,6 @@ import javax.swing.table.TableCellRenderer;
...
@@ -6,8 +6,6 @@ import javax.swing.table.TableCellRenderer;
import
javax.swing.table.TableColumn
;
import
javax.swing.table.TableColumn
;
import
javax.swing.table.TableColumnModel
;
import
javax.swing.table.TableColumnModel
;
import
java.awt.*
;
import
java.awt.*
;
import
java.awt.event.ActionEvent
;
import
java.awt.event.ActionListener
;
import
java.awt.event.KeyAdapter
;
import
java.awt.event.KeyAdapter
;
import
java.awt.event.KeyEvent
;
import
java.awt.event.KeyEvent
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseAdapter
;
...
@@ -90,12 +88,7 @@ public abstract class CommonSearchDialog extends JDialog {
...
@@ -90,12 +88,7 @@ public abstract class CommonSearchDialog extends JDialog {
addWindowListener
(
new
WindowAdapter
()
{
addWindowListener
(
new
WindowAdapter
()
{
@Override
@Override
public
void
windowOpened
(
WindowEvent
e
)
{
public
void
windowOpened
(
WindowEvent
e
)
{
SwingUtilities
.
invokeLater
(
new
Runnable
()
{
SwingUtilities
.
invokeLater
(
CommonSearchDialog
.
this
::
openInit
);
@Override
public
void
run
()
{
openInit
();
}
});
}
}
});
});
}
}
...
@@ -119,12 +112,7 @@ public abstract class CommonSearchDialog extends JDialog {
...
@@ -119,12 +112,7 @@ public abstract class CommonSearchDialog extends JDialog {
protected
void
initCommon
()
{
protected
void
initCommon
()
{
KeyStroke
stroke
=
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_ESCAPE
,
0
);
KeyStroke
stroke
=
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_ESCAPE
,
0
);
getRootPane
().
registerKeyboardAction
(
new
ActionListener
()
{
getRootPane
().
registerKeyboardAction
(
e
->
dispose
(),
stroke
,
JComponent
.
WHEN_IN_FOCUSED_WINDOW
);
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
dispose
();
}
},
stroke
,
JComponent
.
WHEN_IN_FOCUSED_WINDOW
);
}
}
@NotNull
@NotNull
...
@@ -132,17 +120,9 @@ public abstract class CommonSearchDialog extends JDialog {
...
@@ -132,17 +120,9 @@ public abstract class CommonSearchDialog extends JDialog {
progressPane
=
new
ProgressPanel
(
mainWindow
,
false
);
progressPane
=
new
ProgressPanel
(
mainWindow
,
false
);
JButton
cancelButton
=
new
JButton
(
NLS
.
str
(
"search_dialog.cancel"
));
JButton
cancelButton
=
new
JButton
(
NLS
.
str
(
"search_dialog.cancel"
));
cancelButton
.
addActionListener
(
new
ActionListener
()
{
cancelButton
.
addActionListener
(
event
->
dispose
());
public
void
actionPerformed
(
ActionEvent
event
)
{
dispose
();
}
});
JButton
openBtn
=
new
JButton
(
NLS
.
str
(
"search_dialog.open"
));
JButton
openBtn
=
new
JButton
(
NLS
.
str
(
"search_dialog.open"
));
openBtn
.
addActionListener
(
new
ActionListener
()
{
openBtn
.
addActionListener
(
event
->
openSelectedItem
());
public
void
actionPerformed
(
ActionEvent
event
)
{
openSelectedItem
();
}
});
getRootPane
().
setDefaultButton
(
openBtn
);
getRootPane
().
setDefaultButton
(
openBtn
);
JPanel
buttonPane
=
new
JPanel
();
JPanel
buttonPane
=
new
JPanel
();
...
...
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