diff --git a/src/main/java/com/reandroid/apk/xmldecoder/ResXmlDocumentSerializer.java b/src/main/java/com/reandroid/apk/xmldecoder/ResXmlDocumentSerializer.java index 5dc0ca8..3298c12 100644 --- a/src/main/java/com/reandroid/apk/xmldecoder/ResXmlDocumentSerializer.java +++ b/src/main/java/com/reandroid/apk/xmldecoder/ResXmlDocumentSerializer.java @@ -34,10 +34,12 @@ public class ResXmlDocumentSerializer implements ResXmlPullParser.DocumentLoaded private final XmlSerializer serializer; private final XmlParserToSerializer parserToSerializer; private boolean validateXmlNamespace; + private String mCurrentPath; public ResXmlDocumentSerializer(ResXmlPullParser parser){ this.parser = parser; this.serializer = new KXmlSerializer(); this.parserToSerializer = new XmlParserToSerializer(parser, serializer); + this.parser.setDocumentLoadedListener(this); } public ResXmlDocumentSerializer(Decoder decoder){ this(new ResXmlPullParser(decoder)); @@ -61,9 +63,14 @@ public class ResXmlDocumentSerializer implements ResXmlPullParser.DocumentLoaded this.parser.setInput(inputStream, null); OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8); this.serializer.setOutput(writer); - this.parserToSerializer.write(); + try{ + this.parserToSerializer.write(); + }catch (Exception ex){ + throw getError(ex); + } writer.close(); outputStream.close(); + mCurrentPath = null; } } public void write(InputStream inputStream, File file) @@ -72,11 +79,13 @@ public class ResXmlDocumentSerializer implements ResXmlPullParser.DocumentLoaded if(dir != null && !dir.exists()){ dir.mkdirs(); } + mCurrentPath = String.valueOf(file); FileOutputStream outputStream = new FileOutputStream(file); write(inputStream, outputStream); } public void write(ResXmlDocument xmlDocument, File file) throws IOException, XmlPullParserException { + mCurrentPath = String.valueOf(file); File dir = file.getParentFile(); if(dir != null && !dir.exists()){ dir.mkdirs(); @@ -116,6 +125,27 @@ public class ResXmlDocumentSerializer implements ResXmlPullParser.DocumentLoaded namespaceValidator.validate(); return resXmlDocument; } + private IOException getError(Exception exception){ + String path = mCurrentPath; + if(exception instanceof IOException){ + String msg = path + ":" + exception.getMessage(); + IOException ioException = new IOException(msg); + ioException.setStackTrace(exception.getStackTrace()); + Throwable cause = ioException.getCause(); + if(cause != null){ + ioException.initCause(cause); + } + return ioException; + } + String msg = path + ":" + exception.getClass() + ":" + exception.getMessage(); + IOException otherException = new IOException(msg); + otherException.setStackTrace(exception.getStackTrace()); + Throwable cause = otherException.getCause(); + if(cause != null){ + otherException.initCause(cause); + } + return otherException; + } private static Decoder createDecoder(ApkModule apkModule){ Decoder decoder = Decoder.create(apkModule.getTableBlock()); diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ParserEventList.java b/src/main/java/com/reandroid/arsc/chunk/xml/ParserEventList.java index 3e9f72d..d9b2a37 100644 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ParserEventList.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ParserEventList.java @@ -16,6 +16,8 @@ package com.reandroid.arsc.chunk.xml; +import com.reandroid.arsc.decoder.ValueDecoder; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -43,7 +45,11 @@ public class ParserEventList implements Iterator { return getElement().getTag(); } if(type == ParserEvent.TEXT){ - return ((ResXmlTextNode)getXmlNode()).getText(); + String text = ((ResXmlTextNode)getXmlNode()).getText(); + if(text == null){ + text = ""; + } + return ValueDecoder.escapeSpecialCharacter(text); } return null; } diff --git a/src/main/java/com/reandroid/arsc/decoder/Decoder.java b/src/main/java/com/reandroid/arsc/decoder/Decoder.java index e11485e..62da583 100644 --- a/src/main/java/com/reandroid/arsc/decoder/Decoder.java +++ b/src/main/java/com/reandroid/arsc/decoder/Decoder.java @@ -70,10 +70,18 @@ public class Decoder { return ValueDecoder.decode(getEntryStore(), getCurrentPackageId(), value); } public String decodeAttributeValue(AttributeValue attributeValue){ + return decodeAttributeValue(attributeValue, true); + } + public String decodeAttributeValue(AttributeValue attributeValue, boolean escapeStartChar){ if(attributeValue == null){ return null; } - return ValueDecoder.decode(getEntryStore(), getCurrentPackageId(), attributeValue); + String result = ValueDecoder.decode(getEntryStore(), getCurrentPackageId(), attributeValue); + if(!escapeStartChar || result == null || result.length() == 0 + || attributeValue.getValueType() != ValueType.STRING){ + return result; + } + return ValueDecoder.escapeSpecialCharacter(result); } private EntryStore getEntryStore() { return entryStore; diff --git a/src/main/java/com/reandroid/arsc/value/ValueItem.java b/src/main/java/com/reandroid/arsc/value/ValueItem.java index ae16109..32fc29b 100755 --- a/src/main/java/com/reandroid/arsc/value/ValueItem.java +++ b/src/main/java/com/reandroid/arsc/value/ValueItem.java @@ -202,7 +202,11 @@ import java.util.Objects; public String getValueAsString(){ StringItem stringItem = getDataAsPoolString(); if(stringItem!=null){ - return stringItem.getHtml(); + String value = stringItem.getHtml(); + if(value == null){ + value = ""; + } + return value; } return null; }