fix encode decode errors

This commit is contained in:
REAndroid 2023-05-04 01:21:41 +02:00
parent fd6d756482
commit 1b240b2281
9 changed files with 159 additions and 36 deletions

View File

@ -18,6 +18,7 @@ package com.reandroid.apk.xmldecoder;
import com.reandroid.apk.XmlHelper;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.arsc.value.attribute.AttributeBag;
import com.reandroid.arsc.value.attribute.AttributeBagItem;
import com.reandroid.common.EntryStore;
@ -56,7 +57,7 @@ class BagDecoderAttr<OUTPUT> extends BagDecoder<OUTPUT>{
writer.attribute("name", name);
int rawVal = item.getData();
String value;
if(is_flag){
if(item.getBagItem().getValueType() == ValueType.INT_HEX){
value = String.format("0x%08x", rawVal);
}else {
value = String.valueOf(rawVal);

View File

@ -84,7 +84,13 @@ class XMLValuesEncoder {
}
void encodeReferenceValue(Entry entry, String value){
int resourceId = getMaterials().resolveReference(value);
entry.setValueAsReference(resourceId);
ValueType valueType;
if(value.charAt(0) == '?'){
valueType = ValueType.ATTRIBUTE;
}else{
valueType = ValueType.REFERENCE;
}
entry.setValueAsRaw(valueType, resourceId);
}
void encodeStringValue(Entry entry, String value){

View File

@ -46,8 +46,16 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
bagItem.setNameLow((short) (i+1));
String valueText=child.getTextContent();
if(force_string){
if(ValueDecoder.isReference(valueText)){
ValueType valueType;
if(valueText.charAt(0) == '?'){
valueType = ValueType.ATTRIBUTE;
}else {
valueType = ValueType.REFERENCE;
}
bagItem.setTypeAndData(valueType,
getMaterials().resolveReference(valueText));
}else if(force_string){
bagItem.setValueAsString(ValueDecoder
.unEscapeSpecialCharacter(valueText));
}else if(force_integer){
@ -59,9 +67,6 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
}
bagItem.setTypeAndData(ValueType.INT_DEC,
ValueDecoder.parseInteger(valueText));
}else if(ValueDecoder.isReference(valueText)){
bagItem.setTypeAndData(ValueType.REFERENCE,
getMaterials().resolveReference(valueText));
}else if(EncodeUtil.isEmpty(valueText)) {
bagItem.setTypeAndData(ValueType.NULL, 0);
}else {

View File

@ -134,6 +134,20 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
}
return 0;
}
private boolean isFlag(XMLElement parent){
if(parent.getChildesCount()==0){
return false;
}
String tagName=parent.getChildAt(0).getTagName();
return "flag".equals(tagName);
}
private boolean isEnum(XMLElement parent){
if(parent.getChildesCount()==0){
return false;
}
String tagName=parent.getChildAt(0).getTagName();
return "enum".equals(tagName);
}
private int decodeUnknownAttributeHex(String name){
if(name.length()==0||name.charAt(0)!='@'){
return 0;

View File

@ -331,6 +331,9 @@ public class PackageBlock extends Chunk<PackageHeader>
public SpecTypePair getSpecTypePair(String typeName){
return getSpecTypePairArray().getSpecTypePair(typeName);
}
public SpecTypePair getSpecTypePair(int typeId){
return getSpecTypePairArray().getPair((byte) typeId);
}
public EntryGroup getEntryGroup(String typeName, String entryName){
return getSpecTypePairArray().getEntryGroup(typeName, entryName);
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* 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 com.reandroid.arsc.decoder;
import com.reandroid.arsc.value.ValueType;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ColorUtil {
public static String decode(ValueType valueType, int data){
if(valueType == null){
return null;
}
int index;
switch (valueType){
case INT_COLOR_RGB4:
index = 5;
break;
case INT_COLOR_ARGB4:
index = 4;
break;
case INT_COLOR_RGB8:
index = 2;
break;
case INT_COLOR_ARGB8:
index = 0;
break;
default:
return null;
}
String hex = String.format("%08x", data);
return "#" + hex.substring(index);
}
public static ValueDecoder.EncodeResult encode(String hexColor){
if(hexColor == null){
return null;
}
hexColor = hexColor.toUpperCase();
Matcher matcher = PATTERN_COLOR.matcher(hexColor);
if(!matcher.matches()){
return null;
}
char[] s = hexColor.toCharArray();
int len = s.length;
ValueType valueType;
int color = 0;
if (len == 4) {
valueType = ValueType.INT_COLOR_RGB4;
color |= 0xFF0000;
color |= get_hex(s[1]) << 20;
color |= get_hex(s[1]) << 16;
color |= get_hex(s[2]) << 12;
color |= get_hex(s[2]) << 8;
color |= get_hex(s[3]) << 4;
color |= get_hex(s[3]);
} else if (len == 5) {
valueType = ValueType.INT_COLOR_ARGB4;
color |= 0xFFFF0000;
color |= get_hex(s[1]) << 28;
color |= get_hex(s[1]) << 24;
color |= get_hex(s[2]) << 20;
color |= get_hex(s[2]) << 16;
color |= get_hex(s[3]) << 12;
color |= get_hex(s[3]) << 8;
color |= get_hex(s[4]) << 4;
color |= get_hex(s[4]);
} else if (len == 7) {
valueType = ValueType.INT_COLOR_RGB8;
color |= 0xFF000000;
color |= get_hex(s[1]) << 20;
color |= get_hex(s[2]) << 16;
color |= get_hex(s[3]) << 12;
color |= get_hex(s[4]) << 8;
color |= get_hex(s[5]) << 4;
color |= get_hex(s[6]);
} else if (len == 9) {
valueType = ValueType.INT_COLOR_ARGB8;
color |= get_hex(s[1]) << 28;
color |= get_hex(s[2]) << 24;
color |= get_hex(s[3]) << 20;
color |= get_hex(s[4]) << 16;
color |= get_hex(s[5]) << 12;
color |= get_hex(s[6]) << 8;
color |= get_hex(s[7]) << 4;
color |= get_hex(s[8]);
}else {
return null;
}
return new ValueDecoder.EncodeResult(valueType, color);
}
private static int get_hex(char ch){
if(ch <= '9'){
return ch - '0';
}
return 10 + (ch - 'A');
}
public static final Pattern PATTERN_COLOR = Pattern.compile("^#([0-9a-fA-F]{3,8})$");
}

View File

@ -165,21 +165,7 @@ public class ValueDecoder {
return false;
}
public static EncodeResult encodeColor(String value){
if(value==null){
return null;
}
Matcher matcher = PATTERN_COLOR.matcher(value);
if(!matcher.find()){
return null;
}
value=matcher.group(1);
ValueType valueType;
if(value.length()==6){
valueType=ValueType.INT_COLOR_RGB8;
}else {
valueType=ValueType.INT_COLOR_ARGB8;
}
return new EncodeResult(valueType, parseHex(value));
return ColorUtil.encode(value);
}
public static EncodeResult encodeHexOrInt(String numString){
if(numString==null){
@ -468,14 +454,13 @@ public class ValueDecoder {
if(valueType==null){
return null;
}
String hexColor = ColorUtil.decode(valueType, data);
if(hexColor != null){
return hexColor;
}
switch (valueType){
case INT_BOOLEAN:
return decodeBoolean(data);
case INT_COLOR_ARGB4:
case INT_COLOR_ARGB8:
case INT_COLOR_RGB4:
case INT_COLOR_RGB8:
return decodeColor(data);
case DIMENSION:
case FLOAT:
case FRACTION:
@ -739,13 +724,6 @@ public class ValueDecoder {
return "false";
}
private static String decodeColor(int rawVal){
String hex=String.format("%x", rawVal);
if(hex.length()<=6){
return String.format("#%06x", rawVal);
}
return String.format("#%08x", rawVal);
}
private static String decodeDimensionOrFloat(ValueType valueType, int rawVal){
if(valueType==ValueType.FLOAT){
float f=Float.intBitsToFloat(rawVal);
@ -836,7 +814,6 @@ public class ValueDecoder {
}
}
public static final Pattern PATTERN_COLOR = Pattern.compile("^#([0-9a-fA-F]{6,8})$");
public static final Pattern PATTERN_DIMEN = Pattern.compile("^([+\\-]?[0-9]+(\\.[0-9]+(E\\+?-?[0-9]+)?)?)(px|di?p|sp|pt|in|mm|%p?)$");
private static final Pattern PATTERN_INTEGER = Pattern.compile("^(-?)([0-9]+)$");
private static final Pattern PATTERN_HEX = Pattern.compile("^0x[0-9a-fA-F]+$");

View File

@ -47,7 +47,7 @@ public class ResNameMap<VALUE> {
valueMap=new HashMap<>();
mainMap.put(type, valueMap);
}
valueMap.put(name, value);
valueMap.putIfAbsent(name, value);
}
}
public void clear(){

View File

@ -229,6 +229,9 @@ import java.util.Objects;
&& Objects.equals(str, getValueAsString())){
return;
}
if(str == null){
str = "";
}
StringItem stringItem = getStringPool().getOrCreate(str);
setData(stringItem.getIndex());
setValueType(ValueType.STRING);