diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a9dea4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties +/local.properties + +# Log/OS Files +*.log + +# Android Studio generated files and folders +captures/ +.externalNativeBuild/ +.cxx/ +*.apk +output.json + +# IntelliJ +*.iml +.idea/ +misc.xml +deploymentTargetDropDown.xml +render.experimental.xml + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Android Profiling +*.hprof \ No newline at end of file diff --git a/app/src/main/java/modder/hub/dexeditor/fragment/SearchFragment.java b/app/src/main/java/modder/hub/dexeditor/fragment/SearchFragment.java index 11cc542..07811aa 100644 --- a/app/src/main/java/modder/hub/dexeditor/fragment/SearchFragment.java +++ b/app/src/main/java/modder/hub/dexeditor/fragment/SearchFragment.java @@ -755,16 +755,32 @@ public void run() { int countInClass = 0; if (type.equals("String")) { - String findPattern = exactlyMatch ? "\"" + Pattern.quote(findQuery) + "\"" : Pattern.quote(findQuery); - String replacePattern = exactlyMatch ? "\"" + java.util.regex.Matcher.quoteReplacement(replaceWith) + "\"" : java.util.regex.Matcher.quoteReplacement(replaceWith); - Pattern p = Pattern.compile(findPattern, matchCase ? 0 : Pattern.CASE_INSENSITIVE); - java.util.regex.Matcher m = p.matcher(originalText); + Matcher lm = Pattern.compile("\"((?:\\\\.|[^\"\\\\])*)\"").matcher(originalText); StringBuffer sb = new StringBuffer(); - while (m.find()) { - countInClass++; - m.appendReplacement(sb, replacePattern); + + int flag = matchCase ? 0 : Pattern.CASE_INSENSITIVE; + String q1 = isRegex ? findQuery : Pattern.quote(findQuery); + String q2 = exactlyMatch ? "^" + q1 + "$" : q1; + Pattern innerFind = Pattern.compile(q2, flag); + + while (lm.find()) { + Matcher im = innerFind.matcher(lm.group(1)); + StringBuffer inner = new StringBuffer(); + while (im.find()) { + countInClass++; + try { + im.appendReplacement(inner, isRegex ? replaceWith : Matcher.quoteReplacement(replaceWith)); + } catch (IndexOutOfBoundsException | IllegalArgumentException e) { + errorClasses.add(className + ": invalid replacement pattern - " + e.getMessage()); + return; + } + } + im.appendTail(inner); + + String newLiteral = "\"" + inner + "\""; + lm.appendReplacement(sb, Matcher.quoteReplacement(newLiteral)); } - m.appendTail(sb); + lm.appendTail(sb); modifiedText = sb.toString(); } else { if (isRegex) { @@ -772,7 +788,13 @@ public void run() { StringBuffer sb = new StringBuffer(); while (m.find()) { countInClass++; - m.appendReplacement(sb, Matcher.quoteReplacement(replaceWith)); + try { + m.appendReplacement(sb, replaceWith); + } catch (IndexOutOfBoundsException | IllegalArgumentException e) { + // invalid group reference + errorClasses.add(className + ": invalid replacement pattern - " + e.getMessage()); + return; + } } m.appendTail(sb); modifiedText = sb.toString(); @@ -881,7 +903,7 @@ private String generateSmali(ClassDef classDef) throws Exception { @SuppressLint("NotifyDataSetChanged") private void onPostExecute(DexEditorActivity activity) { if (progressDialog.isShowing()) progressDialog.dismiss(); - Notify_MT.Notify(activity, "Info", "Total replaced " + replacedCount.get() + "times in " + affectedClasses.get() + "classes." , "Close"); + Notify_MT.Notify(activity, "Info", "Total replaced " + replacedCount.get() + " times in " + affectedClasses.get() + " classes." , "Close"); if (!errorClasses.isEmpty()) { showErrorDialog(activity); }