PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, May 18, 2022

[FIXED] How NOT to deserialise a nested XML document with XStream

 May 18, 2022     java, partial, serialization, xml, xstream     No comments   

Issue

I have a document structure like this:

<MyDocument>
    <MyChildDocument>
        <SubElement>
            ...
        </SubElement>
    </MyChildDocument>
</MyDocument>

I would like XStream to de-serialise this to the following object:

@XStreamAlias("MyDocument")
public class MyDocument {
    String myChildDocument;

    public String getMyChildDocument() {
        return myChildDocument;
    }

    public void setMyChildDocument(String str) {
        myChildDocument = str;
    }
}

The myChildDocument variable should contain the full child document as a string including the tags.

I also need to do the serialisation side of this, avoiding XStream from entity encoding the XML string contained within the myChildDocument variable.

I've been looking at converters to do this for me, but have not found a good way to do it. Any ideas?


Solution

I managed to create a solution for this using a custom converter. In simple terms, when marshalling, feed the XML string for MyChildDocument into an XML reader and use a copier to feed this back out to the writer that is creating the marshalled result. Reverse the process when unmarshalling incoming XML!

public class MyExchangeConverter implements Converter {

    protected static XmlPullParser pullParser;
    protected static XmlPullParser getPullParser() {
        if (pullParser == null) {
            try {
                pullParser = XmlPullParserFactory.newInstance().newPullParser();
            } 
            catch (XmlPullParserException e) { } // Ah nuts! 
        }
        return pullParser;
    }

    @Override
    public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
        return MyDocument.class.equals(type);
    }

    @Override
    public void marshal(Object source, HierarchicalStreamWriter writer,
            MarshallingContext context) {
        MyDocument request = (MyDocument) source;
        if (request.getMyChildDocument() != null) {
            HierarchicalStreamReader reader;
            reader = new XppReader(new StringReader(request.getMyChildDocument()), getPullParser());
            HierarchicalStreamCopier copier = new HierarchicalStreamCopier();
            copier.copy(reader, writer);
        }
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader,
            UnmarshallingContext context) {
        MyDocument response = new MyDocument();
        reader.moveDown();
        Writer out = new StringWriter(); 
        HierarchicalStreamWriter writer = new CompactWriter(out);
        HierarchicalStreamCopier copier = new HierarchicalStreamCopier();
        copier.copy(reader, writer);
        response.setMyChildDocument(out.toString());
        reader.moveUp();
        return response;
    }
}

Some would (rightly) argue this opens up the system to XML injection attacks to a degree. True enough, but for my particular use case, this is not a risk I am concerned about. Just something to be aware of if anybody plans to use this for public facing interfaces with unknown remote parties or the risk of man-in-the-middle attacks. You have been warned!



Answered By - John Rix
Answer Checked By - David Goodson (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing