mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix escape bug
This commit is contained in:
parent
83d6428db8
commit
fbfb124f11
@ -7,8 +7,10 @@
|
||||
|
||||
### 新特性
|
||||
* 【poi 】 Excel合并单元格读取同一个值,不再为空
|
||||
* 【core 】 增加EscapeUtil.escapeAll(issue#758@Github)
|
||||
|
||||
### Bug修复
|
||||
* 【core 】 修复EscapeUtil.escape转义错误(issue#758@Github)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -29,6 +29,7 @@ public class ReplacerChain extends StrReplacer implements Chain<StrReplacer, Rep
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@Override
|
||||
public Iterator<StrReplacer> iterator() {
|
||||
return replacers.iterator();
|
||||
|
@ -8,31 +8,32 @@ import cn.hutool.core.text.StrBuilder;
|
||||
/**
|
||||
* 抽象字符串替换类<br>
|
||||
* 通过实现replace方法实现局部替换逻辑
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.5
|
||||
*/
|
||||
public abstract class StrReplacer implements Replacer<CharSequence>, Serializable{
|
||||
public abstract class StrReplacer implements Replacer<CharSequence>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* 抽象的字符串替换方法,通过传入原字符串和当前位置,执行替换逻辑,返回处理或替换的字符串长度部分。
|
||||
*
|
||||
* @param str 被处理的字符串
|
||||
* @param pos 当前位置
|
||||
* @param out 输出
|
||||
* @return 处理的原字符串长度,0表示跳过此字符
|
||||
*/
|
||||
protected abstract int replace(CharSequence str, int pos, StrBuilder out);
|
||||
|
||||
|
||||
@Override
|
||||
public CharSequence replace(CharSequence t) {
|
||||
final int len = t.length();
|
||||
final StrBuilder strBuillder = StrBuilder.create(len);
|
||||
int pos = 0;//当前位置
|
||||
int consumed;//处理过的字符数
|
||||
while(pos < len) {
|
||||
while (pos < len) {
|
||||
consumed = replace(t, pos, strBuillder);
|
||||
if(0 == consumed) {
|
||||
if (0 == consumed) {
|
||||
//0表示未处理或替换任何字符,原样输出本字符并从下一个字符继续
|
||||
strBuillder.append(t.charAt(pos));
|
||||
pos++;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.text.escape.Html4Escape;
|
||||
import cn.hutool.core.text.escape.Html4Unescape;
|
||||
|
||||
@ -7,57 +8,87 @@ import cn.hutool.core.text.escape.Html4Unescape;
|
||||
* 转义和反转义工具类Escape / Unescape<br>
|
||||
* escape采用ISO Latin字符集对指定的字符串进行编码。<br>
|
||||
* 所有的空格符、标点符号、特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编码(xx等于该字符在字符集表里面的编码的16进制数字)。
|
||||
*
|
||||
*
|
||||
* @author xiaoleilu
|
||||
*/
|
||||
public class EscapeUtil {
|
||||
|
||||
/**
|
||||
* 不转义的符号编码
|
||||
*/
|
||||
private static final String NOT_ESCAPE_CHARS = "*@-_+./";
|
||||
private static final Filter<Character> JS_ESCAPE_FILTER = c -> false == (
|
||||
Character.isDigit(c)
|
||||
|| Character.isLowerCase(c)
|
||||
|| Character.isUpperCase(c)
|
||||
|| StrUtil.contains(NOT_ESCAPE_CHARS, c)
|
||||
);
|
||||
|
||||
/**
|
||||
* 转义HTML4中的特殊字符
|
||||
*
|
||||
*
|
||||
* @param html HTML文本
|
||||
* @return 转义后的文本
|
||||
* @since 4.1.5
|
||||
*/
|
||||
public static String escapeHtml4(String html) {
|
||||
public static String escapeHtml4(CharSequence html) {
|
||||
Html4Escape escape = new Html4Escape();
|
||||
return escape.replace(html).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 反转义HTML4中的特殊字符
|
||||
*
|
||||
*
|
||||
* @param html HTML文本
|
||||
* @return 转义后的文本
|
||||
* @since 4.1.5
|
||||
*/
|
||||
public static String unescapeHtml4(String html) {
|
||||
public static String unescapeHtml4(CharSequence html) {
|
||||
Html4Unescape unescape = new Html4Unescape();
|
||||
return unescape.replace(html).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape编码(Unicode)<br>
|
||||
* 该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / 。其他所有的字符都会被转义序列替换。
|
||||
*
|
||||
* Escape编码(Unicode)(等同于JS的escape()方法)<br>
|
||||
* 该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / <br>
|
||||
* 其他所有的字符都会被转义序列替换。
|
||||
*
|
||||
* @param content 被转义的内容
|
||||
* @return 编码后的字符串
|
||||
*/
|
||||
public static String escape(String content) {
|
||||
if (StrUtil.isBlank(content)) {
|
||||
return content;
|
||||
public static String escape(CharSequence content) {
|
||||
return escape(content, JS_ESCAPE_FILTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape编码(Unicode)<br>
|
||||
* 该方法不会对 ASCII 字母和数字进行编码。其他所有的字符都会被转义序列替换。
|
||||
*
|
||||
* @param content 被转义的内容
|
||||
* @return 编码后的字符串
|
||||
*/
|
||||
public static String escapeAll(CharSequence content) {
|
||||
return escape(content, c -> true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape编码(Unicode)<br>
|
||||
* 该方法不会对 ASCII 字母和数字进行编码。其他所有的字符都会被转义序列替换。
|
||||
*
|
||||
* @param content 被转义的内容
|
||||
* @param filter 编码过滤器,对于过滤器中accept为false的字符不做编码
|
||||
* @return 编码后的字符串
|
||||
*/
|
||||
public static String escape(CharSequence content, Filter<Character> filter) {
|
||||
if (StrUtil.isEmpty(content)) {
|
||||
return StrUtil.str(content);
|
||||
}
|
||||
|
||||
int i;
|
||||
final StringBuilder tmp = new StringBuilder(content.length() * 6);
|
||||
char j;
|
||||
StringBuilder tmp = new StringBuilder();
|
||||
tmp.ensureCapacity(content.length() * 6);
|
||||
|
||||
for (i = 0; i < content.length(); i++) {
|
||||
|
||||
for (int i = 0; i < content.length(); i++) {
|
||||
j = content.charAt(i);
|
||||
|
||||
if (Character.isDigit(j) || Character.isLowerCase(j) || Character.isUpperCase(j)) {
|
||||
if (false == filter.accept(j)) {
|
||||
tmp.append(j);
|
||||
} else if (j < 256) {
|
||||
tmp.append("%");
|
||||
@ -75,7 +106,7 @@ public class EscapeUtil {
|
||||
|
||||
/**
|
||||
* Escape解码
|
||||
*
|
||||
*
|
||||
* @param content 被转义的内容
|
||||
* @return 解码后的字符串
|
||||
*/
|
||||
@ -115,7 +146,7 @@ public class EscapeUtil {
|
||||
|
||||
/**
|
||||
* 安全的unescape文本,当文本不是被escape的时候,返回原文。
|
||||
*
|
||||
*
|
||||
* @param content 内容
|
||||
* @return 解码后的字符串,如果解码失败返回原字符串
|
||||
*/
|
||||
|
@ -12,6 +12,29 @@ public class EscapeUtilTest {
|
||||
|
||||
String result = EscapeUtil.unescapeHtml4("振荡器类型");
|
||||
Assert.assertEquals("振荡器类型", result);
|
||||
|
||||
|
||||
String escape = EscapeUtil.escapeHtml4("*@-_+./(123你好)");
|
||||
Assert.assertEquals("*@-_+./(123你好)", escape);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void escapeTest(){
|
||||
String str = "*@-_+./(123你好)ABCabc";
|
||||
String escape = EscapeUtil.escape(str);
|
||||
Assert.assertEquals("*@-_+./%28123%u4f60%u597d%29ABCabc", escape);
|
||||
|
||||
String unescape = EscapeUtil.unescape(escape);
|
||||
Assert.assertEquals(str, unescape);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void escapeAllTest(){
|
||||
String str = "*@-_+./(123你好)ABCabc";
|
||||
|
||||
String escape = EscapeUtil.escapeAll(str);
|
||||
Assert.assertEquals("%2a%40%2d%5f%2b%2e%2f%28%31%32%33%u4f60%u597d%29%41%42%43%61%62%63", escape);
|
||||
|
||||
String unescape = EscapeUtil.unescape(escape);
|
||||
Assert.assertEquals(str, unescape);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user