<commit_before>package jadx.core.deobf;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;

import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.api.JadxArgs;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.types.SourceFileAttr;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType;
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.kotlin.KotlinMetadataUtils;

public class Deobfuscator {
	private static final Logger LOG = LoggerFactory.getLogger(Deobfuscator.class);

	private static final boolean DEBUG = false;

	public static final String CLASS_NAME_SEPARATOR = ".";
	public static final String INNER_CLASS_SEPARATOR = "$";

	private final JadxArgs args;
	private final RootNode root;
	private final DeobfPresets deobfPresets;

	private final Map<ClassInfo, DeobfClsInfo> clsMap = new LinkedHashMap<>();
	private final Map<FieldInfo, String> fldMap = new HashMap<>();
	private final Map<MethodInfo, String> mthMap = new HashMap<>();

	private final PackageNode rootPackage = new PackageNode("");
	private final Set<String> pkgSet = new TreeSet<>();
	private final Set<String> reservedClsNames = new HashSet<>();

	private final NavigableSet<MethodNode> mthProcessQueue = new TreeSet<>();

	private final int maxLength;
	private final int minLength;
	private final boolean useSourceNameAsAlias;
	private final boolean parseKotlinMetadata;

	private int pkgIndex = 0;
	private int clsIndex = 0;
	private int fldIndex = 0;
	private int mthIndex = 0;

	public Deobfuscator(RootNode root) {
		this.root = root;
		this.args = root.getArgs();

		this.minLength = args.getDeobfuscationMinLength();
		this.maxLength = args.getDeobfuscationMaxLength();
		this.useSourceNameAsAlias = args.isUseSourceNameAsClassAlias();
		this.parseKotlinMetadata = args.isParseKotlinMetadata();

		this.deobfPresets = DeobfPresets.build(root);
	}

	public void execute() {
		if (args.getDeobfuscationMapFileMode().shouldRead()) {
			if (deobfPresets.load()) {
				for (Map.Entry<String, String> pkgEntry : deobfPresets.getPkgPresetMap().entrySet()) {
					addPackagePreset(pkgEntry.getKey(), pkgEntry.getValue());
				}
				deobfPresets.getPkgPresetMap().clear(); // not needed anymore
				initIndexes();
			}
		}
		process();
	}

	public void savePresets() {
		DeobfuscationMapFileMode mode = args.getDeobfuscationMapFileMode();
		if (!mode.shouldWrite()) {
			return;
		}
		Path deobfMapFile = deobfPresets.getDeobfMapFile();
		if (mode == DeobfuscationMapFileMode.READ_OR_SAVE && Files.exists(deobfMapFile)) {
			return;
		}
		try {
			deobfPresets.clear();
			fillDeobfPresets();
			deobfPresets.save();
		} catch (Exception e) {
			LOG.error("Failed to save deobfuscation map file '{}'", deobfMapFile.toAbsolutePath(), e);
		}
	}

