From aecdc77648346a2cb1c591c48c99e51ace3beb9b Mon Sep 17 00:00:00 2001 From: REAndroid Date: Thu, 5 Jan 2023 08:56:57 -0500 Subject: [PATCH] escape special characters on decode/encode --- .../lib/apk/ApkModuleXmlDecoder.java | 3 +- .../lib/apk/xmlencoder/XMLFileEncoder.java | 6 ++-- .../apk/xmlencoder/XMLValuesEncoderArray.java | 6 ++-- .../xmlencoder/XMLValuesEncoderCommon.java | 3 +- .../xmlencoder/XMLValuesEncoderPlurals.java | 3 +- .../xmlencoder/XMLValuesEncoderString.java | 4 +-- .../apk/xmlencoder/XMLValuesEncoderStyle.java | 5 +-- .../lib/arsc/chunk/xml/ResXmlAttribute.java | 2 +- .../lib/arsc/chunk/xml/ResXmlElement.java | 4 ++- .../lib/arsc/decoder/ValueDecoder.java | 34 +++++++++++++++++-- 10 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/reandroid/lib/apk/ApkModuleXmlDecoder.java b/src/main/java/com/reandroid/lib/apk/ApkModuleXmlDecoder.java index 55da65a..a04dfec 100644 --- a/src/main/java/com/reandroid/lib/apk/ApkModuleXmlDecoder.java +++ b/src/main/java/com/reandroid/lib/apk/ApkModuleXmlDecoder.java @@ -229,7 +229,8 @@ import java.util.*; String value; ResValueInt resValueInt=(ResValueInt) entryBlock.getResValue(); if(resValueInt.getValueType()== ValueType.STRING){ - value=resValueInt.getValueAsString(); + value=ValueDecoder.escapeSpecialCharacter( + resValueInt.getValueAsString()); }else { value= ValueDecoder.decodeEntryValue(entryStore, entryBlock.getPackageBlock(), diff --git a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLFileEncoder.java b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLFileEncoder.java index 4013df2..53d4cde 100644 --- a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLFileEncoder.java +++ b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLFileEncoder.java @@ -141,7 +141,8 @@ public class XMLFileEncoder { continue; } if(attributeBag.isEqualType(AttributeValueType.STRING)) { - xmlAttribute.setValueAsString(valueText); + xmlAttribute.setValueAsString(ValueDecoder + .unEscapeSpecialCharacter(valueText)); continue; } } @@ -155,7 +156,8 @@ public class XMLFileEncoder { xmlAttribute.setValueType(encodeResult.valueType); xmlAttribute.setRawValue(encodeResult.value); }else { - xmlAttribute.setValueAsString(valueText); + xmlAttribute.setValueAsString(ValueDecoder + .unEscapeSpecialCharacter(valueText)); } } } diff --git a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderArray.java b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderArray.java index e5d5b50..ef100ef 100644 --- a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderArray.java +++ b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderArray.java @@ -51,10 +51,12 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{ bagItem.setTypeAndData(encodeResult.valueType, encodeResult.value); }else { - bagItem.setValueAsString(valueText); + bagItem.setValueAsString(ValueDecoder + .unEscapeSpecialCharacter(valueText)); } }else { - bagItem.setValueAsString(valueText); + bagItem.setValueAsString(ValueDecoder + .unEscapeSpecialCharacter(valueText)); } } } diff --git a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderCommon.java b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderCommon.java index 7cb999e..d09c3de 100644 --- a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderCommon.java +++ b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderCommon.java @@ -31,7 +31,8 @@ class XMLValuesEncoderCommon extends XMLValuesEncoder{ if(encodeResult!=null){ entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value); }else { - entryBlock.setValueAsString(value); + entryBlock.setValueAsString(ValueDecoder + .unEscapeSpecialCharacter(value)); } } } diff --git a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderPlurals.java b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderPlurals.java index c6831e8..15e252b 100644 --- a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderPlurals.java +++ b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderPlurals.java @@ -52,7 +52,8 @@ class XMLValuesEncoderPlurals extends XMLValuesEncoderBag{ bagItem.setType(ValueType.NULL); bagItem.setData(0); }else{ - bagItem.setValueAsString(valueText); + bagItem.setValueAsString(ValueDecoder + .unEscapeSpecialCharacter(valueText)); } } } diff --git a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderString.java b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderString.java index 7f1df0d..5d133c3 100644 --- a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderString.java +++ b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderString.java @@ -34,7 +34,7 @@ class XMLValuesEncoderString extends XMLValuesEncoder{ } @Override void encodeStringValue(EntryBlock entryBlock, String value){ - entryBlock.setValueAsString(value); + entryBlock.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value)); } @Override void encodeNullValue(EntryBlock entryBlock){ @@ -53,7 +53,7 @@ class XMLValuesEncoderString extends XMLValuesEncoder{ if(value==null || ValueDecoder.isReference(value)){ continue; } - stringList.add(value); + stringList.add(ValueDecoder.unEscapeSpecialCharacter(value)); } getMaterials().addTableStringPool(stringList); } diff --git a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderStyle.java b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderStyle.java index 2becc91..0914375 100644 --- a/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderStyle.java +++ b/src/main/java/com/reandroid/lib/apk/xmlencoder/XMLValuesEncoderStyle.java @@ -66,7 +66,8 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{ } bagItem.setData(getMaterials().resolveReference(valueText)); }else if(attributeBag.isEqualType(AttributeValueType.STRING)) { - bagItem.setValueAsString(valueText); + bagItem.setValueAsString(ValueDecoder + .unEscapeSpecialCharacter(valueText)); }else if(EncodeUtil.isEmpty(valueText)) { bagItem.setTypeAndData(ValueType.NULL, 0); }else{ @@ -75,7 +76,7 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{ bagItem.setTypeAndData(encodeResult.valueType, encodeResult.value); }else { - bagItem.setValueAsString(valueText); + bagItem.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(valueText)); } } } diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java index d22e081..631801a 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java @@ -468,7 +468,7 @@ import java.util.Set; int raw=getRawValue(); String value; if(valueType==ValueType.STRING){ - value = getValueAsString(); + value = ValueDecoder.escapeSpecialCharacter(getValueAsString()); }else { value = ValueDecoder.decode(entryStore, currentPackageId, diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java index 60ed283..fb2c6ff 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java @@ -20,6 +20,7 @@ import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.container.BlockList; import com.reandroid.lib.arsc.container.FixedBlockContainer; import com.reandroid.lib.arsc.container.SingleBlockContainer; +import com.reandroid.lib.arsc.decoder.ValueDecoder; import com.reandroid.lib.arsc.header.HeaderBlock; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.ResXmlString; @@ -759,7 +760,8 @@ import java.util.*; } ResXmlText resXmlText = getResXmlText(); if(resXmlText!=null){ - xmlElement.setTextContent(resXmlText.getText()); + xmlElement.setTextContent( + ValueDecoder.escapeSpecialCharacter(resXmlText.getText())); } return xmlElement; } diff --git a/src/main/java/com/reandroid/lib/arsc/decoder/ValueDecoder.java b/src/main/java/com/reandroid/lib/arsc/decoder/ValueDecoder.java index eba9aed..be5441a 100755 --- a/src/main/java/com/reandroid/lib/arsc/decoder/ValueDecoder.java +++ b/src/main/java/com/reandroid/lib/arsc/decoder/ValueDecoder.java @@ -31,6 +31,34 @@ import java.util.regex.Pattern; public class ValueDecoder { + public static String escapeSpecialCharacter(String text){ + if(text==null || text.length()==0){ + return text; + } + if(isSpecialCharacter(text.charAt(0))){ + return '\\' +text; + } + return text; + } + public static String unEscapeSpecialCharacter(String text){ + if(text==null || text.length()<2){ + return text; + } + if(text.charAt(0)!='\\' || !isSpecialCharacter(text.charAt(1))){ + return text; + } + return text.substring(1); + } + private static boolean isSpecialCharacter(char ch){ + switch (ch){ + case '@': + case '?': + case '#': + return true; + default: + return false; + } + } public static EncodeResult encodeGuessAny(String txt){ if(txt==null){ return null; @@ -574,7 +602,7 @@ import java.util.regex.Pattern; if(tableString==null){ return null; } - return tableString.getHtml(); + return escapeSpecialCharacter(tableString.getHtml()); } private static String decodeString(EntryStore entryStore, int packageOrResourceId, int stringRef){ if(entryStore==null||packageOrResourceId==0){ @@ -606,7 +634,7 @@ import java.util.regex.Pattern; } } if(tableString!=null){ - return tableString.getHtml(); + return escapeSpecialCharacter(tableString.getHtml()); } return null; } @@ -623,7 +651,7 @@ import java.util.regex.Pattern; if(tableString==null){ return null; } - return tableString.getHtml(); + return escapeSpecialCharacter(tableString.getHtml()); } private static String decodeHex(int rawVal){