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.decoder.ValueDecoder;
import com.reandroid.arsc.value.*; import com.reandroid.arsc.value.*;
import com.reandroid.common.EntryStore; import com.reandroid.common.EntryStore;
import com.reandroid.xml.XMLElement;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
@ -40,11 +39,18 @@ class BagDecoderArray<OUTPUT> extends BagDecoder<OUTPUT>{
writer.attribute("name", entry.getName()); writer.attribute("name", entry.getName());
PackageBlock packageBlock = entry.getPackageBlock(); PackageBlock packageBlock = entry.getPackageBlock();
EntryStore entryStore = getEntryStore();
ResValueMap[] resValueMaps = mapEntry.listResValueMap(); ResValueMap[] resValueMaps = mapEntry.listResValueMap();
boolean zero_name = isZeroNameArray(resValueMaps);
for(int i = 0; i < resValueMaps.length; i++){ for(int i = 0; i < resValueMaps.length; i++){
ResValueMap valueMap = resValueMaps[i]; ResValueMap valueMap = resValueMaps[i];
String childTag = "item"; String childTag = "item";
writer.startTag(childTag); writer.startTag(childTag);
if(zero_name){
String name = ValueDecoder.decodeAttributeName(
entryStore, packageBlock, valueMap.getName());
writer.attribute("name", name);
}
writeText(writer, packageBlock, valueMap); writeText(writer, packageBlock, valueMap);
writer.endTag(childTag); writer.endTag(childTag);
} }
@ -73,14 +79,20 @@ class BagDecoderArray<OUTPUT> extends BagDecoder<OUTPUT>{
if(parentId!=0){ if(parentId!=0){
return false; return false;
} }
ResValueMap[] bagItems = mapEntry.listResValueMap(); ResValueMap[] valueMapList = mapEntry.listResValueMap();
if(bagItems==null||bagItems.length==0){ if(valueMapList == null || valueMapList.length == 0){
return false; return false;
} }
int len=bagItems.length; if(isIndexedArray(valueMapList)){
for(int i=0;i<len;i++){ return true;
ResValueMap item=bagItems[i]; }
int name = item.getName(); 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; int high = (name >> 16) & 0xffff;
if(high!=0x0100 && high!=0x0200){ if(high!=0x0100 && high!=0x0200){
return false; return false;
@ -93,4 +105,16 @@ class BagDecoderArray<OUTPUT> extends BagDecoder<OUTPUT>{
} }
return true; 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 * Copyright (C) 2022 github.com/REAndroid
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -71,11 +71,7 @@ class ValuesEncoder {
type=getType(xmlDocument, type); type=getType(xmlDocument, type);
XMLValuesEncoder encoder; XMLValuesEncoder encoder;
if(isBag(xmlDocument, type)){ if(isBag(xmlDocument, type)){
if("array".equals(type) && hasNameAttributes(xmlDocument)){
encoder = getBagEncoder("style");
}else{
encoder = getBagEncoder(type); encoder = getBagEncoder(type);
}
}else{ }else{
encoder=getEncoder(type); encoder=getEncoder(type);
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (C) 2022 github.com/REAndroid * Copyright (C) 2022 github.com/REAndroid
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * 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)){ }else if(ApkUtil.TAG_INTEGER_ARRAY.equals(tagName)){
force_integer = true; force_integer = true;
} }
EncodeMaterials materials = getMaterials();
ResValueMapArray itemArray = mapEntry.getValue(); ResValueMapArray itemArray = mapEntry.getValue();
for(int i=0;i<count;i++){ for(int i=0;i<count;i++){
XMLElement child=parentElement.getChildAt(i); XMLElement child=parentElement.getChildAt(i);
ResValueMap bagItem = itemArray.get(i); ResValueMap bagItem = itemArray.get(i);
String name = child.getAttributeValue("name");
if(name == null){
bagItem.setNameHigh((short) 0x0100); bagItem.setNameHigh((short) 0x0100);
bagItem.setNameLow((short) (i+1)); 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(); String valueText=child.getTextContent();
if(ValueDecoder.isReference(valueText)){ if(ValueDecoder.isReference(valueText)){

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (C) 2022 github.com/REAndroid * Copyright (C) 2022 github.com/REAndroid
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -102,10 +102,13 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
XMLElement child=element.getChildAt(i); XMLElement child=element.getChildAt(i);
String name = child.getAttributeValue("name"); String name = child.getAttributeValue("name");
int resourceId = decodeUnknownAttributeHex(name); Integer unknown = decodeUnknownAttributeHex(name);
if(resourceId==0){ int resourceId;
resourceId=materials.resolveLocalResourceId("id", if(unknown == null){
resourceId = materials.resolveLocalResourceId("id",
name); name);
}else {
resourceId = unknown;
} }
ValueDecoder.EncodeResult encodeResult = ValueDecoder.EncodeResult encodeResult =
@ -148,14 +151,4 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
String tagName=parent.getChildAt(0).getTagName(); String tagName=parent.getChildAt(0).getTagName();
return "enum".equals(tagName); 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 * Copyright (C) 2022 github.com/REAndroid
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -15,6 +15,7 @@
*/ */
package com.reandroid.apk.xmlencoder; package com.reandroid.apk.xmlencoder;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.Entry; import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry; import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.xml.XMLElement; import com.reandroid.xml.XMLElement;
@ -49,4 +50,15 @@ class XMLValuesEncoderBag extends XMLValuesEncoder{
void encodeNullValue(Entry entry){ void encodeNullValue(Entry entry){
// Nothing to do // 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 * Copyright (C) 2022 github.com/REAndroid
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -71,16 +71,6 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
encodeChild(child, attributeEntry, item); 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){ private void encodeChild(XMLElement child, Entry attributeEntry, ResValueMap bagItem){
bagItem.setName(attributeEntry.getResourceId()); bagItem.setName(attributeEntry.getResourceId());