• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * $RCSfile$
3  * $Revision$
4  * $Date$
5  *
6  * Copyright 2003-2007 Jive Software.
7  *
8  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 package org.jivesoftware.smackx.provider;
22 
23 import org.jivesoftware.smack.packet.IQ;
24 import org.jivesoftware.smack.provider.IQProvider;
25 import org.jivesoftware.smack.util.StringUtils;
26 import org.jivesoftware.smackx.packet.VCard;
27 import org.w3c.dom.*;
28 import org.xmlpull.v1.XmlPullParser;
29 import org.xmlpull.v1.XmlPullParserException;
30 
31 import javax.xml.parsers.DocumentBuilder;
32 import javax.xml.parsers.DocumentBuilderFactory;
33 import java.io.ByteArrayInputStream;
34 import java.io.IOException;
35 import java.util.ArrayList;
36 import java.util.List;
37 
38 /**
39  * vCard provider.
40  *
41  * @author Gaston Dombiak
42  * @author Derek DeMoro
43  */
44 public class VCardProvider implements IQProvider {
45 
46     private static final String PREFERRED_ENCODING = "UTF-8";
47 
parseIQ(XmlPullParser parser)48     public IQ parseIQ(XmlPullParser parser) throws Exception {
49         final StringBuilder sb = new StringBuilder();
50         try {
51             int event = parser.getEventType();
52             // get the content
53             while (true) {
54                 switch (event) {
55                     case XmlPullParser.TEXT:
56                         // We must re-escape the xml so that the DOM won't throw an exception
57                         sb.append(StringUtils.escapeForXML(parser.getText()));
58                         break;
59                     case XmlPullParser.START_TAG:
60                         sb.append('<').append(parser.getName()).append('>');
61                         break;
62                     case XmlPullParser.END_TAG:
63                         sb.append("</").append(parser.getName()).append('>');
64                         break;
65                     default:
66                 }
67 
68                 if (event == XmlPullParser.END_TAG && "vCard".equals(parser.getName())) break;
69 
70                 event = parser.next();
71             }
72         }
73         catch (XmlPullParserException e) {
74             e.printStackTrace();
75         }
76         catch (IOException e) {
77             e.printStackTrace();
78         }
79 
80         String xmlText = sb.toString();
81         return createVCardFromXML(xmlText);
82     }
83 
84     /**
85      * Builds a users vCard from xml file.
86      *
87      * @param xml the xml representing a users vCard.
88      * @return the VCard.
89      * @throws Exception if an exception occurs.
90      */
createVCardFromXML(String xml)91     public static VCard createVCardFromXML(String xml) throws Exception {
92         VCard vCard = new VCard();
93 
94         DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
95         DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
96         Document document = documentBuilder.parse(
97                 new ByteArrayInputStream(xml.getBytes(PREFERRED_ENCODING)));
98 
99         new VCardReader(vCard, document).initializeFields();
100         return vCard;
101     }
102 
103     private static class VCardReader {
104 
105         private final VCard vCard;
106         private final Document document;
107 
VCardReader(VCard vCard, Document document)108         VCardReader(VCard vCard, Document document) {
109             this.vCard = vCard;
110             this.document = document;
111         }
112 
initializeFields()113         public void initializeFields() {
114             vCard.setFirstName(getTagContents("GIVEN"));
115             vCard.setLastName(getTagContents("FAMILY"));
116             vCard.setMiddleName(getTagContents("MIDDLE"));
117             setupPhoto();
118 
119             setupEmails();
120 
121             vCard.setOrganization(getTagContents("ORGNAME"));
122             vCard.setOrganizationUnit(getTagContents("ORGUNIT"));
123 
124             setupSimpleFields();
125 
126             setupPhones();
127             setupAddresses();
128         }
129 
setupPhoto()130         private void setupPhoto() {
131             String binval = null;
132             String mimetype = null;
133 
134             NodeList photo = document.getElementsByTagName("PHOTO");
135             if (photo.getLength() != 1)
136                 return;
137 
138             Node photoNode = photo.item(0);
139             NodeList childNodes = photoNode.getChildNodes();
140 
141             int childNodeCount = childNodes.getLength();
142             List<Node> nodes = new ArrayList<Node>(childNodeCount);
143             for (int i = 0; i < childNodeCount; i++)
144                 nodes.add(childNodes.item(i));
145 
146             String name = null;
147             String value = null;
148             for (Node n : nodes) {
149                 name = n.getNodeName();
150                 value = n.getTextContent();
151                 if (name.equals("BINVAL")) {
152                     binval = value;
153                 }
154                 else if (name.equals("TYPE")) {
155                     mimetype = value;
156                 }
157             }
158 
159             if (binval == null || mimetype == null)
160                 return;
161 
162             vCard.setAvatar(binval, mimetype);
163         }
164 
setupEmails()165         private void setupEmails() {
166             NodeList nodes = document.getElementsByTagName("USERID");
167             if (nodes == null) return;
168             for (int i = 0; i < nodes.getLength(); i++) {
169                 Element element = (Element) nodes.item(i);
170                 if ("WORK".equals(element.getParentNode().getFirstChild().getNodeName())) {
171                     vCard.setEmailWork(getTextContent(element));
172                 }
173                 else {
174                     vCard.setEmailHome(getTextContent(element));
175                 }
176             }
177         }
178 
setupPhones()179         private void setupPhones() {
180             NodeList allPhones = document.getElementsByTagName("TEL");
181             if (allPhones == null) return;
182             for (int i = 0; i < allPhones.getLength(); i++) {
183                 NodeList nodes = allPhones.item(i).getChildNodes();
184                 String type = null;
185                 String code = null;
186                 String value = null;
187                 for (int j = 0; j < nodes.getLength(); j++) {
188                     Node node = nodes.item(j);
189                     if (node.getNodeType() != Node.ELEMENT_NODE) continue;
190                     String nodeName = node.getNodeName();
191                     if ("NUMBER".equals(nodeName)) {
192                         value = getTextContent(node);
193                     }
194                     else if (isWorkHome(nodeName)) {
195                         type = nodeName;
196                     }
197                     else {
198                         code = nodeName;
199                     }
200                 }
201                 if (code == null || value == null) continue;
202                 if ("HOME".equals(type)) {
203                     vCard.setPhoneHome(code, value);
204                 }
205                 else { // By default, setup work phone
206                     vCard.setPhoneWork(code, value);
207                 }
208             }
209         }
210 
isWorkHome(String nodeName)211         private boolean isWorkHome(String nodeName) {
212             return "HOME".equals(nodeName) || "WORK".equals(nodeName);
213         }
214 
setupAddresses()215         private void setupAddresses() {
216             NodeList allAddresses = document.getElementsByTagName("ADR");
217             if (allAddresses == null) return;
218             for (int i = 0; i < allAddresses.getLength(); i++) {
219                 Element addressNode = (Element) allAddresses.item(i);
220 
221                 String type = null;
222                 List<String> code = new ArrayList<String>();
223                 List<String> value = new ArrayList<String>();
224                 NodeList childNodes = addressNode.getChildNodes();
225                 for (int j = 0; j < childNodes.getLength(); j++) {
226                     Node node = childNodes.item(j);
227                     if (node.getNodeType() != Node.ELEMENT_NODE) continue;
228                     String nodeName = node.getNodeName();
229                     if (isWorkHome(nodeName)) {
230                         type = nodeName;
231                     }
232                     else {
233                         code.add(nodeName);
234                         value.add(getTextContent(node));
235                     }
236                 }
237                 for (int j = 0; j < value.size(); j++) {
238                     if ("HOME".equals(type)) {
239                         vCard.setAddressFieldHome((String) code.get(j), (String) value.get(j));
240                     }
241                     else { // By default, setup work address
242                         vCard.setAddressFieldWork((String) code.get(j), (String) value.get(j));
243                     }
244                 }
245             }
246         }
247 
getTagContents(String tag)248         private String getTagContents(String tag) {
249             NodeList nodes = document.getElementsByTagName(tag);
250             if (nodes != null && nodes.getLength() == 1) {
251                 return getTextContent(nodes.item(0));
252             }
253             return null;
254         }
255 
setupSimpleFields()256         private void setupSimpleFields() {
257             NodeList childNodes = document.getDocumentElement().getChildNodes();
258             for (int i = 0; i < childNodes.getLength(); i++) {
259                 Node node = childNodes.item(i);
260                 if (node instanceof Element) {
261                     Element element = (Element) node;
262 
263                     String field = element.getNodeName();
264                     if (element.getChildNodes().getLength() == 0) {
265                         vCard.setField(field, "");
266                     }
267                     else if (element.getChildNodes().getLength() == 1 &&
268                             element.getChildNodes().item(0) instanceof Text) {
269                         vCard.setField(field, getTextContent(element));
270                     }
271                 }
272             }
273         }
274 
getTextContent(Node node)275         private String getTextContent(Node node) {
276             StringBuilder result = new StringBuilder();
277             appendText(result, node);
278             return result.toString();
279         }
280 
appendText(StringBuilder result, Node node)281         private void appendText(StringBuilder result, Node node) {
282             NodeList childNodes = node.getChildNodes();
283             for (int i = 0; i < childNodes.getLength(); i++) {
284                 Node nd = childNodes.item(i);
285                 String nodeValue = nd.getNodeValue();
286                 if (nodeValue != null) {
287                     result.append(nodeValue);
288                 }
289                 appendText(result, nd);
290             }
291         }
292     }
293 }
294