mirror of
https://github.com/TrianguloY/UrlChecker.git
synced 2024-09-20 04:12:14 +02:00
Pattern Checker: Fix optional groups giving a null instead of an empty string
Fixes #237
This commit is contained in:
parent
491cd17c64
commit
72f57e43d9
@ -1,5 +1,7 @@
|
|||||||
package com.trianguloy.urlchecker.modules.list;
|
package com.trianguloy.urlchecker.modules.list;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.os.Build;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
@ -24,6 +26,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This module checks for patterns characters in the url
|
* This module checks for patterns characters in the url
|
||||||
@ -122,7 +125,7 @@ class PatternDialog extends AModuleDialog {
|
|||||||
|
|
||||||
// get regex (must exists)
|
// get regex (must exists)
|
||||||
if (!data.has("regex")) continue;
|
if (!data.has("regex")) continue;
|
||||||
var regex = data.getString("regex");
|
Pattern regex = Pattern.compile(data.getString("regex"));
|
||||||
|
|
||||||
// applied?
|
// applied?
|
||||||
message.applied = urlData.getData(APPLIED + pattern) != null;
|
message.applied = urlData.getData(APPLIED + pattern) != null;
|
||||||
@ -130,7 +133,7 @@ class PatternDialog extends AModuleDialog {
|
|||||||
// check matches
|
// check matches
|
||||||
// if 'regexp' matches, the pattern can match
|
// if 'regexp' matches, the pattern can match
|
||||||
// if 'regexp' doesn't match, the patter doesn't match
|
// if 'regexp' doesn't match, the patter doesn't match
|
||||||
var matches = Pattern.compile(regex).matcher(url).find();
|
var matches = regex.matcher(url).find();
|
||||||
if (matches && data.has("excludeRegex")) {
|
if (matches && data.has("excludeRegex")) {
|
||||||
// if 'excludeRegex' doesn't exist, the pattern can match
|
// if 'excludeRegex' doesn't exist, the pattern can match
|
||||||
// if 'excludeRegex' matches, the pattern doesn't matches
|
// if 'excludeRegex' matches, the pattern doesn't matches
|
||||||
@ -158,7 +161,7 @@ class PatternDialog extends AModuleDialog {
|
|||||||
|
|
||||||
if (replacement != null) {
|
if (replacement != null) {
|
||||||
// replace url
|
// replace url
|
||||||
message.newUrl = url.replaceAll(regex, replacement);
|
message.newUrl = replaceAll(url, regex, replacement);
|
||||||
|
|
||||||
// automatic? apply
|
// automatic? apply
|
||||||
if (data.optBoolean("automatic")) {
|
if (data.optBoolean("automatic")) {
|
||||||
@ -225,4 +228,100 @@ class PatternDialog extends AModuleDialog {
|
|||||||
this.pattern = pattern;
|
this.pattern = pattern;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On Android 10 and under, optional groups may yield a "null" in the replacement output instead of an empty string.
|
||||||
|
* Therefore, we just copy the implementation from newer versions
|
||||||
|
* https://github.com/TrianguloY/UrlChecker/issues/237
|
||||||
|
*/
|
||||||
|
private static String replaceAll(String text, Pattern pattern, String replacement) {
|
||||||
|
// Copied from https://android.googlesource.com/platform/libcore/+/refs/heads/android13-release/ojluni/src/main/java/java/util/regex/Matcher.java#837
|
||||||
|
Matcher matcher = pattern.matcher(text);
|
||||||
|
boolean result = matcher.find();
|
||||||
|
if (result) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
int appendPos = 0;
|
||||||
|
do {
|
||||||
|
appendPos = appendReplacement(text, matcher, sb, replacement, appendPos);
|
||||||
|
result = matcher.find();
|
||||||
|
} while (result);
|
||||||
|
appendTail(text, sb, appendPos);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
return text.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int appendReplacement(String text, Matcher matcher, StringBuffer sb, String replacement, int appendPos) {
|
||||||
|
// Copied from https://android.googlesource.com/platform/libcore/+/refs/heads/android13-release/ojluni/src/main/java/java/util/regex/Matcher.java#714
|
||||||
|
sb.append(text.substring(appendPos, matcher.start()));
|
||||||
|
appendEvaluated(matcher, sb, replacement);
|
||||||
|
appendPos = matcher.end();
|
||||||
|
|
||||||
|
return appendPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
|
private static void appendEvaluated(Matcher matcher, StringBuffer buffer, String s) {
|
||||||
|
// Copied from https://android.googlesource.com/platform/libcore/+/refs/heads/android13-release/ojluni/src/main/java/java/util/regex/Matcher.java#731
|
||||||
|
boolean escape = false;
|
||||||
|
boolean dollar = false;
|
||||||
|
boolean escapeNamedGroup = false;
|
||||||
|
int escapeNamedGroupStart = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
char c = s.charAt(i);
|
||||||
|
if (c == '\\' && !escape) {
|
||||||
|
escape = true;
|
||||||
|
} else if (c == '$' && !escape) {
|
||||||
|
dollar = true;
|
||||||
|
} else if (c >= '0' && c <= '9' && dollar && !escapeNamedGroup) {
|
||||||
|
String groupValue = matcher.group(c - '0');
|
||||||
|
if (groupValue != null) {
|
||||||
|
buffer.append(groupValue);
|
||||||
|
}
|
||||||
|
dollar = false;
|
||||||
|
} else if (c == '{' && dollar) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||||
|
throw new IllegalArgumentException("your android version does not support named-capturing groups");
|
||||||
|
}
|
||||||
|
escapeNamedGroup = true;
|
||||||
|
escapeNamedGroupStart = i;
|
||||||
|
} else if (c == '}' && dollar && escapeNamedGroup) {
|
||||||
|
String groupValue = matcher.group(s.substring(escapeNamedGroupStart + 1, i));
|
||||||
|
if (groupValue != null) {
|
||||||
|
buffer.append(groupValue);
|
||||||
|
}
|
||||||
|
dollar = false;
|
||||||
|
escapeNamedGroup = false;
|
||||||
|
} else if (c != '}' && dollar && escapeNamedGroup) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
buffer.append(c);
|
||||||
|
dollar = false;
|
||||||
|
escape = false;
|
||||||
|
escapeNamedGroup = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escape) {
|
||||||
|
throw new IllegalArgumentException("character to be escaped is missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dollar) {
|
||||||
|
throw new IllegalArgumentException("Illegal group reference: group index is missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escapeNamedGroup) {
|
||||||
|
throw new IllegalArgumentException("Missing ending brace '}' from replacement string");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StringBuffer appendTail(String text, StringBuffer sb, int appendPos) {
|
||||||
|
// Copied from https://android.googlesource.com/platform/libcore/+/refs/heads/android13-release/ojluni/src/main/java/java/util/regex/Matcher.java#796
|
||||||
|
int to = text.length();
|
||||||
|
if (appendPos < to) {
|
||||||
|
sb.append(text.substring(appendPos, to));
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user