mirror of
https://github.com/skylot/jadx.git
synced 2024-11-26 22:20:50 +00:00
fix: disable usage of JDK Unsafe class in GSON (#2341)
Some checks failed
Build Artifacts / build (push) Has been cancelled
Build Artifacts / build-win-bundle (push) Has been cancelled
Build Test / tests (ubuntu-latest) (push) Has been cancelled
Build Test / tests (windows-latest) (push) Has been cancelled
CodeQL / Analyze (java) (push) Has been cancelled
Some checks failed
Build Artifacts / build (push) Has been cancelled
Build Artifacts / build-win-bundle (push) Has been cancelled
Build Test / tests (ubuntu-latest) (push) Has been cancelled
Build Test / tests (windows-latest) (push) Has been cancelled
CodeQL / Analyze (java) (push) Has been cancelled
This commit is contained in:
parent
60dcdc7096
commit
1e1036c049
@ -9,7 +9,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import jadx.api.ICodeInfo;
|
||||
import jadx.api.ICodeWriter;
|
||||
@ -32,13 +31,13 @@ import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.GsonUtils;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
public class JsonCodeGen {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
private static final Gson GSON = GsonUtils.defaultGsonBuilder()
|
||||
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES)
|
||||
.disableHtmlEscaping()
|
||||
.create();
|
||||
|
@ -11,7 +11,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.core.codegen.json.mapping.JsonClsMapping;
|
||||
@ -24,14 +23,14 @@ import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.GsonUtils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
public class JsonMappingGen {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JsonMappingGen.class);
|
||||
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
private static final Gson GSON = GsonUtils.defaultGsonBuilder()
|
||||
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES)
|
||||
.disableHtmlEscaping()
|
||||
.create();
|
||||
|
@ -2,6 +2,9 @@ package jadx.core.utils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.InstanceCreator;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
@ -11,11 +14,27 @@ import com.google.gson.JsonSerializer;
|
||||
|
||||
public class GsonUtils {
|
||||
|
||||
public static Gson buildGson() {
|
||||
return defaultGsonBuilder().create();
|
||||
}
|
||||
|
||||
public static GsonBuilder defaultGsonBuilder() {
|
||||
return new GsonBuilder()
|
||||
.disableJdkUnsafe()
|
||||
.setPrettyPrinting();
|
||||
}
|
||||
|
||||
public static void fillObjectFromJsonString(GsonBuilder builder, Object obj, String jsonStr) {
|
||||
Class<?> type = obj.getClass();
|
||||
Gson gson = builder.registerTypeAdapter(type, (InstanceCreator<?>) t -> obj).create();
|
||||
gson.fromJson(jsonStr, type);
|
||||
}
|
||||
|
||||
public static <T> InterfaceReplace<T> interfaceReplace(Class<T> replaceCls) {
|
||||
return new InterfaceReplace<>(replaceCls);
|
||||
}
|
||||
|
||||
private static final class InterfaceReplace<T> implements JsonSerializer<T>, JsonDeserializer<T> {
|
||||
public static final class InterfaceReplace<T> implements JsonSerializer<T>, JsonDeserializer<T> {
|
||||
private final Class<T> replaceCls;
|
||||
|
||||
private InterfaceReplace(Class<T> replaceCls) {
|
||||
|
@ -141,10 +141,8 @@ runtime {
|
||||
"java.desktop",
|
||||
"java.naming",
|
||||
"java.xml",
|
||||
// needed for "https" protocol to get plugins and updates
|
||||
// needed for "https" protocol to download plugins and updates
|
||||
"jdk.crypto.cryptoki",
|
||||
// add Unsafe class, used by GSON
|
||||
"jdk.unsupported",
|
||||
)
|
||||
jpackage {
|
||||
imageOptions = listOf("--icon", "$projectDir/src/main/resources/logos/jadx-logo.ico")
|
||||
|
@ -19,10 +19,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import jadx.api.plugins.utils.CommonFileUtils;
|
||||
import jadx.core.utils.GsonUtils;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
@ -34,7 +34,7 @@ import jadx.gui.utils.files.JadxFiles;
|
||||
public class CacheManager {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CacheManager.class);
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Gson GSON = GsonUtils.buildGson();
|
||||
private static final Type CACHES_TYPE = new TypeToken<List<CacheEntry>>() {
|
||||
}.getType();
|
||||
|
||||
|
@ -22,17 +22,18 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.gui.device.debugger.smali.Smali;
|
||||
import jadx.gui.treemodel.JClass;
|
||||
|
||||
import static jadx.core.utils.GsonUtils.buildGson;
|
||||
|
||||
public class BreakpointManager {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BreakpointManager.class);
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Gson GSON = buildGson();
|
||||
private static final Type TYPE_TOKEN = new TypeToken<Map<String, List<FileBreakpoint>>>() {
|
||||
}.getType();
|
||||
|
||||
@ -159,9 +160,13 @@ public class BreakpointManager {
|
||||
}
|
||||
|
||||
protected static class FileBreakpoint {
|
||||
final String cls;
|
||||
final String mth;
|
||||
final long codeOffset;
|
||||
public String cls;
|
||||
public String mth;
|
||||
public long codeOffset;
|
||||
|
||||
public FileBreakpoint() {
|
||||
// needed for JSON deserialization
|
||||
}
|
||||
|
||||
private FileBreakpoint(String cls, String mth, long codeOffset) {
|
||||
this.cls = cls;
|
||||
|
@ -12,11 +12,9 @@ import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import jadx.api.ICodeInfo;
|
||||
import jadx.api.impl.SimpleCodeInfo;
|
||||
import jadx.core.utils.GsonUtils;
|
||||
import jadx.gui.treemodel.JClass;
|
||||
import jadx.gui.treemodel.JNode;
|
||||
import jadx.gui.ui.panel.ContentPanel;
|
||||
@ -30,8 +28,6 @@ public class QuarkReportNode extends JNode {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(QuarkReportNode.class);
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().create();
|
||||
|
||||
private static final ImageIcon ICON = UiUtils.openSvgIcon("ui/quark");
|
||||
|
||||
private final Path reportFile;
|
||||
@ -62,7 +58,7 @@ public class QuarkReportNode extends JNode {
|
||||
try {
|
||||
QuarkReportData data;
|
||||
try (BufferedReader reader = Files.newBufferedReader(reportFile)) {
|
||||
data = GSON.fromJson(reader, QuarkReportData.class);
|
||||
data = GsonUtils.buildGson().fromJson(reader, QuarkReportData.class);
|
||||
}
|
||||
data.validate();
|
||||
return new QuarkReportPanel(tabbedPane, this, data);
|
||||
|
@ -21,7 +21,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.data.ICodeComment;
|
||||
@ -34,7 +33,6 @@ import jadx.api.data.impl.JadxCodeRef;
|
||||
import jadx.api.data.impl.JadxCodeRename;
|
||||
import jadx.api.data.impl.JadxNodeRef;
|
||||
import jadx.api.plugins.utils.CommonFileUtils;
|
||||
import jadx.core.utils.GsonUtils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
import jadx.gui.cache.manager.CacheManager;
|
||||
@ -44,6 +42,9 @@ import jadx.gui.ui.MainWindow;
|
||||
import jadx.gui.ui.codearea.EditorViewState;
|
||||
import jadx.gui.utils.RelativePathTypeAdapter;
|
||||
|
||||
import static jadx.core.utils.GsonUtils.defaultGsonBuilder;
|
||||
import static jadx.core.utils.GsonUtils.interfaceReplace;
|
||||
|
||||
public class JadxProject {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JadxProject.class);
|
||||
|
||||
@ -335,13 +336,12 @@ public class JadxProject {
|
||||
}
|
||||
|
||||
private static Gson buildGson(Path basePath) {
|
||||
return new GsonBuilder()
|
||||
return defaultGsonBuilder()
|
||||
.registerTypeHierarchyAdapter(Path.class, new RelativePathTypeAdapter(basePath))
|
||||
.registerTypeAdapter(ICodeComment.class, GsonUtils.interfaceReplace(JadxCodeComment.class))
|
||||
.registerTypeAdapter(ICodeRename.class, GsonUtils.interfaceReplace(JadxCodeRename.class))
|
||||
.registerTypeAdapter(IJavaNodeRef.class, GsonUtils.interfaceReplace(JadxNodeRef.class))
|
||||
.registerTypeAdapter(IJavaCodeRef.class, GsonUtils.interfaceReplace(JadxCodeRef.class))
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ICodeComment.class, interfaceReplace(JadxCodeComment.class))
|
||||
.registerTypeAdapter(ICodeRename.class, interfaceReplace(JadxCodeRename.class))
|
||||
.registerTypeAdapter(IJavaNodeRef.class, interfaceReplace(JadxNodeRef.class))
|
||||
.registerTypeAdapter(IJavaCodeRef.class, interfaceReplace(JadxCodeRef.class))
|
||||
.create();
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,9 @@ import com.google.gson.ExclusionStrategy;
|
||||
import com.google.gson.FieldAttributes;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.InstanceCreator;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import jadx.core.utils.GsonUtils;
|
||||
import jadx.gui.utils.PathTypeAdapter;
|
||||
import jadx.gui.utils.RectangleTypeAdapter;
|
||||
|
||||
@ -34,7 +34,7 @@ public class JadxSettingsAdapter {
|
||||
|| f.hasModifier(Modifier.PUBLIC)
|
||||
|| f.hasModifier(Modifier.TRANSIENT)
|
||||
|| f.hasModifier(Modifier.STATIC)
|
||||
|| (f.getAnnotation(GsonExclude.class) != null);
|
||||
|| f.getAnnotation(GsonExclude.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,12 +42,8 @@ public class JadxSettingsAdapter {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
private static final GsonBuilder GSON_BUILDER = new GsonBuilder()
|
||||
.setExclusionStrategies(EXCLUDE_FIELDS)
|
||||
.registerTypeHierarchyAdapter(Path.class, PathTypeAdapter.singleton())
|
||||
.registerTypeHierarchyAdapter(Rectangle.class, RectangleTypeAdapter.singleton())
|
||||
.setPrettyPrinting();
|
||||
private static final Gson GSON = GSON_BUILDER.create();
|
||||
|
||||
private static final Gson GSON = makeGsonBuilder().create();
|
||||
|
||||
private JadxSettingsAdapter() {
|
||||
}
|
||||
@ -92,17 +88,18 @@ public class JadxSettingsAdapter {
|
||||
}
|
||||
|
||||
public static void fill(JadxSettings settings, String jsonStr) {
|
||||
populate(GSON_BUILDER, jsonStr, JadxSettings.class, settings);
|
||||
GsonUtils.fillObjectFromJsonString(makeGsonBuilder(), settings, jsonStr);
|
||||
}
|
||||
|
||||
private static <T> void populate(GsonBuilder builder, String json, Class<T> type, final T into) {
|
||||
builder.registerTypeAdapter(type, (InstanceCreator<T>) t -> into)
|
||||
.create()
|
||||
.fromJson(json, type);
|
||||
private static GsonBuilder makeGsonBuilder() {
|
||||
return GsonUtils.defaultGsonBuilder()
|
||||
.setExclusionStrategies(EXCLUDE_FIELDS)
|
||||
.registerTypeHierarchyAdapter(Path.class, PathTypeAdapter.singleton())
|
||||
.registerTypeHierarchyAdapter(Rectangle.class, RectangleTypeAdapter.singleton());
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotation for specifying fields that should not be be saved/loaded
|
||||
* Annotation for specifying fields that should not be saved/loaded
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
|
@ -42,7 +42,6 @@ import javax.swing.WindowConstants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import jadx.api.CommentsLevel;
|
||||
@ -57,6 +56,7 @@ import jadx.api.args.UseSourceNameAsClassNameAlias;
|
||||
import jadx.api.plugins.events.JadxEvents;
|
||||
import jadx.api.plugins.events.types.ReloadSettingsWindow;
|
||||
import jadx.api.plugins.gui.ISettingsGroup;
|
||||
import jadx.core.utils.GsonUtils;
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.JadxSettingsAdapter;
|
||||
import jadx.gui.settings.JadxUpdateChannel;
|
||||
@ -747,7 +747,7 @@ public class JadxSettingsWindow extends JDialog {
|
||||
settingsJson.remove("lastOpenFilePath");
|
||||
settingsJson.remove("lastSaveFilePath");
|
||||
settingsJson.remove("recentProjects");
|
||||
String settingsText = new GsonBuilder().setPrettyPrinting().create().toJson(settingsJson);
|
||||
String settingsText = GsonUtils.buildGson().toJson(settingsJson);
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
StringSelection selection = new StringSelection(settingsText);
|
||||
clipboard.setContents(selection, selection);
|
||||
|
@ -322,7 +322,7 @@ public class MainWindow extends JFrame {
|
||||
if (!settings.isCheckForUpdates()) {
|
||||
return;
|
||||
}
|
||||
JadxUpdate.check(settings.getJadxUpdateChannel(), release -> SwingUtilities.invokeLater(() -> {
|
||||
new JadxUpdate().check(settings.getJadxUpdateChannel(), release -> SwingUtilities.invokeLater(() -> {
|
||||
switch (settings.getJadxUpdateChannel()) {
|
||||
case STABLE:
|
||||
updateLink.setUrl(JadxUpdate.JADX_RELEASES_URL);
|
||||
|
@ -1,17 +1,17 @@
|
||||
package jadx.gui.ui.codearea;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import jadx.core.utils.GsonUtils;
|
||||
import jadx.gui.treemodel.JNode;
|
||||
import jadx.gui.ui.action.ActionModel;
|
||||
|
||||
public class JsonPrettifyAction extends JNodeAction {
|
||||
|
||||
private static final long serialVersionUID = -2682529369671695550L;
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
private static final Gson GSON = GsonUtils.buildGson();
|
||||
|
||||
public JsonPrettifyAction(CodeArea codeArea) {
|
||||
super(ActionModel.JSON_PRETTIFY, codeArea);
|
||||
|
@ -1,11 +1,10 @@
|
||||
package jadx.gui.update
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import jadx.api.JadxDecompiler
|
||||
import jadx.core.Jadx
|
||||
import jadx.core.plugins.versions.VersionComparator
|
||||
import jadx.core.utils.GsonUtils.buildGson
|
||||
import jadx.gui.settings.JadxUpdateChannel
|
||||
import org.jetbrains.kotlin.konan.file.use
|
||||
import java.io.InputStreamReader
|
||||
@ -13,43 +12,51 @@ import java.net.HttpURLConnection
|
||||
import java.net.URI
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
data class Release(val name: String)
|
||||
data class Release(var name: String = "")
|
||||
|
||||
data class ArtifactList(val artifacts: List<Artifact>)
|
||||
data class ArtifactList(var artifacts: List<Artifact>? = null)
|
||||
|
||||
data class Artifact(
|
||||
val name: String,
|
||||
@SerializedName("workflow_run") val workflowRun: WorkflowRun,
|
||||
var name: String = "",
|
||||
@SerializedName("workflow_run") var workflowRun: WorkflowRun? = null,
|
||||
)
|
||||
|
||||
data class WorkflowRun(
|
||||
@SerializedName("head_branch") val branch: String,
|
||||
@SerializedName("head_branch") var branch: String = "",
|
||||
)
|
||||
|
||||
interface IUpdateCallback {
|
||||
fun onUpdate(r: Release)
|
||||
}
|
||||
|
||||
object JadxUpdate {
|
||||
private val log = KotlinLogging.logger {}
|
||||
class JadxUpdate(private val jadxVersion: String = Jadx.getVersion()) {
|
||||
|
||||
const val JADX_ARTIFACTS_URL = "https://nightly.link/skylot/jadx/workflows/build-artifacts/master"
|
||||
const val JADX_RELEASES_URL = "https://github.com/skylot/jadx/releases"
|
||||
companion object {
|
||||
private val LOG = KotlinLogging.logger {}
|
||||
|
||||
private const val GITHUB_API_URL = "https://api.github.com/repos/skylot/jadx"
|
||||
private const val GITHUB_LATEST_ARTIFACTS_URL = "$GITHUB_API_URL/actions/artifacts?per_page=5&page=1"
|
||||
private const val GITHUB_LATEST_RELEASE_URL = "$GITHUB_API_URL/releases/latest"
|
||||
const val JADX_ARTIFACTS_URL = "https://nightly.link/skylot/jadx/workflows/build-artifacts/master"
|
||||
const val JADX_RELEASES_URL = "https://github.com/skylot/jadx/releases"
|
||||
|
||||
private const val GITHUB_API_URL = "https://api.github.com/repos/skylot/jadx"
|
||||
private const val GITHUB_LATEST_ARTIFACTS_URL = "$GITHUB_API_URL/actions/artifacts?per_page=5&page=1"
|
||||
private const val GITHUB_LATEST_RELEASE_URL = "$GITHUB_API_URL/releases/latest"
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun check(updateChannel: JadxUpdateChannel, callback: IUpdateCallback) {
|
||||
if (jadxVersion == Jadx.VERSION_DEV) {
|
||||
LOG.debug { "Ignore update check: development version" }
|
||||
return
|
||||
}
|
||||
Thread {
|
||||
try {
|
||||
val release = checkForNewRelease(updateChannel)
|
||||
if (release != null) {
|
||||
callback.onUpdate(release)
|
||||
} else {
|
||||
LOG.info { "No updates found" }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.warn(e) { "Jadx update error" }
|
||||
LOG.warn(e) { "Jadx update error" }
|
||||
}
|
||||
}.apply {
|
||||
name = "Jadx update thread"
|
||||
@ -58,14 +65,9 @@ object JadxUpdate {
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkForNewRelease(updateChannel: JadxUpdateChannel): Release? {
|
||||
if (Jadx.isDevVersion()) {
|
||||
log.debug { "Ignore check for update: development version" }
|
||||
return null
|
||||
}
|
||||
log.info {
|
||||
"Checking for updates... Update channel: $updateChannel, current version: ${JadxDecompiler.getVersion()}"
|
||||
}
|
||||
fun checkForNewRelease(updateChannel: JadxUpdateChannel): Release? {
|
||||
LOG.info { "Checking for updates..." }
|
||||
LOG.info { "Update channel: $updateChannel, current version: $jadxVersion" }
|
||||
return when (updateChannel) {
|
||||
JadxUpdateChannel.STABLE -> checkForNewStableRelease()
|
||||
JadxUpdateChannel.UNSTABLE -> checkForNewUnstableRelease()
|
||||
@ -73,28 +75,27 @@ object JadxUpdate {
|
||||
}
|
||||
|
||||
private fun checkForNewStableRelease(): Release? {
|
||||
val currentVersion = JadxDecompiler.getVersion()
|
||||
if (currentVersion.startsWith("r")) {
|
||||
if (jadxVersion.startsWith("r")) {
|
||||
// current version is 'unstable', but update channel set to 'stable'
|
||||
log.info { "Skip update check: can't compare unstable and stable versions" }
|
||||
LOG.info { "Skip update check: can't compare unstable and stable versions" }
|
||||
return null
|
||||
}
|
||||
val latestRelease = getAndParse(GITHUB_LATEST_RELEASE_URL, Release::class) ?: return null
|
||||
if (VersionComparator.checkAndCompare(currentVersion, latestRelease.name) >= 0) return null
|
||||
log.info { "Found new jadx version: ${latestRelease.name}" }
|
||||
if (VersionComparator.checkAndCompare(jadxVersion, latestRelease.name) >= 0) return null
|
||||
LOG.info { "Found new jadx version: ${latestRelease.name}" }
|
||||
return latestRelease
|
||||
}
|
||||
|
||||
private fun checkForNewUnstableRelease(): Release? {
|
||||
val artifacts = getAndParse(GITHUB_LATEST_ARTIFACTS_URL, ArtifactList::class)
|
||||
?.artifacts
|
||||
?.filter { it.workflowRun.branch == "master" }
|
||||
?.filter { it.workflowRun?.branch == "master" }
|
||||
?: return null
|
||||
if (artifacts.isEmpty()) return null
|
||||
|
||||
val latestVersion = artifacts[0].name.removePrefix("jadx-gui-").removePrefix("jadx-").substringBefore('-')
|
||||
if (VersionComparator.checkAndCompare(JadxDecompiler.getVersion(), latestVersion) >= 0) return null
|
||||
log.info { "Found new unstable version: $latestVersion" }
|
||||
if (VersionComparator.checkAndCompare(jadxVersion, latestVersion) >= 0) return null
|
||||
LOG.info { "Found new unstable version: $latestVersion" }
|
||||
return Release(latestVersion)
|
||||
}
|
||||
|
||||
@ -105,7 +106,7 @@ object JadxUpdate {
|
||||
}
|
||||
return con.inputStream.use { stream ->
|
||||
InputStreamReader(stream).use { reader ->
|
||||
Gson().fromJson(reader, klass.java)
|
||||
buildGson().fromJson(reader, klass.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
jadx-gui/src/test/java/jadx/gui/update/TestJadxUpdate.kt
Normal file
27
jadx-gui/src/test/java/jadx/gui/update/TestJadxUpdate.kt
Normal file
@ -0,0 +1,27 @@
|
||||
package jadx.gui.update
|
||||
|
||||
import jadx.gui.settings.JadxUpdateChannel
|
||||
import org.junit.jupiter.api.Disabled
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
/**
|
||||
* Test updates fetch.
|
||||
* All tests disabled because of network requests, run manually on JadxUpdate changes
|
||||
*/
|
||||
@Disabled("Network requests")
|
||||
class TestJadxUpdate {
|
||||
|
||||
@Test
|
||||
fun testStableCheck() {
|
||||
JadxUpdate("1.5.0").checkForNewRelease(JadxUpdateChannel.STABLE)?.let {
|
||||
println("Latest release: $it")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnstableCheck() {
|
||||
JadxUpdate("r2000").checkForNewRelease(JadxUpdateChannel.UNSTABLE)?.let {
|
||||
println("Latest unstable: $it")
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,6 @@ import java.util.function.Consumer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import jadx.api.plugins.utils.ZipSecurity;
|
||||
@ -26,6 +25,7 @@ import jadx.plugins.tools.resolvers.github.data.Asset;
|
||||
import jadx.plugins.tools.resolvers.github.data.Release;
|
||||
import jadx.plugins.tools.utils.PluginUtils;
|
||||
|
||||
import static jadx.core.utils.GsonUtils.buildGson;
|
||||
import static jadx.plugins.tools.utils.PluginFiles.PLUGINS_LIST_CACHE;
|
||||
|
||||
public class JadxPluginsList {
|
||||
@ -101,10 +101,6 @@ public class JadxPluginsList {
|
||||
loadedList = listCache;
|
||||
}
|
||||
|
||||
private static Gson buildGson() {
|
||||
return new GsonBuilder().setPrettyPrinting().create();
|
||||
}
|
||||
|
||||
private Release fetchLatestRelease() {
|
||||
LocationInfo latest = new LocationInfo("jadx-decompiler", "jadx-plugins-list", "list", null);
|
||||
Release release = GithubTools.fetchRelease(latest);
|
||||
@ -127,7 +123,7 @@ public class JadxPluginsList {
|
||||
}
|
||||
|
||||
private static List<JadxPluginMetadata> loadListBundle(Path tmpListFile) {
|
||||
Gson gson = new Gson();
|
||||
Gson gson = buildGson();
|
||||
List<JadxPluginMetadata> entries = new ArrayList<>();
|
||||
ZipSecurity.readZipEntries(tmpListFile.toFile(), (entry, in) -> {
|
||||
if (entry.getName().endsWith(".json")) {
|
||||
|
@ -19,9 +19,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import jadx.api.plugins.JadxPlugin;
|
||||
import jadx.api.plugins.JadxPluginInfo;
|
||||
import jadx.core.Jadx;
|
||||
@ -36,6 +33,7 @@ import jadx.plugins.tools.resolvers.IJadxPluginResolver;
|
||||
import jadx.plugins.tools.resolvers.ResolversRegistry;
|
||||
import jadx.plugins.tools.utils.PluginUtils;
|
||||
|
||||
import static jadx.core.utils.GsonUtils.buildGson;
|
||||
import static jadx.plugins.tools.utils.PluginFiles.DROPINS_DIR;
|
||||
import static jadx.plugins.tools.utils.PluginFiles.INSTALLED_DIR;
|
||||
import static jadx.plugins.tools.utils.PluginFiles.PLUGINS_JSON;
|
||||
@ -307,12 +305,6 @@ public class JadxPluginsTools {
|
||||
}
|
||||
}
|
||||
|
||||
private static Gson buildGson() {
|
||||
return new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
}
|
||||
|
||||
private JadxInstalledPlugins loadPluginsJson() {
|
||||
if (!Files.isRegularFile(PLUGINS_JSON)) {
|
||||
JadxInstalledPlugins plugins = new JadxInstalledPlugins();
|
||||
|
@ -10,11 +10,12 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import jadx.plugins.tools.resolvers.github.data.Release;
|
||||
|
||||
import static jadx.core.utils.GsonUtils.buildGson;
|
||||
|
||||
public class GithubTools {
|
||||
private static final String GITHUB_API_URL = "https://api.github.com/";
|
||||
|
||||
@ -59,7 +60,7 @@ public class GithubTools {
|
||||
throw new RuntimeException("Request failed, url: " + url, e);
|
||||
}
|
||||
try (Reader reader = new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8)) {
|
||||
return new Gson().fromJson(reader, type);
|
||||
return buildGson().fromJson(reader, type);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to parse response, url: " + url, e);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class XapkCustomResourcesLoader : CustomResourcesLoader {
|
||||
if (!XapkUtils.isSupported(manifest)) return false
|
||||
|
||||
val apkEntries = manifest.splitApks.map { it.file }.toHashSet()
|
||||
ZipSecurity.visitZipEntries(file) { zip, entry ->
|
||||
ZipSecurity.visitZipEntries<Any>(file) { zip, entry ->
|
||||
if (apkEntries.contains(entry.name)) {
|
||||
val tmpFile = ZipSecurity.getInputStreamForEntry(zip, entry).use {
|
||||
CommonFileUtils.saveToTempFile(it, ".apk").toFile()
|
||||
|
@ -4,14 +4,14 @@ import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class XapkManifest(
|
||||
@SerializedName("xapk_version")
|
||||
val xapkVersion: Int,
|
||||
var xapkVersion: Int = 0,
|
||||
@SerializedName("split_apks")
|
||||
val splitApks: List<SplitApk>,
|
||||
var splitApks: List<SplitApk> = listOf(),
|
||||
) {
|
||||
data class SplitApk(
|
||||
@SerializedName("file")
|
||||
val file: String,
|
||||
var file: String = "",
|
||||
@SerializedName("id")
|
||||
val id: String,
|
||||
var id: String = "",
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package jadx.plugins.input.xapk
|
||||
|
||||
import com.google.gson.Gson
|
||||
import jadx.api.plugins.utils.ZipSecurity
|
||||
import jadx.core.utils.GsonUtils.buildGson
|
||||
import jadx.core.utils.files.FileUtils
|
||||
import jadx.core.utils.files.ZipFile
|
||||
import java.io.File
|
||||
@ -14,7 +14,7 @@ object XapkUtils {
|
||||
ZipFile(file).use { zip ->
|
||||
val manifestEntry = zip.getEntry("manifest.json") ?: return null
|
||||
return InputStreamReader(ZipSecurity.getInputStreamForEntry(zip, manifestEntry)).use {
|
||||
Gson().fromJson(it, XapkManifest::class.java)
|
||||
buildGson().fromJson(it, XapkManifest::class.java)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
Loading…
Reference in New Issue
Block a user