mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-14 11:42:04 +01:00
293 lines
10 KiB
Java
293 lines
10 KiB
Java
/**
|
|
*
|
|
* Copyright 2003-2007 Jive Software.
|
|
*
|
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package org.jivesoftware.smackx.provider;
|
|
|
|
import org.jivesoftware.smack.packet.IQ;
|
|
import org.jivesoftware.smack.provider.IQProvider;
|
|
import org.jivesoftware.smack.util.StringUtils;
|
|
import org.jivesoftware.smackx.packet.VCard;
|
|
import org.w3c.dom.*;
|
|
import org.xmlpull.v1.XmlPullParser;
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.IOException;
|
|
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
|
|
*/
|
|
public class VCardProvider implements IQProvider {
|
|
private static Logger log = Logger.getLogger(VCardProvider.class.getName());
|
|
|
|
private static final String PREFERRED_ENCODING = "UTF-8";
|
|
|
|
public IQ parseIQ(XmlPullParser parser) throws Exception {
|
|
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("</").append(parser.getName()).append('>');
|
|
break;
|
|
default:
|
|
}
|
|
|
|
if (event == XmlPullParser.END_TAG && "vCard".equals(parser.getName())) break;
|
|
|
|
event = parser.next();
|
|
}
|
|
}
|
|
catch (XmlPullParserException e) {
|
|
log.log(Level.SEVERE, "Exception parsing VCard", e);
|
|
}
|
|
catch (IOException e) {
|
|
log.log(Level.SEVERE, "Exception parsing VCard", e);
|
|
}
|
|
|
|
String xmlText = sb.toString();
|
|
return createVCardFromXML(xmlText);
|
|
}
|
|
|
|
/**
|
|
* Builds a users vCard from xml file.
|
|
*
|
|
* @param xml the xml representing a users vCard.
|
|
* @return the VCard.
|
|
* @throws Exception if an exception occurs.
|
|
*/
|
|
public static VCard createVCardFromXML(String xml) throws Exception {
|
|
VCard vCard = new VCard();
|
|
|
|
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
|
DocumentBuilder documentBuilder = documentBuilderFactory.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<Node> nodes = new ArrayList<Node>(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));
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
if (code == null || value == null) continue;
|
|
if ("HOME".equals(type)) {
|
|
vCard.setPhoneHome(code, value);
|
|
}
|
|
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<String> code = new ArrayList<String>();
|
|
List<String> value = new ArrayList<String>();
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|