mirror of
https://github.com/revanced/Apktool.git
synced 2025-02-01 14:47:56 +01:00
Added ResXmlEncoders class and use it instead of encoding methods in AndrolibResources.
This commit is contained in:
parent
30add278d5
commit
e23bf8e70d
@ -27,7 +27,6 @@ import brut.androlib.res.util.*;
|
|||||||
import brut.common.BrutException;
|
import brut.common.BrutException;
|
||||||
import brut.directory.*;
|
import brut.directory.*;
|
||||||
import brut.util.*;
|
import brut.util.*;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -485,98 +484,6 @@ final public class AndrolibResources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String escapeTextForResXml(String value) {
|
|
||||||
return escapeTextForResXml(value, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String escapeTextForResXml(String value,
|
|
||||||
boolean escapeChars) {
|
|
||||||
if (value.isEmpty()) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (escapeChars) {
|
|
||||||
value = escapeCharsForResXml(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder out = new StringBuilder(value.length() + 10);
|
|
||||||
char[] chars = value.toCharArray();
|
|
||||||
|
|
||||||
switch (chars[0]) {
|
|
||||||
case '@':
|
|
||||||
case '#':
|
|
||||||
case '?':
|
|
||||||
out.append('\\');
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean space = true;
|
|
||||||
for (char c : chars) {
|
|
||||||
if (c == ' ') {
|
|
||||||
if (space) {
|
|
||||||
out.append("\\u0020");
|
|
||||||
} else {
|
|
||||||
out.append(c);
|
|
||||||
space = true;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
space = false;
|
|
||||||
out.append(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (space && out.charAt(out.length() - 1) == ' ') {
|
|
||||||
out.deleteCharAt(out.length() - 1);
|
|
||||||
out.append("\\u0020");
|
|
||||||
}
|
|
||||||
|
|
||||||
return out.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String escapeCharsForResXml(String value) {
|
|
||||||
if (value.isEmpty()) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder out = new StringBuilder(value.length() + 10);
|
|
||||||
for (char c : value.toCharArray()) {
|
|
||||||
switch (c) {
|
|
||||||
case '\\':
|
|
||||||
case '\'':
|
|
||||||
out.append('\\');
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
out.append("\\"");
|
|
||||||
continue;
|
|
||||||
case '\n':
|
|
||||||
out.append("\\n");
|
|
||||||
continue;
|
|
||||||
case '&':
|
|
||||||
out.append("&");
|
|
||||||
continue;
|
|
||||||
case '<':
|
|
||||||
out.append("<");
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
if (! isPrintableChar(c)) {
|
|
||||||
out.append(String.format("\\u%04x", (int)c));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out.append(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return out.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isPrintableChar(char c) {
|
|
||||||
Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
|
|
||||||
return ! Character.isISOControl(c)
|
|
||||||
&& c != KeyEvent.CHAR_UNDEFINED
|
|
||||||
&& block != null
|
|
||||||
&& block != Character.UnicodeBlock.SPECIALS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: dirty static hack. I have to refactor decoding mechanisms.
|
// TODO: dirty static hack. I have to refactor decoding mechanisms.
|
||||||
public static boolean sKeepBroken = false;
|
public static boolean sKeepBroken = false;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package brut.androlib.res.data.value;
|
package brut.androlib.res.data.value;
|
||||||
|
|
||||||
import brut.androlib.AndrolibException;
|
import brut.androlib.AndrolibException;
|
||||||
|
import brut.androlib.res.xml.ResXmlEncoders;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
@ -33,12 +34,12 @@ public class ResStringValue extends ResScalarValue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String encodeAsResXmlAttr() {
|
public String encodeAsResXmlAttr() {
|
||||||
return mRawValue;
|
return ResXmlEncoders.encodeAsResXmlAttr(mRawValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String encodeAsResXmlValue() {
|
public String encodeAsResXmlValue() {
|
||||||
return mRawValue;
|
return ResXmlEncoders.encodeAsXmlValue(mRawValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -23,6 +23,7 @@ import java.io.Reader;
|
|||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import brut.androlib.AndrolibException;
|
import brut.androlib.AndrolibException;
|
||||||
|
import brut.androlib.res.xml.ResXmlEncoders;
|
||||||
import brut.util.ExtDataInput;
|
import brut.util.ExtDataInput;
|
||||||
import com.mindprod.ledatastream.LEDataInputStream;
|
import com.mindprod.ledatastream.LEDataInputStream;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -312,7 +313,8 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
if (mAttrDecoder != null) {
|
if (mAttrDecoder != null) {
|
||||||
try {
|
try {
|
||||||
return mAttrDecoder.decode(valueType, valueData,
|
return mAttrDecoder.decode(valueType, valueData,
|
||||||
valueRaw == -1 ? null : m_strings.getString(valueRaw),
|
valueRaw == -1 ? null : ResXmlEncoders.escapeXmlChars(
|
||||||
|
m_strings.getString(valueRaw)),
|
||||||
getAttributeNameResource(index));
|
getAttributeNameResource(index));
|
||||||
} catch (AndrolibException ex) {
|
} catch (AndrolibException ex) {
|
||||||
setFirstError(ex);
|
setFirstError(ex);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package brut.androlib.res.decoder;
|
package brut.androlib.res.decoder;
|
||||||
|
|
||||||
import brut.androlib.res.AndrolibResources;
|
import brut.androlib.res.AndrolibResources;
|
||||||
|
import brut.androlib.res.xml.ResXmlEncoders;
|
||||||
import brut.util.ExtDataInput;
|
import brut.util.ExtDataInput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -126,7 +127,7 @@ public class StringBlock {
|
|||||||
}
|
}
|
||||||
int[] style = getStyle(index);
|
int[] style = getStyle(index);
|
||||||
if (style == null) {
|
if (style == null) {
|
||||||
return AndrolibResources.escapeTextForResXml(raw);
|
return ResXmlEncoders.escapeXmlChars(raw);
|
||||||
}
|
}
|
||||||
StringBuilder html = new StringBuilder(raw.length() + 32);
|
StringBuilder html = new StringBuilder(raw.length() + 32);
|
||||||
int[] opened = new int[style.length / 3];
|
int[] opened = new int[style.length / 3];
|
||||||
@ -149,7 +150,7 @@ public class StringBlock {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (offset <= end) {
|
if (offset <= end) {
|
||||||
html.append(AndrolibResources.escapeCharsForResXml(
|
html.append(ResXmlEncoders.escapeXmlChars(
|
||||||
raw.substring(offset, end + 1)));
|
raw.substring(offset, end + 1)));
|
||||||
offset = end + 1;
|
offset = end + 1;
|
||||||
}
|
}
|
||||||
@ -157,7 +158,7 @@ public class StringBlock {
|
|||||||
}
|
}
|
||||||
depth = j + 1;
|
depth = j + 1;
|
||||||
if (offset < start) {
|
if (offset < start) {
|
||||||
html.append(AndrolibResources.escapeCharsForResXml(
|
html.append(ResXmlEncoders.escapeXmlChars(
|
||||||
raw.substring(offset, start)));
|
raw.substring(offset, start)));
|
||||||
offset = start;
|
offset = start;
|
||||||
}
|
}
|
||||||
@ -168,7 +169,7 @@ public class StringBlock {
|
|||||||
style[i + 1] = -1;
|
style[i + 1] = -1;
|
||||||
opened[depth++] = i;
|
opened[depth++] = i;
|
||||||
}
|
}
|
||||||
return AndrolibResources.escapeTextForResXml(html.toString(), false);
|
return html.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void outputStyleTag(String tag, StringBuilder builder,
|
private void outputStyleTag(String tag, StringBuilder builder,
|
||||||
@ -199,7 +200,7 @@ public class StringBlock {
|
|||||||
val = tag.substring(pos2 + 1);
|
val = tag.substring(pos2 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.append(AndrolibResources.escapeCharsForResXml(val))
|
builder.append(ResXmlEncoders.escapeXmlChars(val))
|
||||||
.append('"');
|
.append('"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2011 Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package brut.androlib.res.xml;
|
||||||
|
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
|
*/
|
||||||
|
public final class ResXmlEncoders {
|
||||||
|
|
||||||
|
public static String escapeXmlChars(String str) {
|
||||||
|
return str.replace("&", "&").replace("<", "<");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodeAsResXmlAttr(String str) {
|
||||||
|
if (str.isEmpty()) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] chars = str.toCharArray();
|
||||||
|
StringBuilder out = new StringBuilder(str.length() + 10);
|
||||||
|
|
||||||
|
switch (chars[0]) {
|
||||||
|
case '#':
|
||||||
|
case '@':
|
||||||
|
case '?':
|
||||||
|
out.append('\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (char c : chars) {
|
||||||
|
switch (c) {
|
||||||
|
case '\\':
|
||||||
|
out.append('\\');
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
out.append(""");
|
||||||
|
continue;
|
||||||
|
case '\n':
|
||||||
|
out.append("\\n");
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
if (!isPrintableChar(c)) {
|
||||||
|
out.append(String.format("\\u%04x", (int) c));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodeAsXmlValue(String str) {
|
||||||
|
if (str.isEmpty()) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] chars = str.toCharArray();
|
||||||
|
StringBuilder out = new StringBuilder(str.length() + 10);
|
||||||
|
|
||||||
|
switch (chars[0]) {
|
||||||
|
case '#':
|
||||||
|
case '@':
|
||||||
|
case '?':
|
||||||
|
out.append('\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isInStyleTag = false;
|
||||||
|
boolean enclose = false;
|
||||||
|
boolean wasSpace = true;
|
||||||
|
for (char c : chars) {
|
||||||
|
if (isInStyleTag) {
|
||||||
|
if (c == '>') {
|
||||||
|
isInStyleTag = false;
|
||||||
|
}
|
||||||
|
} else if (c == ' ') {
|
||||||
|
if (wasSpace) {
|
||||||
|
enclose = true;
|
||||||
|
}
|
||||||
|
wasSpace = true;
|
||||||
|
} else {
|
||||||
|
wasSpace = false;
|
||||||
|
switch (c) {
|
||||||
|
case '\\':
|
||||||
|
out.append('\\');
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
case '\n':
|
||||||
|
enclose = true;
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
out.append('\\');
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
isInStyleTag = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!isPrintableChar(c)) {
|
||||||
|
out.append(String.format("\\u%04x", (int) c));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enclose || wasSpace) {
|
||||||
|
out.insert(0, '"').append('"');
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrintableChar(char c) {
|
||||||
|
Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
|
||||||
|
return !Character.isISOControl(c)
|
||||||
|
&& c != KeyEvent.CHAR_UNDEFINED
|
||||||
|
&& block != null
|
||||||
|
&& block != Character.UnicodeBlock.SPECIALS;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user