mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 22:34:24 +02:00
fix XML encode errors
This commit is contained in:
parent
1b9ed9c291
commit
7389358a18
@ -42,9 +42,11 @@ import java.util.*;
|
||||
private final ApkModule apkModule;
|
||||
private final Map<Integer, Set<ResConfig>> decodedEntries;
|
||||
private XMLBagDecoder xmlBagDecoder;
|
||||
private final Set<String> mDecodedPaths;
|
||||
public ApkModuleXmlDecoder(ApkModule apkModule){
|
||||
this.apkModule=apkModule;
|
||||
this.decodedEntries = new HashMap<>();
|
||||
this.mDecodedPaths = new HashSet<>();
|
||||
}
|
||||
public void decodeTo(File outDir)
|
||||
throws IOException, XMLException {
|
||||
@ -60,6 +62,8 @@ import java.util.*;
|
||||
|
||||
decodeAndroidManifest(entryStore, outDir);
|
||||
|
||||
addDecodedPath(TableBlock.FILE_NAME);
|
||||
|
||||
logMessage("Decoding resource files ...");
|
||||
List<ResFile> resFileList=apkModule.listResFiles();
|
||||
for(ResFile resFile:resFileList){
|
||||
@ -76,6 +80,7 @@ import java.util.*;
|
||||
}else {
|
||||
decodeResRaw(outDir, resFile);
|
||||
}
|
||||
addDecodedPath(resFile.getFilePath());
|
||||
}
|
||||
private void decodeResRaw(File outDir, ResFile resFile)
|
||||
throws IOException {
|
||||
@ -147,6 +152,7 @@ import java.util.*;
|
||||
int currentPackageId= manifestBlock.guessCurrentPackageId();
|
||||
XMLDocument xmlDocument=manifestBlock.decodeToXml(entryStore, currentPackageId);
|
||||
xmlDocument.save(file, true);
|
||||
addDecodedPath(AndroidManifestBlock.FILE_NAME);
|
||||
}
|
||||
private void addDecodedEntry(Collection<EntryBlock> entryBlockList){
|
||||
for(EntryBlock entryBlock:entryBlockList){
|
||||
@ -245,7 +251,11 @@ import java.util.*;
|
||||
logMessage("Extracting root files");
|
||||
File rootDir = new File(outDir, "root");
|
||||
for(InputSource inputSource:apkModule.getApkArchive().listInputSources()){
|
||||
if(containsDecodedPath(inputSource.getAlias())){
|
||||
continue;
|
||||
}
|
||||
extractRootFiles(rootDir, inputSource);
|
||||
addDecodedPath(inputSource.getAlias());
|
||||
}
|
||||
}
|
||||
private void extractRootFiles(File rootDir, InputSource inputSource) throws IOException {
|
||||
@ -260,6 +270,12 @@ import java.util.*;
|
||||
inputSource.write(outputStream);
|
||||
outputStream.close();
|
||||
}
|
||||
private boolean containsDecodedPath(String path){
|
||||
return mDecodedPaths.contains(path);
|
||||
}
|
||||
private void addDecodedPath(String path){
|
||||
mDecodedPaths.add(path);
|
||||
}
|
||||
|
||||
private void logMessage(String msg) {
|
||||
APKLogger apkLogger=apkModule.getApkLogger();
|
||||
|
@ -49,7 +49,7 @@ public class ApkUtil {
|
||||
public static List<File> recursiveFiles(File dir, String ext){
|
||||
List<File> results=new ArrayList<>();
|
||||
if(dir.isFile()){
|
||||
if(ext==null || dir.getName().endsWith(ext)){
|
||||
if(hasExtension(dir, ext)){
|
||||
results.add(dir);
|
||||
}
|
||||
return results;
|
||||
@ -63,7 +63,7 @@ public class ApkUtil {
|
||||
}
|
||||
for(File file:files){
|
||||
if(file.isFile()){
|
||||
if(ext!=null && !file.getName().endsWith(ext)){
|
||||
if(!hasExtension(file, ext)){
|
||||
continue;
|
||||
}
|
||||
results.add(file);
|
||||
@ -74,26 +74,7 @@ public class ApkUtil {
|
||||
return results;
|
||||
}
|
||||
public static List<File> recursiveFiles(File dir){
|
||||
List<File> results=new ArrayList<>();
|
||||
if(dir.isFile()){
|
||||
results.add(dir);
|
||||
return results;
|
||||
}
|
||||
if(!dir.isDirectory()){
|
||||
return results;
|
||||
}
|
||||
File[] files=dir.listFiles();
|
||||
if(files==null){
|
||||
return results;
|
||||
}
|
||||
for(File file:files){
|
||||
if(file.isFile()){
|
||||
results.add(file);
|
||||
continue;
|
||||
}
|
||||
results.addAll(recursiveFiles(file));
|
||||
}
|
||||
return results;
|
||||
return recursiveFiles(dir, null);
|
||||
}
|
||||
public static List<File> listDirectories(File dir){
|
||||
List<File> results=new ArrayList<>();
|
||||
@ -116,7 +97,7 @@ public class ApkUtil {
|
||||
}
|
||||
for(File file:files){
|
||||
if(file.isFile()){
|
||||
if(ext!=null && !file.getName().endsWith(ext)){
|
||||
if(!hasExtension(file, ext)){
|
||||
continue;
|
||||
}
|
||||
results.add(file);
|
||||
@ -124,6 +105,14 @@ public class ApkUtil {
|
||||
}
|
||||
return results;
|
||||
}
|
||||
private static boolean hasExtension(File file, String ext){
|
||||
if(ext==null){
|
||||
return true;
|
||||
}
|
||||
String name=file.getName().toLowerCase();
|
||||
ext=ext.toLowerCase();
|
||||
return name.endsWith(ext);
|
||||
}
|
||||
public static String toModuleName(File file){
|
||||
String name=file.getName();
|
||||
int i=name.lastIndexOf('.');
|
||||
|
@ -39,6 +39,7 @@
|
||||
private PackageBlock currentPackage;
|
||||
private final Set<FrameworkTable> frameworkTables = new HashSet<>();
|
||||
private APKLogger apkLogger;
|
||||
private boolean mForceCreateNamespaces = true;
|
||||
public EncodeMaterials(){
|
||||
}
|
||||
public SpecString getSpecString(String name){
|
||||
@ -278,6 +279,11 @@
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public EncodeMaterials setForceCreateNamespaces(boolean force) {
|
||||
this.mForceCreateNamespaces = force;
|
||||
return this;
|
||||
}
|
||||
public EncodeMaterials setPackageIds(ResourceIds.Table.Package packageIds) {
|
||||
this.packageIds = packageIds;
|
||||
return this;
|
||||
@ -302,6 +308,10 @@
|
||||
public PackageBlock getCurrentPackage() {
|
||||
return currentPackage;
|
||||
}
|
||||
public boolean isForceCreateNamespaces() {
|
||||
return mForceCreateNamespaces;
|
||||
}
|
||||
|
||||
public String getCurrentPackageName(){
|
||||
return currentPackage.getName();
|
||||
}
|
||||
|
@ -113,4 +113,9 @@ package com.reandroid.lib.apk.xmlencoder;
|
||||
}
|
||||
public static final String NULL_PACKAGE_NAME = "NULL_PACKAGE_NAME";
|
||||
private static final Pattern PATTERN_TYPE=Pattern.compile("^([a-z]+)[^a-z]*.*$");
|
||||
|
||||
public static final String URI_ANDROID = "http://schemas.android.com/apk/res/android";
|
||||
public static final String URI_APP = "http://schemas.android.com/apk/res-auto";
|
||||
public static final String PREFIX_ANDROID = "android";
|
||||
public static final String PREFIX_APP = "app";
|
||||
}
|
||||
|
@ -63,10 +63,12 @@ public class XMLEncodeSource extends ByteInputSource {
|
||||
}
|
||||
try {
|
||||
XMLFileEncoder xmlFileEncoder=new XMLFileEncoder(encodeMaterials);
|
||||
xmlFileEncoder.setCurrentPath(xmlSource.getPath());
|
||||
encodeMaterials.logVerbose("Encoding xml: "+xmlSource.getPath());
|
||||
resXmlBlock = xmlFileEncoder.encode(xmlSource.getXMLDocument());
|
||||
} catch (XMLException ex) {
|
||||
throw new IOException(ex.getMessage(), ex);
|
||||
throw new EncodeException("XMLException on: '"+xmlSource.getPath()
|
||||
+"'\n '"+ex.getMessage()+"'");
|
||||
}
|
||||
return resXmlBlock;
|
||||
}
|
||||
|
@ -30,9 +30,15 @@ import java.io.InputStream;
|
||||
public class XMLFileEncoder {
|
||||
private final EncodeMaterials materials;
|
||||
private ResXmlBlock resXmlBlock;
|
||||
private String mCurrentPath;
|
||||
public XMLFileEncoder(EncodeMaterials materials){
|
||||
this.materials=materials;
|
||||
}
|
||||
|
||||
// Just for logging purpose
|
||||
public void setCurrentPath(String path) {
|
||||
this.mCurrentPath = path;
|
||||
}
|
||||
public ResXmlBlock encode(String xmlString){
|
||||
try {
|
||||
return encode(XMLDocument.load(xmlString));
|
||||
@ -50,6 +56,7 @@ public class XMLFileEncoder {
|
||||
return null;
|
||||
}
|
||||
public ResXmlBlock encode(File xmlFile){
|
||||
setCurrentPath(xmlFile.getAbsolutePath());
|
||||
try {
|
||||
return encode(XMLDocument.load(xmlFile));
|
||||
} catch (XMLException ex) {
|
||||
@ -100,6 +107,14 @@ public class XMLFileEncoder {
|
||||
String prefix=attribute.getNamePrefix();
|
||||
if(prefix!=null){
|
||||
ResXmlStartNamespace ns = resXmlElement.getStartNamespaceByPrefix(prefix);
|
||||
if(ns==null){
|
||||
ns=forceCreateNamespace(resXmlElement, resourceId, prefix);
|
||||
}
|
||||
if(ns==null){
|
||||
throw new EncodeException("Namespace not found: "
|
||||
+attribute.toString()
|
||||
+", path="+mCurrentPath);
|
||||
}
|
||||
xmlAttribute.setNamespaceReference(ns.getUriReference());
|
||||
}
|
||||
|
||||
@ -125,15 +140,14 @@ public class XMLFileEncoder {
|
||||
xmlAttribute.setRawValue(encodeResult.value);
|
||||
continue;
|
||||
}
|
||||
if(attributeBag.contains(AttributeValueType.STRING)) {
|
||||
if(attributeBag.isEqualType(AttributeValueType.STRING)) {
|
||||
xmlAttribute.setValueAsString(valueText);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(EncodeUtil.isEmpty(valueText)) {
|
||||
xmlAttribute.setValueType(ValueType.NULL);
|
||||
xmlAttribute.setRawValue(0);
|
||||
xmlAttribute.setValueAsString("");
|
||||
}else{
|
||||
ValueDecoder.EncodeResult encodeResult =
|
||||
ValueDecoder.encodeGuessAny(valueText);
|
||||
@ -145,6 +159,7 @@ public class XMLFileEncoder {
|
||||
}
|
||||
}
|
||||
}
|
||||
resXmlElement.calculatePositions();
|
||||
}
|
||||
private void ensureNamespaces(XMLElement element, ResXmlElement resXmlElement){
|
||||
int count=element.getAttributeCount();
|
||||
@ -181,4 +196,21 @@ public class XMLFileEncoder {
|
||||
idBuilder.add(entryBlock.getResourceId(), entryBlock.getName());
|
||||
}
|
||||
}
|
||||
private ResXmlStartNamespace forceCreateNamespace(ResXmlElement resXmlElement,
|
||||
int resourceId, String prefix){
|
||||
if(!materials.isForceCreateNamespaces()){
|
||||
return null;
|
||||
}
|
||||
int pkgId = (resourceId>>24) & 0xff;
|
||||
String uri;
|
||||
if(pkgId==materials.getCurrentPackageId()){
|
||||
uri=EncodeUtil.URI_APP;
|
||||
}else {
|
||||
uri=EncodeUtil.URI_ANDROID;
|
||||
}
|
||||
ResXmlElement root=resXmlElement.getRootResXmlElement();
|
||||
ResXmlStartNamespace ns=root.getOrCreateNamespace(uri, prefix);
|
||||
materials.logMessage("Force created ns: "+prefix+":"+uri);
|
||||
return ns;
|
||||
}
|
||||
}
|
||||
|
@ -52,10 +52,8 @@ class XMLValuesEncoder {
|
||||
|
||||
encodeValue(entryBlock, element);
|
||||
|
||||
if(!entryBlock.isNull()){
|
||||
SpecString specString = getMaterials().getSpecString(name);
|
||||
entryBlock.setSpecReference(specString);
|
||||
}
|
||||
SpecString specString = getMaterials().getSpecString(name);
|
||||
entryBlock.setSpecReference(specString);
|
||||
}
|
||||
void encodeValue(EntryBlock entryBlock, XMLElement element){
|
||||
String value = getValue(element);
|
||||
|
@ -65,7 +65,7 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
|
||||
bagItem.setType(ValueType.REFERENCE);
|
||||
}
|
||||
bagItem.setData(getMaterials().resolveReference(valueText));
|
||||
}else if(attributeBag.contains(AttributeValueType.STRING)) {
|
||||
}else if(attributeBag.isEqualType(AttributeValueType.STRING)) {
|
||||
bagItem.setValueAsString(valueText);
|
||||
}else if(EncodeUtil.isEmpty(valueText)) {
|
||||
bagItem.setTypeAndData(ValueType.NULL, 0);
|
||||
|
@ -247,7 +247,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
||||
public int getHighestEntryCount(){
|
||||
int result=0;
|
||||
for(TypeBlock typeBlock:getChildes()){
|
||||
int count=typeBlock.getEntryCount();
|
||||
int count=typeBlock.getEntryBlockArray().childesCount();
|
||||
if(count>result){
|
||||
result=count;
|
||||
}
|
||||
|
@ -60,6 +60,12 @@ import java.util.*;
|
||||
addChild(4, mEndElementContainer);
|
||||
addChild(5, mEndNamespaceList);
|
||||
}
|
||||
public void calculatePositions(){
|
||||
ResXmlStartElement start = getStartElement();
|
||||
if(start!=null){
|
||||
start.calculatePositions();
|
||||
}
|
||||
}
|
||||
public ResXmlAttribute newAttribute(){
|
||||
return getStartElement().newAttribute();
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ import java.util.regex.Pattern;
|
||||
return new EncodeResult(ValueType.INT_HEX, parseHex(numString));
|
||||
}
|
||||
if(isInteger(numString)){
|
||||
return new EncodeResult(ValueType.INT_DEC, parseHex(numString));
|
||||
return new EncodeResult(ValueType.INT_DEC, parseInteger(numString));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
}
|
||||
boolean renameOk=false;
|
||||
for(EntryBlock block:items){
|
||||
if(block==null||block.isNull()){
|
||||
if(block==null){
|
||||
continue;
|
||||
}
|
||||
if(block.getSpecReference()==specReference){
|
||||
@ -87,15 +87,22 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
return renameOk;
|
||||
}
|
||||
public EntryBlock pickOne(){
|
||||
EntryBlock defEntryBlock=getDefault();
|
||||
if(defEntryBlock!=null){
|
||||
return defEntryBlock;
|
||||
EntryBlock[] items=getItems();
|
||||
if(items==null){
|
||||
return null;
|
||||
}
|
||||
Iterator<EntryBlock> itr=iterator(true);
|
||||
while (itr.hasNext()){
|
||||
return itr.next();
|
||||
EntryBlock result = null;
|
||||
for(EntryBlock entryBlock:items){
|
||||
if(entryBlock==null){
|
||||
continue;
|
||||
}
|
||||
if(result==null || result.isNull()){
|
||||
result=entryBlock;
|
||||
}else if(entryBlock.isDefault()){
|
||||
return entryBlock;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
public EntryBlock getDefault(){
|
||||
Iterator<EntryBlock> itr=iterator(true);
|
||||
|
@ -278,28 +278,45 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
private void setByteFlagsB(byte b){
|
||||
mByteFlagsB.set(b);
|
||||
}
|
||||
public IntegerItem getSpecReferenceBlock(){
|
||||
private IntegerItem getSpecReferenceBlock(){
|
||||
return mSpecReference;
|
||||
}
|
||||
public int getSpecReference(){
|
||||
if(mSpecReference==null){
|
||||
return -1;
|
||||
}
|
||||
return mSpecReference.get();
|
||||
}
|
||||
public void setSpecReference(int ref){
|
||||
if(mSpecReference==null){
|
||||
return;
|
||||
}
|
||||
boolean created = createNullSpecReference();
|
||||
int old=mSpecReference.get();
|
||||
if(ref==old){
|
||||
return;
|
||||
}
|
||||
mSpecReference.set(ref);
|
||||
updateSpecRef(old, ref);
|
||||
if(created){
|
||||
updatePackage();
|
||||
}
|
||||
}
|
||||
public void setSpecReference(SpecString specString){
|
||||
removeSpecRef();
|
||||
if(mSpecReference!=null){
|
||||
mSpecReference.set(specString.getIndex());
|
||||
if(specString==null){
|
||||
return;
|
||||
}
|
||||
boolean created = createNullSpecReference();
|
||||
mSpecReference.set(specString.getIndex());
|
||||
if(created){
|
||||
updatePackage();
|
||||
}
|
||||
}
|
||||
private boolean createNullSpecReference(){
|
||||
if(mSpecReference==null){
|
||||
mSpecReference = new IntegerItem();
|
||||
mSpecReference.setNull(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public BaseResValue getResValue(){
|
||||
return mResValue;
|
||||
@ -352,6 +369,13 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
}
|
||||
return specString.get();
|
||||
}
|
||||
public String getNameOrHex(){
|
||||
String name = getName();
|
||||
if(name==null){
|
||||
name = String.format("@0x%08x", getResourceId());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
private void setName(String name){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
EntryGroup entryGroup = packageBlock.getEntryGroup(getResourceId());
|
||||
@ -378,6 +402,9 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
return packageBlock.getName();
|
||||
}
|
||||
public SpecString getSpecString(){
|
||||
if(mSpecReference==null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
@ -486,7 +513,11 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
this.mHeaderSize =new ShortItem();
|
||||
this.mFlagEntryType =new ByteItem();
|
||||
this.mByteFlagsB=new ByteItem();
|
||||
this.mSpecReference = new IntegerItem();
|
||||
if(mSpecReference==null){
|
||||
this.mSpecReference = new IntegerItem();
|
||||
}else if(mSpecReference.isNull()){
|
||||
mSpecReference.setNull(false);
|
||||
}
|
||||
|
||||
mHeaderSize.setIndex(0);
|
||||
mFlagEntryType.setIndex(1);
|
||||
@ -625,11 +656,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
updateSpecRef(-1, getSpecReference());
|
||||
}
|
||||
private void updateSpecRef(int oldRef, int newNef){
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock==null){
|
||||
return;
|
||||
}
|
||||
PackageBlock packageBlock=typeBlock.getPackageBlock();
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
@ -647,11 +674,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
if(mSpecReference==null){
|
||||
return;
|
||||
}
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock==null){
|
||||
return;
|
||||
}
|
||||
PackageBlock packageBlock=typeBlock.getPackageBlock();
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
@ -662,11 +685,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
}
|
||||
}
|
||||
private void updatePackage(){
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock==null){
|
||||
return;
|
||||
}
|
||||
PackageBlock packageBlock=typeBlock.getPackageBlock();
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
@ -761,37 +780,6 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
}
|
||||
return new ResValueInt();
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
builder.append(": ");
|
||||
ResConfig resConfig=getResConfig();
|
||||
if(resConfig!=null){
|
||||
builder.append(resConfig.toString());
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(" resId=");
|
||||
builder.append(String.format("0x%08x", getResourceId()));
|
||||
if(isNull()){
|
||||
builder.append(", null entry");
|
||||
return builder.toString();
|
||||
}
|
||||
String name=getResourceName();
|
||||
if(name!=null){
|
||||
builder.append('(');
|
||||
builder.append(name);
|
||||
builder.append(')');
|
||||
}
|
||||
BaseResValue baseResValue=getResValue();
|
||||
if(baseResValue instanceof ResValueInt){
|
||||
ResValueInt resValueInt=(ResValueInt)baseResValue;
|
||||
builder.append(" '");
|
||||
builder.append(resValueInt.toString());
|
||||
builder.append(" '");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
public static String buildResourceName(char prefix, String packageName, String type, String name){
|
||||
if(name==null){
|
||||
return null;
|
||||
@ -811,6 +799,39 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
builder.append(name);
|
||||
return builder.toString();
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
builder.append(": ");
|
||||
ResConfig resConfig=getResConfig();
|
||||
if(resConfig!=null){
|
||||
builder.append(resConfig.toString());
|
||||
builder.append(", ");
|
||||
}
|
||||
String name=getResourceName();
|
||||
if(name==null){
|
||||
name=getNameOrHex();
|
||||
}else{
|
||||
builder.append(" id=");
|
||||
builder.append(String.format("0x%08x", getResourceId()));
|
||||
}
|
||||
builder.append('(');
|
||||
builder.append(name);
|
||||
builder.append(')');
|
||||
if(isNull()){
|
||||
builder.append(", null entry");
|
||||
return builder.toString();
|
||||
}
|
||||
BaseResValue baseResValue=getResValue();
|
||||
if(baseResValue instanceof ResValueInt){
|
||||
ResValueInt resValueInt=(ResValueInt)baseResValue;
|
||||
builder.append(" '");
|
||||
builder.append(resValueInt.toString());
|
||||
builder.append(" '");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private final static short HEADER_SIZE_BAG = 0x0010;
|
||||
private final static short HEADER_SIZE_INT = 0x0008;
|
||||
|
@ -31,6 +31,9 @@ public class AttributeBag {
|
||||
public boolean contains(AttributeValueType valueType){
|
||||
return getFormat().contains(valueType);
|
||||
}
|
||||
public boolean isEqualType(AttributeValueType valueType){
|
||||
return getFormat().isEqualType(valueType);
|
||||
}
|
||||
public ValueDecoder.EncodeResult encodeEnumOrFlagValue(String valueString){
|
||||
if(valueString==null || !isEnumOrFlag()){
|
||||
return null;
|
||||
|
@ -92,6 +92,14 @@ public class AttributeBagItem {
|
||||
int dataLow = 0xffff & getBagItem().getDataLow();
|
||||
return (dataLow & value) == value;
|
||||
}
|
||||
public boolean isEqualType(AttributeValueType valueType){
|
||||
if(valueType == null || getItemType()!=AttributeItemType.FORMAT){
|
||||
return false;
|
||||
}
|
||||
int value = 0xff & valueType.getByte();
|
||||
int dataLow = 0xffff & getBagItem().getDataLow();
|
||||
return (dataLow == value);
|
||||
}
|
||||
public AttributeValueType[] getValueTypes(){
|
||||
AttributeItemType type=getItemType();
|
||||
if(type!=AttributeItemType.FORMAT){
|
||||
|
@ -33,12 +33,6 @@ public class XMLTextAttribute extends XMLAttribute {
|
||||
if(unEscape){
|
||||
return XMLUtil.unEscapeXmlChars(mText);
|
||||
}
|
||||
if(mText!=null){
|
||||
String junk= XMLUtil.unEscapeXmlChars(mText);
|
||||
if(!mText.equals(junk)){
|
||||
junk.trim();
|
||||
}
|
||||
}
|
||||
return mText;
|
||||
}
|
||||
@Override
|
||||
|
@ -530,30 +530,17 @@ public class MXParser implements XmlPullParser
|
||||
}
|
||||
return i;
|
||||
}
|
||||
public String getPositionDescription ()
|
||||
@Override
|
||||
public String getPositionDescription()
|
||||
{
|
||||
String fragment = null;
|
||||
if(posStart <= pos) {
|
||||
final int start = findFragment(0, buf, posStart, pos);
|
||||
|
||||
if(start < pos) {
|
||||
fragment = new String(buf, start, pos - start);
|
||||
}
|
||||
if(bufAbsoluteStart > 0 || start > 0) {
|
||||
fragment = "..." + fragment;
|
||||
}
|
||||
}
|
||||
return " "+TYPES[ eventType ] +
|
||||
(fragment != null ? " seen "+printable(fragment)+"..." : "")
|
||||
+" "+(location != null ? location : "")
|
||||
+"@"+getLineNumber()+":"+getColumnNumber();
|
||||
return "line="+getLineNumber()+", col="+getColumnNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineNumber()
|
||||
{
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnNumber()
|
||||
{
|
||||
return columnNumber;
|
||||
@ -740,11 +727,13 @@ public class MXParser implements XmlPullParser
|
||||
return attributeValue[ index ];
|
||||
}
|
||||
|
||||
public String getAttributeValue(String namespace,
|
||||
String name)
|
||||
@Override
|
||||
public String getAttributeValue(String namespace, String name)
|
||||
{
|
||||
if(eventType != START_TAG) throw new IndexOutOfBoundsException(
|
||||
"only START_TAG can have attributes"+getPositionDescription());
|
||||
if(eventType != START_TAG) {
|
||||
throw new IndexOutOfBoundsException("only START_TAG can have attributes "
|
||||
+getPositionDescription());
|
||||
}
|
||||
if(name == null) {
|
||||
throw new IllegalArgumentException("attribute name can not be null");
|
||||
}
|
||||
@ -1651,7 +1640,7 @@ public class MXParser implements XmlPullParser
|
||||
} // skip additional spaces
|
||||
if(ch != '=') {
|
||||
throw new XmlPullParserException(
|
||||
"expected = after attribute name", this, null);
|
||||
"expected = after attribute name '"+name+processNamespaces+"'", this, null);
|
||||
}
|
||||
ch = more();
|
||||
while(isS(ch)) {
|
||||
@ -2689,7 +2678,7 @@ public class MXParser implements XmlPullParser
|
||||
return (ch < LOOKUP_MAX_CHAR && lookupNameChar[ ch ])
|
||||
|| (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
|
||||
|| (ch >= '\u202A' && ch <= '\u218F')
|
||||
|| (ch >= '\u2800' && ch <= '\uFFEF');
|
||||
|| (ch >= '\u2800' && ch <= '\uFFEF') || ch=='@';
|
||||
}
|
||||
|
||||
protected boolean isS(char ch) {
|
||||
|
@ -17,10 +17,7 @@ public class XmlPullParserException extends Exception {
|
||||
super(s);
|
||||
}
|
||||
public XmlPullParserException(String msg, XmlPullParser parser, Throwable chain) {
|
||||
super ((msg == null ? "" : msg+" ")
|
||||
+ (parser == null ? "" : "(position:"+parser.getPositionDescription()+") ")
|
||||
+ (chain == null ? "" : "caused by: "+chain));
|
||||
|
||||
super(buildMessage(msg, parser));
|
||||
if (parser != null) {
|
||||
this.row = parser.getLineNumber();
|
||||
this.column = parser.getColumnNumber();
|
||||
@ -30,5 +27,19 @@ public class XmlPullParserException extends Exception {
|
||||
public Throwable getDetail() { return detail; }
|
||||
public int getLineNumber() { return row; }
|
||||
public int getColumnNumber() { return column; }
|
||||
private static String buildMessage(String msg, XmlPullParser parser){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
if(parser!=null){
|
||||
builder.append("[line=");
|
||||
builder.append(parser.getLineNumber());
|
||||
builder.append(", col=");
|
||||
builder.append(parser.getColumnNumber());
|
||||
builder.append("] ");
|
||||
}
|
||||
if(msg!=null){
|
||||
builder.append(msg);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user