	private void fillDeobfPresets() {
		for (PackageNode p : getRootPackage().getInnerPackages()) {
			for (PackageNode pp : p.getInnerPackages()) {
				dfsPackageName(p.getName(), pp);
			}
			if (p.hasAlias()) {
				deobfPresets.getPkgPresetMap().put(p.getName(), p.getAlias());
			}
		}
		for (ClassNode cls : root.getClasses()) {
			ClassInfo classInfo = cls.getClassInfo();
			if (classInfo.hasAlias()) {
				deobfPresets.getClsPresetMap().put(classInfo.makeRawFullName(), classInfo.getAliasShortName());
			}

			for (FieldNode fld : cls.getFields()) {
				FieldInfo fieldInfo = fld.getFieldInfo();
				if (fieldInfo.hasAlias()) {
					deobfPresets.getFldPresetMap().put(fieldInfo.getRawFullId(), fld.getAlias());
				}
			}

			for (MethodNode mth : cls.getMethods()) {
				MethodInfo methodInfo = mth.getMethodInfo();
				if (methodInfo.hasAlias()) {
					deobfPresets.getFldPresetMap().put(methodInfo.getRawFullId(), methodInfo.getAlias());
				}
			}
		}
	}<commit_msg>fix(deobf): fix writing method mappings as fields entries (#1432)(PR #1433)<commit_after>package jadx.core.deobf;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;

import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.api.JadxArgs;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.api.plugins.input.data.attributes.JadxAttrType;
import jadx.api.plugins.input.data.attributes.types.SourceFileAttr;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType;
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.kotlin.KotlinMetadataUtils;

public class Deobfuscator {
	private static final Logger LOG = LoggerFactory.getLogger(Deobfuscator.class);

	private static final boolean DEBUG = false;

	public static final String CLASS_NAME_SEPARATOR = ".";
	public static final String INNER_CLASS_SEPARATOR = "$";

	private final JadxArgs args;
	private final RootNode root;
	private final DeobfPresets deobfPresets;

	private final Map<ClassInfo, DeobfClsInfo> clsMap = new LinkedHashMap<>();
	private final Map<FieldInfo, String> fldMap = new HashMap<>();
	private final Map<MethodInfo, String> mthMap = new HashMap<>();

	private final PackageNode rootPackage = new PackageNode("");
	private final Set<String> pkgSet = new TreeSet<>();
	private final Set<String> reservedClsNames = new HashSet<>();

	private final NavigableSet<MethodNode> mthProcessQueue = new TreeSet<>();

	private final int maxLength;
	private final int minLength;
	private final boolean useSourceNameAsAlias;
	private final boolean parseKotlinMetadata;

	private int pkgIndex = 0;
	private int clsIndex = 0;
	private int fldIndex = 0;
	private int mthIndex = 0;

	public Deobfuscator(RootNode root) {
		this.root = root;
		this.args = root.getArgs();

		this.minLength = args.getDeobfuscationMinLength();
		this.maxLength = args.getDeobfuscationMaxLength();
		this.useSourceNameAsAlias = args.isUseSourceNameAsClassAlias();
		this.parseKotlinMetadata = args.isParseKotlinMetadata();

		this.deobfPresets = DeobfPresets.build(root);
	}

	public void execute() {
		if (args.getDeobfuscationMapFileMode().shouldRead()) {
			if (deobfPresets.load()) {
				for (Map.Entry<String, String> pkgEntry : deobfPresets.getPkgPresetMap().entrySet()) {
					addPackagePreset(pkgEntry.getKey(), pkgEntry.getValue());
				}
				deobfPresets.getPkgPresetMap().clear(); // not needed anymore
				initIndexes();
			}
		}
		process();
	}

	public void savePresets() {
		DeobfuscationMapFileMode mode = args.getDeobfuscationMapFileMode();
		if (!mode.shouldWrite()) {
			return;
		}
		Path deobfMapFile = deobfPresets.getDeobfMapFile();
		if (mode == DeobfuscationMapFileMode.READ_OR_SAVE && Files.exists(deobfMapFile)) {
			return;
		}
		try {
			deobfPresets.clear();
			fillDeobfPresets();
			deobfPresets.save();
		} catch (Exception e) {
			LOG.error("Failed to save deobfuscation map file '{}'", deobfMapFile.toAbsolutePath(), e);
		}
	}

	private void fillDeobfPresets() {
		for (PackageNode p : getRootPackage().getInnerPackages()) {
			for (PackageNode pp : p.getInnerPackages()) {
				dfsPackageName(p.getName(), pp);
			}
			if (p.hasAlias()) {
				deobfPresets.getPkgPresetMap().put(p.getName(), p.getAlias());
			}
		}
		for (ClassNode cls : root.getClasses()) {
			ClassInfo classInfo = cls.getClassInfo();
			if (classInfo.hasAlias()) {
				deobfPresets.getClsPresetMap().put(classInfo.makeRawFullName(), classInfo.getAliasShortName());
			}

			for (FieldNode fld : cls.getFields()) {
				FieldInfo fieldInfo = fld.getFieldInfo();
				if (fieldInfo.hasAlias()) {
					deobfPresets.getFldPresetMap().put(fieldInfo.getRawFullId(), fld.getAlias());
				}
			}

			for (MethodNode mth : cls.getMethods()) {
				MethodInfo methodInfo = mth.getMethodInfo();
				if (methodInfo.hasAlias()) {
					deobfPresets.getMthPresetMap().put(methodInfo.getRawFullId(), methodInfo.getAlias());
				}
			}
		}
	}
{'fraction_non_alphanumeric': 0.12326776933392937, 'fraction_numerical': 0.002235136343316942, 'mean_word_length': 4.872047244094488, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1084426', 'n_tokens_mistral': 3330, 'n_tokens_neox': 3069, 'n_words': 595}