fix encoding of array type bag entries

This commit is contained in:
REAndroid 2023-05-05 18:10:32 +02:00
parent eac14028fd
commit f6ad9d1ba8
6 changed files with 72 additions and 42 deletions

View File

@ -21,7 +21,6 @@ import com.reandroid.arsc.chunk.PackageBlock;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.*;
import com.reandroid.common.EntryStore;
import com.reandroid.xml.XMLElement;
import java.io.IOException;
import java.util.HashSet;
@ -40,11 +39,18 @@ class BagDecoderArray<OUTPUT> extends BagDecoder<OUTPUT>{
writer.attribute("name", entry.getName());
PackageBlock packageBlock = entry.getPackageBlock();
EntryStore entryStore = getEntryStore();
ResValueMap[] resValueMaps = mapEntry.listResValueMap();
boolean zero_name = isZeroNameArray(resValueMaps);
for(int i = 0; i < resValueMaps.length; i++){
ResValueMap valueMap = resValueMaps[i];
String childTag = "item";
writer.startTag(childTag);
if(zero_name){
String name = ValueDecoder.decodeAttributeName(
entryStore, packageBlock, valueMap.getName());
writer.attribute("name", name);
}
writeText(writer, packageBlock, valueMap);
writer.endTag(childTag);
}
@ -73,14 +79,20 @@ class BagDecoderArray<OUTPUT> extends BagDecoder<OUTPUT>{
if(parentId!=0){
return false;
}
ResValueMap[] bagItems = mapEntry.listResValueMap();
if(bagItems==null||bagItems.length==0){
ResValueMap[] valueMapList = mapEntry.listResValueMap();
if(valueMapList == null || valueMapList.length == 0){
return false;
}
int len=bagItems.length;
for(int i=0;i<len;i++){
ResValueMap item=bagItems[i];
int name = item.getName();
if(isIndexedArray(valueMapList)){
return true;
}
return isZeroNameArray(valueMapList);
}
private static boolean isIndexedArray(ResValueMap[] resValueMapList){
int length = resValueMapList.length;
for(int i = 0; i < length; i++){
ResValueMap valueMap = resValueMapList[i];
int name = valueMap.getName();
int high = (name >> 16) & 0xffff;
if(high!=0x0100 && high!=0x0200){
return false;
@ -93,4 +105,16 @@ class BagDecoderArray<OUTPUT> extends BagDecoder<OUTPUT>{
}
return true;
}
private static boolean isZeroNameArray(ResValueMap[] resValueMapList){
int length = resValueMapList.length;
for(int i = 0; i < length; i++){
if(!isZeroName(resValueMapList[i])){
return false;
}
}
return true;
}
private static boolean isZeroName(ResValueMap resValueMap){
return resValueMap.getName() == 0;
}
}

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -71,11 +71,7 @@ class ValuesEncoder {
type=getType(xmlDocument, type);
XMLValuesEncoder encoder;
if(isBag(xmlDocument, type)){
if("array".equals(type) && hasNameAttributes(xmlDocument)){
encoder = getBagEncoder("style");
}else{
encoder = getBagEncoder(type);
}
encoder = getBagEncoder(type);
}else{
encoder=getEncoder(type);
}

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -38,12 +38,27 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
}else if(ApkUtil.TAG_INTEGER_ARRAY.equals(tagName)){
force_integer = true;
}
EncodeMaterials materials = getMaterials();
ResValueMapArray itemArray = mapEntry.getValue();
for(int i=0;i<count;i++){
XMLElement child=parentElement.getChildAt(i);
ResValueMap bagItem = itemArray.get(i);
bagItem.setNameHigh((short) 0x0100);
bagItem.setNameLow((short) (i+1));
String name = child.getAttributeValue("name");
if(name == null){
bagItem.setNameHigh((short) 0x0100);
bagItem.setNameLow((short) (i+1));
}else {
Integer unknown = decodeUnknownAttributeHex(name);
int resourceId;
if(unknown == null){
resourceId = materials.resolveLocalResourceId("id", name);
}else {
resourceId = unknown;
}
bagItem.setName(resourceId);
}
String valueText=child.getTextContent();
if(ValueDecoder.isReference(valueText)){

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -102,10 +102,13 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
XMLElement child=element.getChildAt(i);
String name = child.getAttributeValue("name");
int resourceId = decodeUnknownAttributeHex(name);
if(resourceId==0){
resourceId=materials.resolveLocalResourceId("id",
Integer unknown = decodeUnknownAttributeHex(name);
int resourceId;
if(unknown == null){
resourceId = materials.resolveLocalResourceId("id",
name);
}else {
resourceId = unknown;
}
ValueDecoder.EncodeResult encodeResult =
@ -148,14 +151,4 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
String tagName=parent.getChildAt(0).getTagName();
return "enum".equals(tagName);
}
private int decodeUnknownAttributeHex(String name){
if(name.length()==0||name.charAt(0)!='@'){
return 0;
}
name=name.substring(1);
if(!ValueDecoder.isHex(name)){
return 0;
}
return ValueDecoder.parseHex(name);
}
}

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -15,6 +15,7 @@
*/
package com.reandroid.apk.xmlencoder;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.xml.XMLElement;
@ -49,4 +50,15 @@ class XMLValuesEncoderBag extends XMLValuesEncoder{
void encodeNullValue(Entry entry){
// Nothing to do
}
Integer decodeUnknownAttributeHex(String name){
if(name.length() == 0 || (name.charAt(0) !='@' && name.charAt(0) != '?')){
return null;
}
name = name.substring(1);
if(!ValueDecoder.isHex(name)){
return null;
}
return ValueDecoder.parseHex(name);
}
}

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -71,16 +71,6 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
encodeChild(child, attributeEntry, item);
}
}
private Integer decodeUnknownAttributeHex(String name){
if(name.length()==0||(name.charAt(0)!='@' && name.charAt(0)!='?')){
return null;
}
name=name.substring(1);
if(!ValueDecoder.isHex(name)){
return null;
}
return ValueDecoder.parseHex(name);
}
private void encodeChild(XMLElement child, Entry attributeEntry, ResValueMap bagItem){
bagItem.setName(attributeEntry.getResourceId());