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
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
;
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.ByteArrayOutputStream
;
import
java.io.File
;
...
...
@@ -24,8 +15,16 @@ import java.util.zip.ZipFile;
import
org.slf4j.Logger
;
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
.
close
;
import
static
jadx
.
core
.
utils
.
files
.
FileUtils
.
copyStream
;
// TODO: move to core package
...
...
@@ -53,44 +52,30 @@ public final class ResourcesLoader {
}
public
static
ResContainer
decodeStream
(
ResourceFile
rf
,
ResourceDecoder
decoder
)
throws
JadxException
{
ZipFile
zipFile
=
null
;
InputStream
inputStream
=
null
;
ResContainer
result
;
try
{
long
size
;
ZipRef
zipRef
=
rf
.
getZipRef
();
if
(
zipRef
==
null
)
{
File
file
=
new
File
(
rf
.
getName
());
inputStream
=
new
BufferedInputStream
(
new
FileInputStream
(
file
));
size
=
file
.
length
();
}
else
{
zipFile
=
new
ZipFile
(
zipRef
.
getZipFile
());
ZipEntry
entry
=
zipFile
.
getEntry
(
zipRef
.
getEntryName
());
if
(!
ZipSecurity
.
isValidZipEntry
(
entry
))
{
return
null
;
try
(
InputStream
inputStream
=
new
BufferedInputStream
(
new
FileInputStream
(
file
)))
{
return
decoder
.
decode
(
file
.
length
(),
inputStream
);
}
if
(
entry
==
null
)
{
throw
new
IOException
(
"Zip entry not found: "
+
zipRef
);
}
else
{
try
(
ZipFile
zipFile
=
new
ZipFile
(
zipRef
.
getZipFile
()))
{
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
)
{
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
)
{
...
...
@@ -106,7 +91,7 @@ public final class ResourcesLoader {
}
private
static
ResContainer
loadContent
(
JadxDecompiler
jadxRef
,
ResourceFile
rf
,
InputStream
inputStream
,
long
size
)
throws
IOException
{
InputStream
inputStream
,
long
size
)
throws
IOException
{
switch
(
rf
.
getType
())
{
case
MANIFEST:
case
XML:
...
...
@@ -118,39 +103,31 @@ public final class ResourcesLoader {
case
IMG:
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
)
{
if
(
file
==
null
)
{
return
;
}
ZipFile
zip
=
null
;
try
{
zip
=
new
ZipFile
(
file
);
try
(
ZipFile
zip
=
new
ZipFile
(
file
))
{
Enumeration
<?
extends
ZipEntry
>
entries
=
zip
.
entries
();
while
(
entries
.
hasMoreElements
())
{
ZipEntry
entry
=
entries
.
nextElement
();
if
(
ZipSecurity
.
isValidZipEntry
(
entry
))
{
if
(
ZipSecurity
.
isValidZipEntry
(
entry
))
{
addEntry
(
list
,
file
,
entry
);
}
}
}
catch
(
IO
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
debug
(
"Not a zip file: {}"
,
file
.
getAbsolutePath
());
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 {
String
name
=
file
.
getAbsolutePath
();
ResourceType
type
=
ResourceType
.
getFileType
(
name
);
ResourceFile
rf
=
ResourceFile
.
createResourceFileInstance
(
jadxRef
,
name
,
type
);
if
(
rf
!=
null
)
{
if
(
rf
!=
null
)
{
list
.
add
(
rf
);
}
}
...
...
@@ -170,7 +147,7 @@ public final class ResourcesLoader {
String
name
=
entry
.
getName
();
ResourceType
type
=
ResourceType
.
getFileType
(
name
);
ResourceFile
rf
=
ResourceFile
.
createResourceFileInstance
(
jadxRef
,
name
,
type
);
if
(
rf
!=
null
)
{
if
(
rf
!=
null
)
{
rf
.
setZipRef
(
new
ZipRef
(
zipFile
,
name
));
list
.
add
(
rf
);
}
...
...
jadx-core/src/main/java/jadx/core/Consts.java
View file @
f02b99a1
...
...
@@ -21,4 +21,7 @@ public class Consts {
public
static
final
String
ANONYMOUS_CLASS_PREFIX
=
"AnonymousClass"
;
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
;
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.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AttrNode
;
import
jadx.core.dex.attributes.nodes.EnumClassAttr
;
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.info.AccessInfo
;
import
jadx.core.dex.info.ClassInfo
;
...
...
@@ -23,30 +36,7 @@ import jadx.core.utils.ErrorsCounter;
import
jadx.core.utils.Utils
;
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
{
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
ClassGen
parentGen
;
...
...
@@ -276,7 +266,7 @@ public class ClassGen {
private
static
List
<
MethodNode
>
sortMethodsByLine
(
List
<
MethodNode
>
methods
)
{
List
<
MethodNode
>
out
=
new
ArrayList
<>(
methods
);
Collections
.
sort
(
out
,
METHOD_LINE_COMPARATOR
);
out
.
sort
(
Comparator
.
comparingInt
(
LineAttrNode:
:
getSourceLine
)
);
return
out
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
View file @
f02b99a1
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.core.dex.attributes.AType
;
import
jadx.core.dex.instructions.args.LiteralArg
;
...
...
@@ -10,14 +18,6 @@ import jadx.core.dex.nodes.FieldNode;
import
jadx.core.dex.nodes.ResRefField
;
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
{
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
;
import
java.util.List
;
import
com.android.dex.Dex.Section
;
import
jadx.core.dex.attributes.nodes.SourceFileAttr
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
...
...
@@ -9,16 +13,8 @@ import jadx.core.dex.nodes.InsnNode;
import
jadx.core.dex.nodes.MethodNode
;
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
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
DebugInfoParser
.
class
);
private
static
final
int
DBG_END_SEQUENCE
=
0x00
;
private
static
final
int
DBG_ADVANCE_PC
=
0x01
;
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
;
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.List
;
import
com.android.dex.Dex.Section
;
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
{
private
static
final
int
ENCODED_BYTE
=
0x00
;
...
...
@@ -91,8 +91,10 @@ public class EncValueParser {
case
ENCODED_ANNOTATION:
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
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java
View file @
f02b99a1
package
jadx
.
core
.
dex
.
visitors
;
import
java.io.File
;
import
jadx.api.IJadxArgs
;
import
jadx.core.codegen.CodeWriter
;
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
{
private
final
File
dir
;
private
final
IJadxArgs
args
;
public
class
SaveCode
{
public
SaveCode
(
File
dir
,
IJadxArgs
args
)
{
this
.
args
=
args
;
this
.
dir
=
dir
;
}
@Override
public
boolean
visit
(
ClassNode
cls
)
throws
CodegenException
{
save
(
dir
,
args
,
cls
);
return
false
;
}
private
SaveCode
()
{}
public
static
void
save
(
File
dir
,
IJadxArgs
args
,
ClassNode
cls
)
{
CodeWriter
clsCode
=
cls
.
getCode
();
String
fileName
=
cls
.
getClassInfo
().
getFullPath
()
+
".java"
;
if
(
args
.
isFallbackMode
())
{
if
(
args
.
isFallbackMode
())
{
fileName
+=
".jadx"
;
}
clsCode
.
save
(
dir
,
fileName
);
...
...
jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java
View file @
f02b99a1
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.Collections
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
...
...
@@ -17,6 +9,13 @@ import java.util.Set;
import
org.slf4j.Logger
;
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
{
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
;
import
jadx.api.JadxDecompiler
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
jadx.api.JadxDecompiler
;
public
class
Utils
{
public
static
final
String
JADX_API_PACKAGE
=
JadxDecompiler
.
class
.
getPackage
().
getName
();
...
...
@@ -95,8 +95,4 @@ public class Utils {
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
;
import
java.util.List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.codegen.ClassGen
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.info.ClassInfo
;
...
...
@@ -7,17 +12,15 @@ import jadx.core.dex.nodes.ClassNode;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.dex.nodes.RootNode
;
import
java.util.List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* Android resources specific handlers
*/
public
class
AndroidResourcesUtils
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
AndroidResourcesUtils
.
class
);
private
AndroidResourcesUtils
()
{
}
public
static
ClassNode
searchAppResClass
(
RootNode
root
)
{
String
appPackage
=
root
.
getAppPackage
();
String
fullName
=
appPackage
!=
null
?
appPackage
+
".R"
:
"R"
;
...
...
@@ -49,7 +52,7 @@ public class AndroidResourcesUtils {
private
static
ClassNode
makeClass
(
RootNode
root
,
String
clsName
)
{
List
<
DexNode
>
dexNodes
=
root
.
getDexNodes
();
if
(
dexNodes
.
size
()
==
0
)
{
if
(
dexNodes
.
isEmpty
()
)
{
return
null
;
}
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>
*
*
Licensed under the Apache License, Version 2.0 (the "License");
*
you may not use this file except in compliance with the License.
*
You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
*
Unless required by applicable law or agreed to in writing, software
*
distributed under the License is distributed on an "AS IS" BASIS,
*
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
See the License for the specific language governing permissions and
*
limitations under the License.
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
<p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
<p>
* http://www.apache.org/licenses/LICENSE-2.0
*
<p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
jadx
.
core
.
utils
.
android
;
...
...
@@ -22,70 +22,70 @@ import java.io.IOException;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
abstract
public
class
DataInputDelegate
implements
DataInput
{
protected
final
DataInput
mDelegate
;
public
abstract
class
DataInputDelegate
implements
DataInput
{
protected
final
DataInput
mDelegate
;
public
DataInputDelegate
(
DataInput
delegate
)
{
this
.
mDelegate
=
delegate
;
}
public
DataInputDelegate
(
DataInput
delegate
)
{
this
.
mDelegate
=
delegate
;
}
public
int
skipBytes
(
int
n
)
throws
IOException
{
return
mDelegate
.
skipBytes
(
n
);
}
public
int
skipBytes
(
int
n
)
throws
IOException
{
return
mDelegate
.
skipBytes
(
n
);
}
public
int
readUnsignedShort
()
throws
IOException
{
return
mDelegate
.
readUnsignedShort
();
}
public
int
readUnsignedShort
()
throws
IOException
{
return
mDelegate
.
readUnsignedShort
();
}
public
int
readUnsignedByte
()
throws
IOException
{
return
mDelegate
.
readUnsignedByte
();
}
public
int
readUnsignedByte
()
throws
IOException
{
return
mDelegate
.
readUnsignedByte
();
}
public
String
readUTF
()
throws
IOException
{
return
mDelegate
.
readUTF
();
}
public
String
readUTF
()
throws
IOException
{
return
mDelegate
.
readUTF
();
}
public
short
readShort
()
throws
IOException
{
return
mDelegate
.
readShort
();
}
public
short
readShort
()
throws
IOException
{
return
mDelegate
.
readShort
();
}
public
long
readLong
()
throws
IOException
{
return
mDelegate
.
readLong
();
}
public
long
readLong
()
throws
IOException
{
return
mDelegate
.
readLong
();
}
public
String
readLine
()
throws
IOException
{
return
mDelegate
.
readLine
();
}
public
String
readLine
()
throws
IOException
{
return
mDelegate
.
readLine
();
}
public
int
readInt
()
throws
IOException
{
return
mDelegate
.
readInt
();
}
public
int
readInt
()
throws
IOException
{
return
mDelegate
.
readInt
();
}
public
void
readFully
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
mDelegate
.
readFully
(
b
,
off
,
len
);
}
public
void
readFully
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
mDelegate
.
readFully
(
b
,
off
,
len
);
}
public
void
readFully
(
byte
[]
b
)
throws
IOException
{
mDelegate
.
readFully
(
b
);
}
public
void
readFully
(
byte
[]
b
)
throws
IOException
{
mDelegate
.
readFully
(
b
);
}
public
float
readFloat
()
throws
IOException
{
return
mDelegate
.
readFloat
();
}
public
float
readFloat
()
throws
IOException
{
return
mDelegate
.
readFloat
();
}
public
double
readDouble
()
throws
IOException
{
return
mDelegate
.
readDouble
();
}
public
double
readDouble
()
throws
IOException
{
return
mDelegate
.
readDouble
();
}
public
char
readChar
()
throws
IOException
{
return
mDelegate
.
readChar
();
}
public
char
readChar
()
throws
IOException
{
return
mDelegate
.
readChar
();
}
public
byte
readByte
()
throws
IOException
{
return
mDelegate
.
readByte
();
}
public
byte
readByte
()
throws
IOException
{
return
mDelegate
.
readByte
();
}
public
boolean
readBoolean
()
throws
IOException
{
return
mDelegate
.
readBoolean
();
}
}
\ No newline at end of file
public
boolean
readBoolean
()
throws
IOException
{
return
mDelegate
.
readBoolean
();
}
}
jadx-core/src/main/java/jadx/core/utils/android/ExtDataInput.java
View file @
f02b99a1
/**
*
Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
*
Licensed under the Apache License, Version 2.0 (the "License");
*
you may not use this file except in compliance with the License.
*
You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
*
Unless required by applicable law or agreed to in writing, software
*
distributed under the License is distributed on an "AS IS" BASIS,
*
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
See the License for the specific language governing permissions and
*
limitations under the License.
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
<p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
<p>
* http://www.apache.org/licenses/LICENSE-2.0
*
<p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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>
*/
public
class
ExtDataInput
extends
DataInputDelegate
{
public
ExtDataInput
(
InputStream
in
)
{
this
((
DataInput
)
new
DataInputStream
(
in
));
}
public
ExtDataInput
(
DataInput
delegate
)
{
super
(
delegate
);
}
public
int
[]
readIntArray
(
int
length
)
throws
IOException
{
int
[]
array
=
new
int
[
length
];
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
array
[
i
]
=
readInt
();
}
return
array
;
}
public
void
skipInt
()
throws
IOException
{
skipBytes
(
4
);
}
public
void
skipCheckInt
(
int
expected
)
throws
IOException
{
int
got
=
readInt
();
if
(
got
!=
expected
)
{
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
}
}
public
void
skipCheckShort
(
short
expected
)
throws
IOException
{
short
got
=
readShort
();
if
(
got
!=
expected
)
{
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
}
}
public
void
skipCheckByte
(
byte
expected
)
throws
IOException
{
byte
got
=
readByte
();
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
)
{
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).
*/
public
final
int
skipBytes
(
int
n
)
throws
IOException
{
int
total
=
0
;
int
cur
=
0
;
while
((
total
<
n
)
&&
((
cur
=
(
int
)
super
.
skipBytes
(
n
-
total
))
>
0
))
{
total
+=
cur
;
}
return
total
;
}
public
String
readNullEndedString
(
int
length
,
boolean
fixed
)
throws
IOException
{
StringBuilder
string
=
new
StringBuilder
(
16
);
while
(
length
--
!=
0
)
{
short
ch
=
readShort
();
if
(
ch
==
0
)
{
break
;
}
string
.
append
((
char
)
ch
);
}
if
(
fixed
)
{
skipBytes
(
length
*
2
);
}
return
string
.
toString
();
}
}
\ No newline at end of file
public
ExtDataInput
(
InputStream
in
)
{
this
((
DataInput
)
new
DataInputStream
(
in
));
}
public
ExtDataInput
(
DataInput
delegate
)
{
super
(
delegate
);
}
public
int
[]
readIntArray
(
int
length
)
throws
IOException
{
int
[]
array
=
new
int
[
length
];
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
array
[
i
]
=
readInt
();
}
return
array
;
}
public
void
skipInt
()
throws
IOException
{
skipBytes
(
4
);
}
public
void
skipCheckInt
(
int
expected
)
throws
IOException
{
int
got
=
readInt
();
if
(
got
!=
expected
)
{
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
}
}
public
void
skipCheckShort
(
short
expected
)
throws
IOException
{
short
got
=
readShort
();
if
(
got
!=
expected
)
{
throw
new
IOException
(
String
.
format
(
"Expected: 0x%08x, got: 0x%08x"
,
expected
,
got
));
}
}
public
void
skipCheckByte
(
byte
expected
)
throws
IOException
{
byte
got
=
readByte
();
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
)
{
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).
*/
@Override
public
final
int
skipBytes
(
int
n
)
throws
IOException
{
int
total
=
0
;
int
cur
=
0
;
while
((
total
<
n
)
&&
((
cur
=
super
.
skipBytes
(
n
-
total
))
>
0
))
{
total
+=
cur
;
}
return
total
;
}
public
String
readNullEndedString
(
int
length
,
boolean
fixed
)
throws
IOException
{
StringBuilder
string
=
new
StringBuilder
(
16
);
while
(
length
--
!=
0
)
{
short
ch
=
readShort
();
if
(
ch
==
0
)
{
break
;
}
string
.
append
((
char
)
ch
);
}
if
(
fixed
)
{
skipBytes
(
length
*
2
);
}
return
string
.
toString
();
}
}
jadx-core/src/main/java/jadx/core/utils/android/Res9patchStreamDecoder.java
View file @
f02b99a1
/**
*
Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
*
Licensed under the Apache License, Version 2.0 (the "License");
*
you may not use this file except in compliance with the License.
*
You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
*
Unless required by applicable law or agreed to in writing, software
*
distributed under the License is distributed on an "AS IS" BASIS,
*
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
See the License for the specific language governing permissions and
*
limitations under the License.
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
<p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
<p>
* http://www.apache.org/licenses/LICENSE-2.0
*
<p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
jadx
.
core
.
utils
.
android
;
import
org.apache.commons.io.IOUtils
;
import
javax.imageio.ImageIO
;
import
java.awt.image.BufferedImage
;
import
java.io.ByteArrayInputStream
;
import
java.io.DataInput
;
...
...
@@ -25,7 +24,7 @@ import java.io.IOException;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
javax.imageio.ImageIO
;
import
org.apache.commons.io.IOUtils
;
import
jadx.core.utils.exceptions.JadxException
;
...
...
@@ -34,105 +33,107 @@ import jadx.core.utils.exceptions.JadxException;
*/
public
class
Res9patchStreamDecoder
{
public
void
decode
(
InputStream
in
,
OutputStream
out
)
throws
JadxException
{
try
{
byte
[]
data
=
IOUtils
.
toByteArray
(
in
);
BufferedImage
im
=
ImageIO
.
read
(
new
ByteArrayInputStream
(
data
));
int
w
=
im
.
getWidth
(),
h
=
im
.
getHeight
();
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
);
drawVLine
(
im2
,
w
+
1
,
np
.
padTop
+
1
,
h
-
np
.
padBottom
);
int
[]
xDivs
=
np
.
xDivs
;
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
)
{
drawVLine
(
im2
,
0
,
yDivs
[
i
]
+
1
,
yDivs
[
i
+
1
]);
}
ImageIO
.
write
(
im2
,
"png"
,
out
);
}
catch
(
IOException
|
NullPointerException
ex
)
{
throw
new
JadxException
(
ex
.
toString
());
}
}
private
NinePatch
getNinePatch
(
byte
[]
data
)
throws
JadxException
,
IOException
{
ExtDataInput
di
=
new
ExtDataInput
(
new
ByteArrayInputStream
(
data
));
find9patchChunk
(
di
);
return
NinePatch
.
decode
(
di
);
}
private
void
find9patchChunk
(
DataInput
di
)
throws
JadxException
,
IOException
{
di
.
skipBytes
(
8
);
while
(
true
)
{
int
size
;
try
{
size
=
di
.
readInt
();
}
catch
(
IOException
ex
)
{
throw
new
JadxException
(
"Cant find nine patch chunk"
,
ex
);
}
if
(
di
.
readInt
()
==
NP_CHUNK_TYPE
)
{
return
;
}
di
.
skipBytes
(
size
+
4
);
}
}
private
void
drawHLine
(
BufferedImage
im
,
int
y
,
int
x1
,
int
x2
)
{
for
(
int
x
=
x1
;
x
<=
x2
;
x
++)
{
im
.
setRGB
(
x
,
y
,
NP_COLOR
);
}
}
private
void
drawVLine
(
BufferedImage
im
,
int
x
,
int
y1
,
int
y2
)
{
for
(
int
y
=
y1
;
y
<=
y2
;
y
++)
{
im
.
setRGB
(
x
,
y
,
NP_COLOR
);
}
}
private
static
final
int
NP_CHUNK_TYPE
=
0x6e705463
;
// npTc
private
static
final
int
NP_COLOR
=
0xff000000
;
private
static
class
NinePatch
{
public
final
int
padLeft
,
padRight
,
padTop
,
padBottom
;
public
final
int
[]
xDivs
,
yDivs
;
public
NinePatch
(
int
padLeft
,
int
padRight
,
int
padTop
,
int
padBottom
,
int
[]
xDivs
,
int
[]
yDivs
)
{
this
.
padLeft
=
padLeft
;
this
.
padRight
=
padRight
;
this
.
padTop
=
padTop
;
this
.
padBottom
=
padBottom
;
this
.
xDivs
=
xDivs
;
this
.
yDivs
=
yDivs
;
}
public
static
NinePatch
decode
(
ExtDataInput
di
)
throws
IOException
{
di
.
skipBytes
(
1
);
byte
numXDivs
=
di
.
readByte
();
byte
numYDivs
=
di
.
readByte
();
di
.
skipBytes
(
1
);
di
.
skipBytes
(
8
);
int
padLeft
=
di
.
readInt
();
int
padRight
=
di
.
readInt
();
int
padTop
=
di
.
readInt
();
int
padBottom
=
di
.
readInt
();
di
.
skipBytes
(
4
);
int
[]
xDivs
=
di
.
readIntArray
(
numXDivs
);
int
[]
yDivs
=
di
.
readIntArray
(
numYDivs
);
return
new
NinePatch
(
padLeft
,
padRight
,
padTop
,
padBottom
,
xDivs
,
yDivs
);
}
}
}
\ No newline at end of file
public
void
decode
(
InputStream
in
,
OutputStream
out
)
throws
JadxException
{
try
{
byte
[]
data
=
IOUtils
.
toByteArray
(
in
);
BufferedImage
im
=
ImageIO
.
read
(
new
ByteArrayInputStream
(
data
));
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
);
NinePatch
np
=
getNinePatch
(
data
);
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
)
{
drawHLine
(
im2
,
0
,
xDivs
[
i
]
+
1
,
xDivs
[
i
+
1
]);
}
int
[]
yDivs
=
np
.
yDivs
;
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
)
{
throw
new
JadxException
(
ex
.
toString
());
}
}
private
NinePatch
getNinePatch
(
byte
[]
data
)
throws
JadxException
,
IOException
{
ExtDataInput
di
=
new
ExtDataInput
(
new
ByteArrayInputStream
(
data
));
find9patchChunk
(
di
);
return
NinePatch
.
decode
(
di
);
}
private
void
find9patchChunk
(
DataInput
di
)
throws
JadxException
,
IOException
{
di
.
skipBytes
(
8
);
while
(
true
)
{
int
size
;
try
{
size
=
di
.
readInt
();
}
catch
(
IOException
ex
)
{
throw
new
JadxException
(
"Cant find nine patch chunk"
,
ex
);
}
if
(
di
.
readInt
()
==
NP_CHUNK_TYPE
)
{
return
;
}
di
.
skipBytes
(
size
+
4
);
}
}
private
void
drawHLine
(
BufferedImage
im
,
int
y
,
int
x1
,
int
x2
)
{
for
(
int
x
=
x1
;
x
<=
x2
;
x
++)
{
im
.
setRGB
(
x
,
y
,
NP_COLOR
);
}
}
private
void
drawVLine
(
BufferedImage
im
,
int
x
,
int
y1
,
int
y2
)
{
for
(
int
y
=
y1
;
y
<=
y2
;
y
++)
{
im
.
setRGB
(
x
,
y
,
NP_COLOR
);
}
}
private
static
final
int
NP_CHUNK_TYPE
=
0x6e705463
;
// npTc
private
static
final
int
NP_COLOR
=
0xff000000
;
private
static
class
NinePatch
{
public
final
int
padLeft
;
public
final
int
padRight
;
public
final
int
padTop
;
public
final
int
padBottom
;
public
final
int
[]
xDivs
;
public
final
int
[]
yDivs
;
public
NinePatch
(
int
padLeft
,
int
padRight
,
int
padTop
,
int
padBottom
,
int
[]
xDivs
,
int
[]
yDivs
)
{
this
.
padLeft
=
padLeft
;
this
.
padRight
=
padRight
;
this
.
padTop
=
padTop
;
this
.
padBottom
=
padBottom
;
this
.
xDivs
=
xDivs
;
this
.
yDivs
=
yDivs
;
}
public
static
NinePatch
decode
(
ExtDataInput
di
)
throws
IOException
{
di
.
skipBytes
(
1
);
byte
numXDivs
=
di
.
readByte
();
byte
numYDivs
=
di
.
readByte
();
di
.
skipBytes
(
1
);
di
.
skipBytes
(
8
);
int
padLeft
=
di
.
readInt
();
int
padRight
=
di
.
readInt
();
int
padTop
=
di
.
readInt
();
int
padBottom
=
di
.
readInt
();
di
.
skipBytes
(
4
);
int
[]
xDivs
=
di
.
readIntArray
(
numXDivs
);
int
[]
yDivs
=
di
.
readIntArray
(
numYDivs
);
return
new
NinePatch
(
padLeft
,
padRight
,
padTop
,
padBottom
,
xDivs
,
yDivs
);
}
}
}
jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
View file @
f02b99a1
...
...
@@ -7,6 +7,7 @@ import java.io.FileInputStream;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.nio.file.Files
;
import
java.util.ArrayList
;
import
java.util.Enumeration
;
import
java.util.List
;
...
...
@@ -179,20 +180,10 @@ public class FileUtils {
}
private
static
boolean
isZipFileCanBeOpen
(
File
file
)
{
ZipFile
zipFile
=
null
;
try
{
zipFile
=
new
ZipFile
(
file
);
try
(
ZipFile
zipFile
=
new
ZipFile
(
file
))
{
return
zipFile
.
entries
().
hasMoreElements
();
}
catch
(
Exception
e
)
{
return
false
;
}
finally
{
if
(
zipFile
!=
null
)
{
try
{
zipFile
.
close
();
}
catch
(
IOException
e
)
{
LOG
.
error
(
e
.
getMessage
());
}
}
}
}
...
...
@@ -214,8 +205,8 @@ public class FileUtils {
LOG
.
debug
(
"Failed to detect filesystem case-sensitivity by file creation"
,
e
);
}
finally
{
try
{
caseCheckUpper
.
delete
(
);
caseCheckLow
.
delete
(
);
Files
.
deleteIfExists
(
caseCheckUpper
.
toPath
()
);
Files
.
deleteIfExists
(
caseCheckLow
.
toPath
()
);
}
catch
(
Exception
e
)
{
// ignore
}
...
...
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
View file @
f02b99a1
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.FileOutputStream
;
import
java.io.IOException
;
...
...
@@ -16,13 +11,16 @@ import java.util.jar.JarOutputStream;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipFile
;
import
com.android.dex.Dex
;
import
org.apache.commons.io.IOUtils
;
import
org.slf4j.Logger
;
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
.
isZipDexFile
;
...
...
@@ -30,7 +28,7 @@ public class InputFile {
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
InputFile
.
class
);
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
{
InputFile
inputFile
=
new
InputFile
(
file
);
...
...
@@ -38,7 +36,7 @@ public class InputFile {
list
.
add
(
inputFile
);
}
private
InputFile
(
File
file
)
throws
IOException
,
DecodeException
{
private
InputFile
(
File
file
)
throws
IOException
{
if
(!
file
.
exists
())
{
throw
new
IOException
(
"File not found: "
+
file
.
getAbsolutePath
());
}
...
...
@@ -80,11 +78,11 @@ public class InputFile {
throw
new
DecodeException
(
"Unsupported input file format: "
+
file
);
}
private
void
addDexFile
(
Dex
dexBuf
)
throws
IOException
{
private
void
addDexFile
(
Dex
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
));
}
...
...
@@ -92,44 +90,41 @@ public class InputFile {
int
index
=
0
;
try
(
ZipFile
zf
=
new
ZipFile
(
file
))
{
// 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
;
for
(
Enumeration
<?
extends
ZipEntry
>
e
=
zf
.
entries
();
e
.
hasMoreElements
();
)
{
ZipEntry
entry
=
e
.
nextElement
();
String
entryName
=
entry
.
getName
();
// security check
if
(!
ZipSecurity
.
isValidZipEntry
(
entry
))
{
if
(!
ZipSecurity
.
isValidZipEntry
(
entry
))
{
continue
;
}
InputStream
inputStream
=
zf
.
getInputStream
(
entry
);
try
{
String
entryName
=
entry
.
getName
(
);
try
(
InputStream
inputStream
=
zf
.
getInputStream
(
entry
))
{
if
((
entryName
.
startsWith
(
"classes"
)
&&
entryName
.
endsWith
(
ext
))
||
entryName
.
endsWith
(
instantRunDexSuffix
))
{
if
(
ext
.
equals
(
".dex"
))
{
index
++;
addDexFile
(
entryName
,
new
Dex
(
inputStream
));
}
else
if
(
ext
.
equals
(
".jar"
))
{
index
++;
File
jarFile
=
FileUtils
.
createTempFile
(
entryName
);
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
);
try
{
IOUtils
.
copy
(
inputStream
,
fos
);
}
finally
{
close
(
fos
);
}
addDexFile
(
entryName
,
loadFromJar
(
jarFile
));
}
else
{
throw
new
JadxRuntimeException
(
"Unexpected extension in zip: "
+
ext
);
switch
(
ext
)
{
case
".dex"
:
index
++;
addDexFile
(
entryName
,
new
Dex
(
inputStream
));
break
;
case
".jar"
:
index
++;
File
jarFile
=
FileUtils
.
createTempFile
(
entryName
);
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
))
{
IOUtils
.
copy
(
inputStream
,
fos
);
}
addDexFile
(
entryName
,
loadFromJar
(
jarFile
));
break
;
default
:
throw
new
JadxRuntimeException
(
"Unexpected extension in zip: "
+
ext
);
}
}
else
if
(
entryName
.
equals
(
"instant-run.zip"
)
&&
ext
.
equals
(
".dex"
))
{
File
jarFile
=
FileUtils
.
createTempFile
(
"instant-run.zip"
);
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
);
try
{
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
))
{
IOUtils
.
copy
(
inputStream
,
fos
);
}
finally
{
close
(
fos
);
}
InputFile
tempFile
=
new
InputFile
(
jarFile
);
tempFile
.
loadFromZip
(
ext
);
...
...
@@ -139,8 +134,6 @@ public class InputFile {
this
.
dexFiles
.
addAll
(
dexFiles
);
}
}
}
finally
{
close
(
inputStream
);
}
}
}
...
...
@@ -156,7 +149,7 @@ public class InputFile {
throw
new
JadxException
(
"Empty dx output"
);
}
return
new
Dex
(
ba
);
}
catch
(
Throwable
e
)
{
}
catch
(
Exception
e
)
{
throw
new
DecodeException
(
"java class to dex conversion error:\n "
+
e
.
getMessage
(),
e
);
}
finally
{
if
(
j2d
.
isError
())
{
...
...
@@ -167,19 +160,12 @@ public class InputFile {
private
static
Dex
loadFromClassFile
(
File
file
)
throws
IOException
,
DecodeException
{
File
outFile
=
FileUtils
.
createTempFile
(
"cls.jar"
);
FileOutputStream
out
=
null
;
JarOutputStream
jo
=
null
;
try
{
out
=
new
FileOutputStream
(
outFile
);
jo
=
new
JarOutputStream
(
out
);
try
(
JarOutputStream
jo
=
new
JarOutputStream
(
new
FileOutputStream
(
outFile
)))
{
String
clsName
=
AsmUtils
.
getNameFromClassFile
(
file
);
if
(
clsName
==
null
||
ZipSecurity
.
isValidZipEntryName
(
clsName
))
{
throw
new
IOException
(
"Can't read class name from file: "
+
file
);
}
FileUtils
.
addFileToJar
(
jo
,
file
,
clsName
+
".class"
);
}
finally
{
close
(
jo
);
close
(
out
);
}
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;
import
com.android.dx.command.dexer.DxContext
;
import
com.android.dx.command.dexer.Main
;
import
com.android.dx.command.dexer.Main.Arguments
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.utils.exceptions.JadxException
;
public
class
JavaToDex
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
JavaToDex
.
class
);
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
)
{
super
(
context
);
outName
=
dexFile
;
...
...
jadx-core/src/main/java/jadx/core/utils/files/ZipSecurity.java
View file @
f02b99a1
...
...
@@ -8,55 +8,55 @@ import org.slf4j.LoggerFactory;
public
class
ZipSecurity
{
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
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
// and prevents cases like "../classes.dex", to limit output only to the specified directory
public
static
boolean
isValidZipEntryName
(
String
entryName
)
{
try
{
File
currentPath
=
new
File
(
"."
).
getCanonicalFile
();
File
canonical
=
new
File
(
currentPath
,
entryName
).
getCanonicalFile
();
if
(
isInSubDirectory
(
currentPath
,
canonical
))
{
if
(
isInSubDirectory
(
currentPath
,
canonical
))
{
return
true
;
}
LOG
.
error
(
"Path traversal attack detected, invalid name: {}"
,
entryName
);
return
false
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Path traversal attack detected, invalid name: {}"
,
entryName
);
return
false
;
}
}
public
static
boolean
isZipBomb
(
ZipEntry
entry
)
{
long
compressedSize
=
entry
.
getCompressedSize
();
long
compressedSize
=
entry
.
getCompressedSize
();
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 {}"
,
compressedSize
,
uncompressedSize
,
entry
.
getName
());
return
true
;
}
if
(
compressedSize
*
MAX_SIZE_DIFF
<
uncompressedSize
)
{
LOG
.
error
(
"Zip bom
p
attack detected, invalid sizes: compressed {}, uncompressed {}, name {}"
,
if
(
compressedSize
*
MAX_SIZE_DIFF
<
uncompressedSize
)
{
LOG
.
error
(
"Zip bom
b
attack detected, invalid sizes: compressed {}, uncompressed {}, name {}"
,
compressedSize
,
uncompressedSize
,
entry
.
getName
());
return
true
;
}
return
false
;
}
public
static
boolean
isValidZipEntry
(
ZipEntry
entry
)
{
return
isValidZipEntryName
(
entry
.
getName
())
&&
!
isZipBomb
(
entry
);
...
...
jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
View file @
f02b99a1
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.InputStream
;
import
java.lang.reflect.Field
;
...
...
@@ -18,6 +9,16 @@ import java.util.Map;
import
org.slf4j.Logger
;
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:
Don't die when error occurs
Check error cases, maybe checked const values are not always the same
...
...
@@ -34,10 +35,12 @@ public class BinaryXMLParser extends CommonBinaryParser {
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
BinaryXMLParser
.
class
);
private
static
final
String
ANDROID_R_STYLE_CLS
=
"android.R$style"
;
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
<
String
,
String
>
nsMap
=
new
HashMap
<>();
private
CodeWriter
writer
;
private
String
[]
strings
;
private
String
currentTag
=
"ERROR"
;
...
...
@@ -48,14 +51,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
public
BinaryXMLParser
(
RootNode
root
)
{
try
{
try
{
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
);
}
readAndroidRStyleClass
();
// add application constants
ConstStorage
constStorage
=
root
.
getConstValues
();
Map
<
Object
,
FieldNode
>
constFields
=
constStorage
.
getGlobalConstFields
();
...
...
@@ -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
{
is
=
new
ParserStream
(
inputStream
);
if
(!
isBinaryXml
())
{
...
...
@@ -186,13 +193,11 @@ public class BinaryXMLParser extends CommonBinaryParser {
int
strIndex
=
is
.
readInt32
();
String
str
=
strings
[
strIndex
];
writer
.
startLine
().
addIndent
();
writer
.
attachSourceLine
(
lineNumber
);
writer
.
add
(
StringUtils
.
escapeXML
(
str
.
trim
()));
//TODO: what's this for?
/*writer.startLine().addIndent();
writer.attachSourceLine(lineNumber);
writer.add(StringUtils.escapeXML(str.trim()));*/
int
size
=
is
.
readInt16
();
long
size
=
is
.
readInt16
();
is
.
skip
(
size
-
2
);
}
...
...
@@ -236,7 +241,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
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
++)
{
parseAttribute
(
i
,
attrNewLine
);
}
...
...
@@ -284,7 +289,6 @@ public class BinaryXMLParser extends CommonBinaryParser {
if
(
attributeNS
!=
-
1
)
{
writer
.
add
(
nsMap
.
get
(
strings
[
attributeNS
])).
add
(
':'
);
}
LOG
.
debug
(
"decodeAttribute: "
+
attributeNS
+
" "
+
name
);
writer
.
add
(
"style/"
).
add
(
name
.
replaceAll
(
"_"
,
"."
));
}
else
{
FieldNode
field
=
localStyleMap
.
get
(
attrValData
);
...
...
@@ -304,7 +308,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
}
writer
.
add
(
resName
);
}
else
{
resName
=
ValuesParser
.
androidResMap
.
get
(
attrValData
);
resName
=
ValuesParser
.
getAndroidResMap
()
.
get
(
attrValData
);
if
(
resName
!=
null
)
{
writer
.
add
(
"@android:"
).
add
(
resName
);
}
else
if
(
attrValData
==
0
)
{
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ManifestAttributes.java
View file @
f02b99a1
...
...
@@ -56,7 +56,7 @@ public class ManifestAttributes {
try
{
instance
=
new
ManifestAttributes
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
);
LOG
.
error
(
"Failed to create ManifestAttributes"
,
e
);
}
}
return
instance
;
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ResContainer.java
View file @
f02b99a1
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
java.awt.image.BufferedImage
;
import
java.io.ByteArrayInputStream
;
...
...
@@ -17,9 +12,17 @@ import java.util.List;
import
org.jetbrains.annotations.NotNull
;
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
>
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ResContainer
.
class
);
private
final
String
name
;
private
final
List
<
ResContainer
>
subFiles
;
...
...
@@ -34,21 +37,21 @@ public class ResContainer implements Comparable<ResContainer> {
}
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
;
return
resContainer
;
}
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
;
if
(
name
.
endsWith
(
".9.png"
))
{
Res9patchStreamDecoder
decoder
=
new
Res9patchStreamDecoder
();
ByteArrayOutputStream
os
=
new
ByteArrayOutputStream
();
try
{
decoder
.
decode
(
content
,
os
);
}
catch
(
Jadx
Exception
e
)
{
e
.
printStackTrace
(
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to decode 9-patch png image"
,
e
);
}
newContent
=
new
ByteArrayInputStream
(
os
.
toByteArray
());
}
...
...
@@ -61,7 +64,7 @@ public class ResContainer implements Comparable<ResContainer> {
}
public
static
ResContainer
multiFile
(
String
name
)
{
return
new
ResContainer
(
name
,
new
ArrayList
<
ResContainer
>());
return
new
ResContainer
(
name
,
new
ArrayList
<>());
}
public
String
getName
()
{
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ResourceStorage.java
View file @
f02b99a1
package
jadx
.
core
.
xmlgen
;
import
jadx.core.utils.Utils
;
import
jadx.core.xmlgen.entry.ResourceEntry
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
...
...
@@ -11,14 +8,9 @@ import java.util.HashMap;
import
java.util.List
;
import
java.util.Map
;
public
class
ResourceStorage
{
import
jadx.core.xmlgen.entry.ResourceEntry
;
private
static
final
Comparator
<
ResourceEntry
>
COMPARATOR
=
new
Comparator
<
ResourceEntry
>()
{
@Override
public
int
compare
(
ResourceEntry
a
,
ResourceEntry
b
)
{
return
Utils
.
compare
(
a
.
getId
(),
b
.
getId
());
}
};
public
class
ResourceStorage
{
private
final
List
<
ResourceEntry
>
list
=
new
ArrayList
<>();
private
String
appPackage
;
...
...
@@ -32,12 +24,12 @@ public class ResourceStorage {
}
public
void
finish
()
{
Collections
.
sort
(
list
,
COMPARATOR
);
list
.
sort
(
Comparator
.
comparingInt
(
ResourceEntry:
:
getId
)
);
}
public
ResourceEntry
getByRef
(
int
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
)
{
return
null
;
}
...
...
jadx-core/src/main/java/jadx/core/xmlgen/XmlSecurity.java
View file @
f02b99a1
...
...
@@ -4,23 +4,24 @@ import javax.xml.parsers.DocumentBuilderFactory;
import
javax.xml.parsers.ParserConfigurationException
;
public
class
XmlSecurity
{
private
static
DocumentBuilderFactory
secureDbf
=
null
;
private
XmlSecurity
()
{}
public
static
DocumentBuilderFactory
getSecureDbf
()
throws
ParserConfigurationException
{
synchronized
(
XmlSecurity
.
class
)
{
if
(
secureDbf
==
null
)
{
synchronized
(
XmlSecurity
.
class
)
{
if
(
secureDbf
==
null
)
{
secureDbf
=
DocumentBuilderFactory
.
newInstance
();
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://xml.org/sax/features/external-general-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
.
setXIncludeAware
(
false
);
secureDbf
.
setExpandEntityReferences
(
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://apache.org/xml/features/dom/create-entity-ref-nodes"
,
false
);
secureDbf
.
setXIncludeAware
(
false
);
secureDbf
.
setExpandEntityReferences
(
false
);
}
}
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;
public
class
ValuesParser
extends
ParserConstants
{
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
Map
<
Integer
,
String
>
resMap
;
public
static
String
[]
androidStrings
;
public
static
Map
<
Integer
,
String
>
androidResMap
;
public
ValuesParser
(
String
[]
strings
,
Map
<
Integer
,
String
>
resMap
)
{
this
.
strings
=
strings
;
this
.
resMap
=
resMap
;
...
...
@@ -31,14 +31,14 @@ public class ValuesParser extends ParserConstants {
if
(
androidStrings
==
null
&&
androidResMap
==
null
)
{
try
{
decodeAndroid
();
}
catch
(
IO
Exception
e
)
{
e
.
printStackTrace
(
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to decode Android Resource file"
,
e
);
}
}
}
private
void
decodeAndroid
()
throws
IOException
{
InputStream
inputStream
=
new
BufferedInputStream
(
getClass
()
.
getResourceAsStream
(
"/resources.arsc"
));
private
static
void
decodeAndroid
()
throws
IOException
{
InputStream
inputStream
=
new
BufferedInputStream
(
ValuesParser
.
class
.
getResourceAsStream
(
"/resources.arsc"
));
ResTableParser
androidParser
=
new
ResTableParser
();
androidParser
.
decode
(
inputStream
);
androidStrings
=
androidParser
.
getStrings
();
...
...
@@ -212,4 +212,8 @@ public class ValuesParser extends ParserConstants {
f
.
setMinimumIntegerDigits
(
1
);
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;
import
java.util.List
;
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.gui.JadxWrapper
;
import
jadx.gui.treemodel.JResource.JResType
;
import
jadx.gui.utils.Utils
;
import
jadx.gui.treemodel.JResource.JResType
;
import
jadx.gui.utils.Utils
;
public
class
JRoot
extends
JNode
{
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;
import
javax.swing.table.TableColumn
;
import
javax.swing.table.TableColumnModel
;
import
java.awt.*
;
import
java.awt.event.ActionEvent
;
import
java.awt.event.ActionListener
;
import
java.awt.event.KeyAdapter
;
import
java.awt.event.KeyEvent
;
import
java.awt.event.MouseAdapter
;
...
...
@@ -90,12 +88,7 @@ public abstract class CommonSearchDialog extends JDialog {
addWindowListener
(
new
WindowAdapter
()
{
@Override
public
void
windowOpened
(
WindowEvent
e
)
{
SwingUtilities
.
invokeLater
(
new
Runnable
()
{
@Override
public
void
run
()
{
openInit
();
}
});
SwingUtilities
.
invokeLater
(
CommonSearchDialog
.
this
::
openInit
);
}
});
}
...
...
@@ -119,12 +112,7 @@ public abstract class CommonSearchDialog extends JDialog {
protected
void
initCommon
()
{
KeyStroke
stroke
=
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_ESCAPE
,
0
);
getRootPane
().
registerKeyboardAction
(
new
ActionListener
()
{
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
dispose
();
}
},
stroke
,
JComponent
.
WHEN_IN_FOCUSED_WINDOW
);
getRootPane
().
registerKeyboardAction
(
e
->
dispose
(),
stroke
,
JComponent
.
WHEN_IN_FOCUSED_WINDOW
);
}
@NotNull
...
...
@@ -132,17 +120,9 @@ public abstract class CommonSearchDialog extends JDialog {
progressPane
=
new
ProgressPanel
(
mainWindow
,
false
);
JButton
cancelButton
=
new
JButton
(
NLS
.
str
(
"search_dialog.cancel"
));
cancelButton
.
addActionListener
(
new
ActionListener
()
{
public
void
actionPerformed
(
ActionEvent
event
)
{
dispose
();
}
});
cancelButton
.
addActionListener
(
event
->
dispose
());
JButton
openBtn
=
new
JButton
(
NLS
.
str
(
"search_dialog.open"
));
openBtn
.
addActionListener
(
new
ActionListener
()
{
public
void
actionPerformed
(
ActionEvent
event
)
{
openSelectedItem
();
}
});
openBtn
.
addActionListener
(
event
->
openSelectedItem
());
getRootPane
().
setDefaultButton
(
openBtn
);
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