diff --git a/.gitignore b/.gitignore index 1c36f1a20..8eeb443be 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ experimental/bin extensions/bin target/ +.metadata diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/provider/VCardProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/provider/VCardProvider.java index d5e44691e..92549f699 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/provider/VCardProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/provider/VCardProvider.java @@ -18,339 +18,321 @@ package org.jivesoftware.smackx.vcardtemp.provider; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.provider.IQProvider; -import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; -import org.xml.sax.SAXException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; /** * vCard provider. * * @author Gaston Dombiak * @author Derek DeMoro + * @author Chris Deering */ public class VCardProvider extends IQProvider { - private static final Logger LOGGER = Logger.getLogger(VCardProvider.class.getName()); - - private static final String PREFERRED_ENCODING = "UTF-8"; - private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY; + // @formatter:off + private static final String[] ADR = new String[] { + "POSTAL", + "PARCEL", + "DOM", + "INTL", + "PREF", + "POBOX", + "EXTADR", + "STREET", + "LOCALITY", + "REGION", + "PCODE", + "CTRY", + "FF", + }; - static { - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - try { - documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - } catch (ParserConfigurationException e) { - LOGGER.finer("Could not disallow doctype decl: " + e.getMessage()); - // If we can't disable DTDs, then at least try the following - // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities - // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities - try { - documentBuilderFactory.setFeature( "http://xml.org/sax/features/external-general-entities", false); - documentBuilderFactory.setFeature( "http://xml.org/sax/features/external-parameter-entities", false); - } catch (ParserConfigurationException e1) { - LOGGER.finer("Could not disallow external entities for xerces parser: " + e1.getMessage()); - } - } - // Android throws an UnsupportedOperationException when calling setXIncludeAware() and for some dumb reason also - // when calling isXIncludeWare(), while it defaults according to the docs to 'false'. - boolean isXIncludeAware; - try { - isXIncludeAware = documentBuilderFactory.isXIncludeAware(); - } catch (UnsupportedOperationException e) { - // Assume we are on Android where isXIncludeAware defaults to 'false' - isXIncludeAware = false; - } - if (isXIncludeAware) { - documentBuilderFactory.setXIncludeAware(false); - } - documentBuilderFactory.setExpandEntityReferences(false); - - // Harden the parser even further - documentBuilderFactory.setIgnoringComments(true); - documentBuilderFactory.setCoalescing(false); - documentBuilderFactory.setValidating(false); - - try { - documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - } catch (ParserConfigurationException e) { - LOGGER.info("Could not enable secure processing parsing feature: " + e.getMessage()); - } - - DOCUMENT_BUILDER_FACTORY = documentBuilderFactory; - } + private static final String[] TEL = new String[] { + "VOICE", + "FAX", + "PAGER", + "MSG", + "CELL", + "VIDEO", + "BBS", + "MODEM", + "ISDN", + "PCS", + "PREF", + }; + // @formatter:on @Override - public VCard parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, SmackException { - final StringBuilder sb = new StringBuilder(); - try { - int event = parser.getEventType(); - // get the content - while (true) { - switch (event) { - case XmlPullParser.TEXT: - // We must re-escape the xml so that the DOM won't throw an exception - sb.append(StringUtils.escapeForXML(parser.getText())); - break; - case XmlPullParser.START_TAG: - sb.append('<').append(parser.getName()).append('>'); - break; - case XmlPullParser.END_TAG: - sb.append("'); - break; - default: + public VCard parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, + SmackException { + VCard vCard = new VCard(); + String name = null; + + outerloop: while (true) { + int eventType = parser.next(); + switch (eventType) { + case XmlPullParser.START_TAG: + name = parser.getName(); + switch (name) { + case "N": + parseName(parser, vCard); + break; + case "ORG": + parseOrg(parser, vCard); + break; + case "TEL": + parseTel(parser, vCard); + break; + case "ADR": + parseAddress(parser, vCard); + break; + case "EMAIL": + parseEmail(parser, vCard); + break; + case "NICKNAME": + vCard.setNickName(parser.nextText()); + break; + case "JABBERID": + vCard.setJabberId(parser.nextText()); + break; + case "PHOTO": + parsePhoto(parser, vCard); + break; + default: + break; } - - if (event == XmlPullParser.END_TAG && "vCard".equals(parser.getName())) break; - - event = parser.next(); + break; + case XmlPullParser.TEXT: + if (initialDepth + 1 == parser.getDepth()) { + vCard.setField(name, parser.getText()); + } + break; + case XmlPullParser.END_TAG: + if (parser.getDepth() == initialDepth) { + break outerloop; + } + break; + default: + break; } } - catch (XmlPullParserException e) { - LOGGER.log(Level.SEVERE, "Exception parsing VCard", e); - } - catch (IOException e) { - LOGGER.log(Level.SEVERE, "Exception parsing VCard", e); - } - String xmlText = sb.toString(); - try { - return createVCardFromXML(xmlText); - } catch (SAXException | ParserConfigurationException e) { - throw new SmackException(e); - } - } - - /** - * Builds a users vCard from xml file. - * - * @param xml the xml representing a users vCard. - * @return the VCard. - * @throws IOException - * @throws SAXException - * @throws UnsupportedEncodingException - * @throws ParserConfigurationException - */ - public static VCard createVCardFromXML(String xml) throws UnsupportedEncodingException, SAXException, IOException, ParserConfigurationException { - VCard vCard = new VCard(); - - DocumentBuilder documentBuilder = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder(); - Document document = documentBuilder.parse( - new ByteArrayInputStream(xml.getBytes(PREFERRED_ENCODING))); - - new VCardReader(vCard, document).initializeFields(); return vCard; } - private static class VCardReader { - - private final VCard vCard; - private final Document document; - - VCardReader(VCard vCard, Document document) { - this.vCard = vCard; - this.document = document; - } - - public void initializeFields() { - vCard.setFirstName(getTagContents("GIVEN")); - vCard.setLastName(getTagContents("FAMILY")); - vCard.setMiddleName(getTagContents("MIDDLE")); - setupPhoto(); - - setupEmails(); - - vCard.setOrganization(getTagContents("ORGNAME")); - vCard.setOrganizationUnit(getTagContents("ORGUNIT")); - - setupSimpleFields(); - - setupPhones(); - setupAddresses(); - } - - private void setupPhoto() { - String binval = null; - String mimetype = null; - - NodeList photo = document.getElementsByTagName("PHOTO"); - if (photo.getLength() != 1) - return; - - Node photoNode = photo.item(0); - NodeList childNodes = photoNode.getChildNodes(); - - int childNodeCount = childNodes.getLength(); - List nodes = new ArrayList(childNodeCount); - for (int i = 0; i < childNodeCount; i++) - nodes.add(childNodes.item(i)); - - String name = null; - String value = null; - for (Node n : nodes) { - name = n.getNodeName(); - value = n.getTextContent(); - if (name.equals("BINVAL")) { - binval = value; - } - else if (name.equals("TYPE")) { - mimetype = value; - } - } - - if (binval == null || mimetype == null) - return; - - vCard.setAvatar(binval, mimetype); - } - - private void setupEmails() { - NodeList nodes = document.getElementsByTagName("USERID"); - if (nodes == null) return; - for (int i = 0; i < nodes.getLength(); i++) { - Element element = (Element) nodes.item(i); - if ("WORK".equals(element.getParentNode().getFirstChild().getNodeName())) { - vCard.setEmailWork(getTextContent(element)); + private static void parseAddress(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { + final int initialDepth = parser.getDepth(); + boolean isWork = true; + outerloop: while (true) { + int eventType = parser.next(); + switch (eventType) { + case XmlPullParser.START_TAG: + String name = parser.getName(); + if ("HOME".equals(name)) { + isWork = false; } else { - vCard.setEmailHome(getTextContent(element)); - } - } - } - - private void setupPhones() { - NodeList allPhones = document.getElementsByTagName("TEL"); - if (allPhones == null) return; - for (int i = 0; i < allPhones.getLength(); i++) { - NodeList nodes = allPhones.item(i).getChildNodes(); - String type = null; - String code = null; - String value = null; - for (int j = 0; j < nodes.getLength(); j++) { - Node node = nodes.item(j); - if (node.getNodeType() != Node.ELEMENT_NODE) continue; - String nodeName = node.getNodeName(); - if ("NUMBER".equals(nodeName)) { - value = getTextContent(node); - } - else if (isWorkHome(nodeName)) { - type = nodeName; - } - else { - code = nodeName; + for (String adr : ADR) { + if (adr.equals(name)) { + if (isWork) { + vCard.setAddressFieldWork(name, parser.nextText()); + } + else { + vCard.setAddressFieldHome(name, parser.nextText()); + } + } } } - if (value == null) continue; - if (code == null) - code = "VOICE"; - if ("HOME".equals(type)) { - vCard.setPhoneHome(code, value); + break; + case XmlPullParser.END_TAG: + if (parser.getDepth() == initialDepth) { + break outerloop; } - else { // By default, setup work phone - vCard.setPhoneWork(code, value); - } - } - } - - private boolean isWorkHome(String nodeName) { - return "HOME".equals(nodeName) || "WORK".equals(nodeName); - } - - private void setupAddresses() { - NodeList allAddresses = document.getElementsByTagName("ADR"); - if (allAddresses == null) return; - for (int i = 0; i < allAddresses.getLength(); i++) { - Element addressNode = (Element) allAddresses.item(i); - - String type = null; - List code = new ArrayList(); - List value = new ArrayList(); - NodeList childNodes = addressNode.getChildNodes(); - for (int j = 0; j < childNodes.getLength(); j++) { - Node node = childNodes.item(j); - if (node.getNodeType() != Node.ELEMENT_NODE) continue; - String nodeName = node.getNodeName(); - if (isWorkHome(nodeName)) { - type = nodeName; - } - else { - code.add(nodeName); - value.add(getTextContent(node)); - } - } - for (int j = 0; j < value.size(); j++) { - if ("HOME".equals(type)) { - vCard.setAddressFieldHome((String) code.get(j), (String) value.get(j)); - } - else { // By default, setup work address - vCard.setAddressFieldWork((String) code.get(j), (String) value.get(j)); - } - } - } - } - - private String getTagContents(String tag) { - NodeList nodes = document.getElementsByTagName(tag); - if (nodes != null && nodes.getLength() == 1) { - return getTextContent(nodes.item(0)); - } - return null; - } - - private void setupSimpleFields() { - NodeList childNodes = document.getDocumentElement().getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - if (node instanceof Element) { - Element element = (Element) node; - - String field = element.getNodeName(); - if (element.getChildNodes().getLength() == 0) { - vCard.setField(field, ""); - } - else if (element.getChildNodes().getLength() == 1 && - element.getChildNodes().item(0) instanceof Text) { - vCard.setField(field, getTextContent(element)); - } - } - } - } - - private String getTextContent(Node node) { - StringBuilder result = new StringBuilder(); - appendText(result, node); - return result.toString(); - } - - private void appendText(StringBuilder result, Node node) { - NodeList childNodes = node.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node nd = childNodes.item(i); - String nodeValue = nd.getNodeValue(); - if (nodeValue != null) { - result.append(nodeValue); - } - appendText(result, nd); + break; + default: + break; } } } + + private static void parseTel(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { + final int initialDepth = parser.getDepth(); + boolean isWork = true; + String telLabel = null; + + outerloop: while (true) { + int eventType = parser.next(); + switch (eventType) { + case XmlPullParser.START_TAG: + String name = parser.getName(); + if ("HOME".equals(name)) { + isWork = false; + } + else { + if (telLabel != null && "NUMBER".equals(name)) { + if (isWork) { + vCard.setPhoneWork(telLabel, parser.nextText()); + } + else { + vCard.setPhoneHome(telLabel, parser.nextText()); + } + } + else { + for (String tel : TEL) { + if (tel.equals(name)) { + telLabel = name; + } + } + } + } + break; + case XmlPullParser.END_TAG: + if (parser.getDepth() == initialDepth) { + break outerloop; + } + break; + default: + break; + } + } + } + + private static void parseOrg(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { + final int initialDepth = parser.getDepth(); + + outerloop: while (true) { + int eventType = parser.next(); + switch (eventType) { + case XmlPullParser.START_TAG: + String name = parser.getName(); + switch (name) { + case "ORGNAME": + vCard.setOrganization(parser.nextText()); + break; + case "ORGUNIT": + vCard.setOrganizationUnit(parser.nextText()); + break; + default: + break; + } + break; + case XmlPullParser.END_TAG: + if (parser.getDepth() == initialDepth) { + break outerloop; + } + break; + default: + break; + } + } + } + + private static void parseEmail(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { + final int initialDepth = parser.getDepth(); + boolean isWork = false; + + outerloop: while (true) { + int eventType = parser.next(); + switch (eventType) { + case XmlPullParser.START_TAG: + String name = parser.getName(); + switch (name) { + case "WORK": + isWork = true; + break; + case "USERID": + if (isWork) { + vCard.setEmailWork(parser.nextText()); + } + else { + vCard.setEmailHome(parser.nextText()); + } + break; + default: + break; + } + case XmlPullParser.END_TAG: + if (parser.getDepth() == initialDepth) { + break outerloop; + } + default: + break; + } + } + } + + private static void parseName(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { + final int initialDepth = parser.getDepth(); + + outerloop: while (true) { + int eventType = parser.next(); + switch (eventType) { + case XmlPullParser.START_TAG: + String name = parser.getName(); + switch (name) { + case "FAMILY": + vCard.setLastName(parser.nextText()); + break; + case "GIVEN": + vCard.setFirstName(parser.nextText()); + break; + case "MIDDLE": + vCard.setMiddleName(parser.nextText()); + break; + default: + break; + } + break; + case XmlPullParser.END_TAG: + if (parser.getDepth() == initialDepth) { + break outerloop; + } + break; + default: + break; + + } + } + } + + private static void parsePhoto(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { + final int initialDepth = parser.getDepth(); + String binval = null; + String mimetype = null; + + outerloop: while (true) { + int eventType = parser.next(); + switch (eventType) { + case XmlPullParser.START_TAG: + String name = parser.getName(); + switch (name) { + case "BINVAL": + binval = parser.nextText(); + break; + case "TYPE": + mimetype = parser.nextText(); + break; + default: + break; + } + break; + case XmlPullParser.END_TAG: + if (parser.getDepth() == initialDepth) { + break outerloop; + } + break; + default: + break; + } + } + + if (binval == null || mimetype == null) { + return; + } + + vCard.setAvatar(binval, mimetype); + } } diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/VCardUnitTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/VCardUnitTest.java index 3ced33d48..18ba52f27 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/VCardUnitTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/VCardUnitTest.java @@ -15,15 +15,16 @@ * limitations under the License. */ package org.jivesoftware.smackx; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.Arrays; import org.jivesoftware.smack.test.util.SmackTestSuite; +import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.stringencoder.Base64; import org.jivesoftware.smackx.vcardtemp.packet.VCard; -import org.jivesoftware.smackx.vcardtemp.provider.VCardProvider; import org.junit.Before; import org.junit.Test; @@ -34,41 +35,240 @@ public class VCardUnitTest extends InitExtensions { SmackTestSuite.init(); } + @Test + public void testParseFullVCardIQStanza() throws Throwable { + + // @formatter:off + final String request = + "" + + "" + + "User Name" + + "" + + "Name" + + "User" + + "PJ" + + "" + + "User dude" + + "http://www.igniterealtime.org" + + "1970-17-03" + + "" + + "Ignite Realtime" + + "Smack" + + "" + + "Programmer & tester" + + "Bug fixer" + + "123-456-7890" + + "" + + "" + + "" + + "" + + "" + + "Work Street" + + "Work Locality" + + "Work Region" + + "Work Post Code" + + "Work Country" + + "" + + "123-098-7654" + + "" + + "" + + "" + + "" + + "" + + "" + + "Home Locality" + + "Home Region" + + "Home Post Code" + + "Home Country" + + "" + + "user@igniterealtime.org" + + "work@igniterealtime.org" + + "user@igniterealtime.org" + + "" + + "<Check out our website: http://www.igniterealtime.org>" + + "" + + "" + getAvatarEncoded() + "" + MIME_TYPE + "" + + "" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + + assertEquals("User", vCard.getFirstName()); + assertEquals("Name", vCard.getLastName()); + assertEquals("PJ", vCard.getMiddleName()); + assertEquals("User dude", vCard.getNickName()); + + assertEquals("Programmer & tester", vCard.getField("TITLE")); + assertEquals("Bug fixer", vCard.getField("ROLE")); + assertEquals("", vCard.getField("DESC")); + assertEquals("http://www.igniterealtime.org", vCard.getField("URL")); + + assertEquals("user@igniterealtime.org", vCard.getEmailHome()); + assertEquals("work@igniterealtime.org", vCard.getEmailWork()); + + assertEquals("user@igniterealtime.org", vCard.getJabberId()); + assertEquals("Ignite Realtime", vCard.getOrganization()); + assertEquals("Smack", vCard.getOrganizationUnit()); + + assertEquals("123-098-7654", vCard.getPhoneHome("VOICE")); + assertEquals("123-456-7890", vCard.getPhoneWork("VOICE")); + + assertEquals("Work Locality", vCard.getAddressFieldWork("LOCALITY")); + assertEquals("Work Region", vCard.getAddressFieldWork("REGION")); + assertEquals("Work Post Code", vCard.getAddressFieldWork("PCODE")); + assertEquals("Work Country", vCard.getAddressFieldWork("CTRY")); + + assertEquals("Home Locality", vCard.getAddressFieldHome("LOCALITY")); + assertEquals("Home Region", vCard.getAddressFieldHome("REGION")); + assertEquals("Home Post Code", vCard.getAddressFieldHome("PCODE")); + assertEquals("Home Country", vCard.getAddressFieldHome("CTRY")); + + byte[] expectedAvatar = getAvatarBinary(); + assertTrue(Arrays.equals(vCard.getAvatar(), expectedAvatar)); + assertEquals(MIME_TYPE, vCard.getAvatarMimeType()); + } + @Test public void testNoWorkHomeSpecifier_EMAIL() throws Throwable { - VCard card = VCardProvider.createVCardFromXML("foo@fee.www.bar"); - assertEquals("foo@fee.www.bar", card.getEmailHome()); + + // @formatter:off + final String request = + "" + + "foo@fee.www.bar" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + + assertEquals("foo@fee.www.bar", vCard.getEmailHome()); } @Test public void testNoWorkHomeSpecifier_TEL() throws Throwable { - VCard card = VCardProvider.createVCardFromXML("3443233"); - assertEquals("3443233", card.getPhoneWork("FAX")); + + // @formatter:off + final String request = + "" + + "3443233" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + + assertEquals("3443233", vCard.getPhoneWork("FAX")); + } + + @Test + public void testUnknownTopLevelElementAdded() throws Throwable { + + // @formatter:off + final String request = + "" + + "1234" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + + assertEquals("1234", vCard.getField("UNKNOWN")); + } + + @Test + public void testUnknownComplexTopLevelElementNotAdded() throws Throwable { + + // @formatter:off + final String request = + "" + + "" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + + assertEquals(null, vCard.getField("UNKNOWN")); + } + + @Test + public void testUnknownAddressElementNotAdded() throws Throwable { + + // @formatter:off + final String request = + "" + + "1234" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + assertEquals(null, vCard.getField("UNKNOWN")); + } + + @Test + public void testUnknownDeepElementNotAdded() throws Throwable { + + // @formatter:off + final String request = + "" + + "1234" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + assertEquals(null, vCard.getField("UNKNOWN")); } @Test public void testNoWorkHomeSpecifier_ADDR() throws Throwable { - VCard card = VCardProvider.createVCardFromXML("Some streetddss"); - assertEquals("Some street", card.getAddressFieldWork("STREET")); - assertEquals("ddss", card.getAddressFieldWork("FF")); + + // @formatter:off + final String request = + "" + + "Some streetddss" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + + assertEquals("Some street", vCard.getAddressFieldWork("STREET")); + assertEquals("ddss", vCard.getAddressFieldWork("FF")); + } @Test public void testFN() throws Throwable { - VCard card = VCardProvider.createVCardFromXML("kir max"); - assertEquals("kir max", card.getField("FN")); - // assertEquals("kir max", card.getFullName()); + + // @formatter:off + final String request = + "" + + "kir max" + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + + assertEquals("kir max", vCard.getField("FN")); } private final static String MIME_TYPE = "testtype"; - private final static String VCARD_XML = "" + getAvatarEncoded() + "" + MIME_TYPE + ""; + private final static String VCARD_XML = "" + getAvatarEncoded() + + "" + MIME_TYPE + ""; + @Test public void testPhoto() throws Throwable { - VCard vc = VCardProvider.createVCardFromXML(VCARD_XML); - byte[] avatar = vc.getAvatar(); - String mimeType = vc.getAvatarMimeType(); + + // @formatter:off + final String request = + "" + + VCARD_XML + + ""; + // @formatter:on + + VCard vCard = (VCard) PacketParserUtils.parseStanza(request); + + byte[] avatar = vCard.getAvatar(); + String mimeType = vCard.getAvatarMimeType(); assertEquals(mimeType, MIME_TYPE); - + byte[] expectedAvatar = getAvatarBinary(); assertTrue(Arrays.equals(avatar, expectedAvatar)); }