1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$ 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$ 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$ 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2007 Jive Software. 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smackx.packet; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.BufferedInputStream; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.File; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.FileInputStream; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.IOException; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.reflect.Field; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.reflect.Modifier; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.URL; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.security.MessageDigest; 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.security.NoSuchAlgorithmException; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.HashMap; 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Iterator; 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Map; 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Map.Entry; 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.Connection; 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.PacketCollector; 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.SmackConfiguration; 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.XMPPException; 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.PacketIDFilter; 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.IQ; 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Packet; 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.XMPPError; 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.util.StringUtils; 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A VCard class for use with the 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <a href="http://www.jivesoftware.org/smack/" target="_blank">SMACK jabber library</a>.<p> 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You should refer to the 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <a href="http://www.jabber.org/jeps/jep-0054.html" target="_blank">JEP-54 documentation</a>.<p> 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Please note that this class is incomplete but it does provide the most commonly found 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * information in vCards. Also remember that VCard transfer is not a standard, and the protocol 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * may change or be replaced.<p> 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <b>Usage:</b> 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <pre> 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // To save VCard: 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * VCard vCard = new VCard(); 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setFirstName("kir"); 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setLastName("max"); 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setEmailHome("foo@fee.bar"); 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setJabberId("jabber@id.org"); 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setOrganization("Jetbrains, s.r.o"); 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setNickName("KIR"); 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setField("TITLE", "Mr"); 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setAddressFieldHome("STREET", "Some street"); 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setAddressFieldWork("CTRY", "US"); 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.setPhoneWork("FAX", "3443233"); 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.save(connection); 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // To load VCard: 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * VCard vCard = new VCard(); 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.load(conn); // load own VCard 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * vCard.load(conn, "joe@foo.bar"); // load someone's VCard 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </pre> 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Kirill Maximov (kir@maxkir.com) 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class VCard extends IQ { 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Phone types: 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * VOICE?, FAX?, PAGER?, MSG?, CELL?, VIDEO?, BBS?, MODEM?, ISDN?, PCS?, PREF? 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Map<String, String> homePhones = new HashMap<String, String>(); 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Map<String, String> workPhones = new HashMap<String, String>(); 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Address types: 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * POSTAL?, PARCEL?, (DOM | INTL)?, PREF?, POBOX?, EXTADR?, STREET?, LOCALITY?, 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * REGION?, PCODE?, CTRY? 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Map<String, String> homeAddr = new HashMap<String, String>(); 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Map<String, String> workAddr = new HashMap<String, String>(); 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String firstName; 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String lastName; 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String middleName; 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String emailHome; 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String emailWork; 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String organization; 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String organizationUnit; 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String photoMimeType; 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String photoBinval; 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Such as DESC ROLE GEO etc.. see JEP-0054 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Map<String, String> otherSimpleFields = new HashMap<String, String>(); 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // fields that, as they are should not be escaped before forwarding to the server 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Map<String, String> otherUnescapableFields = new HashMap<String, String>(); 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public VCard() { 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Set generic VCard field. 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param field value of field. Possible values: NICKNAME, PHOTO, BDAY, JABBERID, MAILER, TZ, 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * GEO, TITLE, ROLE, LOGO, NOTE, PRODID, REV, SORT-STRING, SOUND, UID, URL, DESC. 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getField(String field) { 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return otherSimpleFields.get(field); 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Set generic VCard field. 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param value value of field 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param field field to set. See {@link #getField(String)} 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see #getField(String) 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setField(String field, String value) { 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setField(field, value, false); 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Set generic, unescapable VCard field. If unescabale is set to true, XML maybe a part of the 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * value. 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param value value of field 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param field field to set. See {@link #getField(String)} 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param isUnescapable True if the value should not be escaped, and false if it should. 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setField(String field, String value, boolean isUnescapable) { 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!isUnescapable) { 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen otherSimpleFields.put(field, value); 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen otherUnescapableFields.put(field, value); 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getFirstName() { 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return firstName; 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setFirstName(String firstName) { 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.firstName = firstName; 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Update FN field 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen updateFN(); 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getLastName() { 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return lastName; 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setLastName(String lastName) { 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.lastName = lastName; 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Update FN field 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen updateFN(); 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getMiddleName() { 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return middleName; 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setMiddleName(String middleName) { 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.middleName = middleName; 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Update FN field 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen updateFN(); 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getNickName() { 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return otherSimpleFields.get("NICKNAME"); 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setNickName(String nickName) { 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen otherSimpleFields.put("NICKNAME", nickName); 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getEmailHome() { 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return emailHome; 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setEmailHome(String email) { 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.emailHome = email; 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getEmailWork() { 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return emailWork; 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setEmailWork(String emailWork) { 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.emailWork = emailWork; 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getJabberId() { 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return otherSimpleFields.get("JABBERID"); 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setJabberId(String jabberId) { 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen otherSimpleFields.put("JABBERID", jabberId); 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getOrganization() { 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return organization; 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setOrganization(String organization) { 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.organization = organization; 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getOrganizationUnit() { 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return organizationUnit; 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setOrganizationUnit(String organizationUnit) { 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.organizationUnit = organizationUnit; 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Get home address field 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET, 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * LOCALITY, REGION, PCODE, CTRY 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getAddressFieldHome(String addrField) { 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return homeAddr.get(addrField); 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Set home address field 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET, 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * LOCALITY, REGION, PCODE, CTRY 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setAddressFieldHome(String addrField, String value) { 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen homeAddr.put(addrField, value); 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Get work address field 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET, 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * LOCALITY, REGION, PCODE, CTRY 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getAddressFieldWork(String addrField) { 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return workAddr.get(addrField); 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Set work address field 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET, 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * LOCALITY, REGION, PCODE, CTRY 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setAddressFieldWork(String addrField, String value) { 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen workAddr.put(addrField, value); 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Set home phone number 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param phoneNum phone number 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setPhoneHome(String phoneType, String phoneNum) { 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen homePhones.put(phoneType, phoneNum); 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Get home phone number 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getPhoneHome(String phoneType) { 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return homePhones.get(phoneType); 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Set work phone number 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param phoneNum phone number 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setPhoneWork(String phoneType, String phoneNum) { 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen workPhones.put(phoneType, phoneNum); 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Get work phone number 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getPhoneWork(String phoneType) { 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return workPhones.get(phoneType); 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Set the avatar for the VCard by specifying the url to the image. 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param avatarURL the url to the image(png,jpeg,gif,bmp) 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setAvatar(URL avatarURL) { 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte[] bytes = new byte[0]; 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen bytes = getBytes(avatarURL); 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (IOException e) { 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setAvatar(bytes); 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes the avatar from the vCard 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This is done by setting the PHOTO value to the empty string as defined in XEP-0153 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removeAvatar() { 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Remove avatar (if any) 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen photoBinval = null; 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen photoMimeType = null; 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Specify the bytes of the JPEG for the avatar to use. 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If bytes is null, then the avatar will be removed. 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 'image/jpeg' will be used as MIME type. 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param bytes the bytes of the avatar, or null to remove the avatar data 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setAvatar(byte[] bytes) { 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setAvatar(bytes, "image/jpeg"); 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Specify the bytes for the avatar to use as well as the mime type. 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param bytes the bytes of the avatar. 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param mimeType the mime type of the avatar. 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setAvatar(byte[] bytes, String mimeType) { 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If bytes is null, remove the avatar 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (bytes == null) { 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen removeAvatar(); 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Otherwise, add to mappings. 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String encodedImage = StringUtils.encodeBase64(bytes); 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setAvatar(encodedImage, mimeType); 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Specify the Avatar used for this vCard. 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param encodedImage the Base64 encoded image as String 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param mimeType the MIME type of the image 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void setAvatar(String encodedImage, String mimeType) { 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen photoBinval = encodedImage; 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen photoMimeType = mimeType; 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Return the byte representation of the avatar(if one exists), otherwise returns null if 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * no avatar could be found. 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <b>Example 1</b> 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <pre> 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // Load Avatar from VCard 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * byte[] avatarBytes = vCard.getAvatar(); 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // To create an ImageIcon for Swing applications 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * ImageIcon icon = new ImageIcon(avatar); 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // To create just an image object from the bytes 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * ByteArrayInputStream bais = new ByteArrayInputStream(avatar); 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * try { 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Image image = ImageIO.read(bais); 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * } 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * catch (IOException e) { 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * e.printStackTrace(); 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * } 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </pre> 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return byte representation of avatar. 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public byte[] getAvatar() { 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (photoBinval == null) { 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return StringUtils.decodeBase64(photoBinval); 421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the MIME Type of the avatar or null if none is set 425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the MIME Type of the avatar or null 427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getAvatarMimeType() { 429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return photoMimeType; 430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Common code for getting the bytes of a url. 434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param url the url to read. 436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static byte[] getBytes(URL url) throws IOException { 438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final String path = url.getPath(); 439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final File file = new File(path); 440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (file.exists()) { 441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getFileBytes(file); 442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static byte[] getFileBytes(File file) throws IOException { 448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen BufferedInputStream bis = null; 449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen bis = new BufferedInputStream(new FileInputStream(file)); 451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int bytes = (int) file.length(); 452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte[] buffer = new byte[bytes]; 453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int readBytes = bis.read(buffer); 454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (readBytes != buffer.length) { 455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IOException("Entire file not read"); 456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return buffer; 458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen finally { 460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (bis != null) { 461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen bis.close(); 462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the SHA-1 Hash of the Avatar image. 468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the SHA-1 Hash of the Avatar image. 470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getAvatarHash() { 472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte[] bytes = getAvatar(); 473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (bytes == null) { 474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MessageDigest digest; 478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen digest = MessageDigest.getInstance("SHA-1"); 480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (NoSuchAlgorithmException e) { 482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen digest.update(bytes); 487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return StringUtils.encodeHex(digest.digest()); 488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void updateFN() { 491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuilder sb = new StringBuilder(); 492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (firstName != null) { 493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(StringUtils.escapeForXML(firstName)).append(' '); 494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (middleName != null) { 496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(StringUtils.escapeForXML(middleName)).append(' '); 497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (lastName != null) { 499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(StringUtils.escapeForXML(lastName)); 500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setField("FN", sb.toString()); 502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Save this vCard for the user connected by 'connection'. Connection should be authenticated 506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and not anonymous.<p> 507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * NOTE: the method is asynchronous and does not wait for the returned value. 509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the Connection to use. 511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException thrown if there was an issue setting the VCard in the server. 512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void save(Connection connection) throws XMPPException { 514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkAuthenticated(connection, true); 515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setType(IQ.Type.SET); 517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setFrom(connection.getUser()); 518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(getPacketID())); 519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(this); 520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Packet response = collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Cancel the collector. 524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen collector.cancel(); 525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (response == null) { 526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server on status set."); 527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (response.getError() != null) { 529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(response.getError()); 530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Load VCard information for a connected user. Connection should be authenticated 535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and not anonymous. 536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void load(Connection connection) throws XMPPException { 538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkAuthenticated(connection, true); 539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setFrom(connection.getUser()); 541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen doLoad(connection, connection.getUser()); 542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Load VCard information for a given user. Connection should be authenticated and not anonymous. 546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void load(Connection connection, String user) throws XMPPException { 548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkAuthenticated(connection, false); 549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setTo(user); 551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen doLoad(connection, user); 552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void doLoad(Connection connection, String user) throws XMPPException { 555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setType(Type.GET); 556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector collector = connection.createPacketCollector( 557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new PacketIDFilter(getPacketID())); 558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(this); 559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen VCard result = null; 561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = (VCard) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (result == null) { 565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String errorMessage = "Timeout getting VCard information"; 566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(errorMessage, new XMPPError( 567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen XMPPError.Condition.request_timeout, errorMessage)); 568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (result.getError() != null) { 570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(result.getError()); 571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (ClassCastException e) { 574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println("No VCard for " + user); 575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen copyFieldsFrom(result); 578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getChildElementXML() { 581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuilder sb = new StringBuilder(); 582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new VCardWriter(sb).write(); 583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sb.toString(); 584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void copyFieldsFrom(VCard from) { 587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Field[] fields = VCard.class.getDeclaredFields(); 588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Field field : fields) { 589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (field.getDeclaringClass() == VCard.class && 590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen !Modifier.isFinal(field.getModifiers())) { 591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen field.setAccessible(true); 593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen field.set(this, field.get(from)); 594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (IllegalAccessException e) { 596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new RuntimeException("This cannot happen:" + field, e); 597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void checkAuthenticated(Connection connection, boolean checkForAnonymous) { 603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (connection == null) { 604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("No connection was provided"); 605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!connection.isAuthenticated()) { 607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("Connection is not authenticated"); 608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (checkForAnonymous && connection.isAnonymous()) { 610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("Connection cannot be anonymous"); 611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean hasContent() { 615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //noinspection OverlyComplexBooleanExpression 616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return hasNameField() 617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || hasOrganizationFields() 618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || emailHome != null 619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || emailWork != null 620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || otherSimpleFields.size() > 0 621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || otherUnescapableFields.size() > 0 622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || homeAddr.size() > 0 623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || homePhones.size() > 0 624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || workAddr.size() > 0 625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || workPhones.size() > 0 626d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen || photoBinval != null 627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ; 628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean hasNameField() { 631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return firstName != null || lastName != null || middleName != null; 632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean hasOrganizationFields() { 635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return organization != null || organizationUnit != null; 636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Used in tests: 639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean equals(Object o) { 641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (this == o) return true; 642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (o == null || getClass() != o.getClass()) return false; 643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final VCard vCard = (VCard) o; 645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (emailHome != null ? !emailHome.equals(vCard.emailHome) : vCard.emailHome != null) { 647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (emailWork != null ? !emailWork.equals(vCard.emailWork) : vCard.emailWork != null) { 650d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (firstName != null ? !firstName.equals(vCard.firstName) : vCard.firstName != null) { 653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!homeAddr.equals(vCard.homeAddr)) { 656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!homePhones.equals(vCard.homePhones)) { 659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (lastName != null ? !lastName.equals(vCard.lastName) : vCard.lastName != null) { 662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (middleName != null ? !middleName.equals(vCard.middleName) : vCard.middleName != null) { 665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (organization != null ? 668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen !organization.equals(vCard.organization) : vCard.organization != null) { 669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (organizationUnit != null ? 672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen !organizationUnit.equals(vCard.organizationUnit) : vCard.organizationUnit != null) { 673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!otherSimpleFields.equals(vCard.otherSimpleFields)) { 676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!workAddr.equals(vCard.workAddr)) { 679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (photoBinval != null ? !photoBinval.equals(vCard.photoBinval) : vCard.photoBinval != null) { 682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 683d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return workPhones.equals(vCard.workPhones); 686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int hashCode() { 689d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int result; 690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = homePhones.hashCode(); 691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + workPhones.hashCode(); 692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + homeAddr.hashCode(); 693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + workAddr.hashCode(); 694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + (firstName != null ? firstName.hashCode() : 0); 695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + (lastName != null ? lastName.hashCode() : 0); 696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + (middleName != null ? middleName.hashCode() : 0); 697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + (emailHome != null ? emailHome.hashCode() : 0); 698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + (emailWork != null ? emailWork.hashCode() : 0); 699d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + (organization != null ? organization.hashCode() : 0); 700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + (organizationUnit != null ? organizationUnit.hashCode() : 0); 701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + otherSimpleFields.hashCode(); 702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen result = 29 * result + (photoBinval != null ? photoBinval.hashCode() : 0); 703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return result; 704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String toString() { 707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getChildElementXML(); 708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 709d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //============================================================== 711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private class VCardWriter { 713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final StringBuilder sb; 715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen VCardWriter(StringBuilder sb) { 717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.sb = sb; 718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 719d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void write() { 721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("vCard", "xmlns", "vcard-temp", hasContent(), new ContentBuilder() { 722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addTagContent() { 723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buildActualContent(); 724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 726d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void buildActualContent() { 729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (hasNameField()) { 730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendN(); 731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendOrganization(); 734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendGenericFields(); 735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendPhoto(); 736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 737d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendEmail(emailWork, "WORK"); 738d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendEmail(emailHome, "HOME"); 739d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 740d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendPhones(workPhones, "WORK"); 741d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendPhones(homePhones, "HOME"); 742d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 743d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendAddress(workAddr, "WORK"); 744d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendAddress(homeAddr, "HOME"); 745d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 746d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 747d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendPhoto() { 748d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (photoBinval == null) 749d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 750d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 751d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("PHOTO", true, new ContentBuilder() { 752d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addTagContent() { 753d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("BINVAL", photoBinval); // No need to escape photoBinval, as it's already Base64 encoded 754d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("TYPE", StringUtils.escapeForXML(photoMimeType)); 755d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 756d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 757d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 758d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendEmail(final String email, final String type) { 759d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (email != null) { 760d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("EMAIL", true, new ContentBuilder() { 761d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addTagContent() { 762d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendEmptyTag(type); 763d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendEmptyTag("INTERNET"); 764d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendEmptyTag("PREF"); 765d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("USERID", StringUtils.escapeForXML(email)); 766d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 767d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 768d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 769d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 770d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 771d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendPhones(Map<String, String> phones, final String code) { 772d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Iterator<Map.Entry<String, String>> it = phones.entrySet().iterator(); 773d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (it.hasNext()) { 774d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final Map.Entry<String,String> entry = it.next(); 775d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("TEL", true, new ContentBuilder() { 776d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addTagContent() { 777d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendEmptyTag(entry.getKey()); 778d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendEmptyTag(code); 779d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("NUMBER", StringUtils.escapeForXML(entry.getValue())); 780d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 781d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 782d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 783d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 784d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 785d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendAddress(final Map<String, String> addr, final String code) { 786d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (addr.size() > 0) { 787d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("ADR", true, new ContentBuilder() { 788d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addTagContent() { 789d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendEmptyTag(code); 790d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 791d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Iterator<Map.Entry<String, String>> it = addr.entrySet().iterator(); 792d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (it.hasNext()) { 793d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final Entry<String, String> entry = it.next(); 794d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag(entry.getKey(), StringUtils.escapeForXML(entry.getValue())); 795d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 796d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 797d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 798d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 799d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 800d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 801d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendEmptyTag(Object tag) { 802d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('<').append(tag).append("/>"); 803d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 804d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 805d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendGenericFields() { 806d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Iterator<Map.Entry<String, String>> it = otherSimpleFields.entrySet().iterator(); 807d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (it.hasNext()) { 808d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Map.Entry<String, String> entry = it.next(); 809d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag(entry.getKey().toString(), 810d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringUtils.escapeForXML(entry.getValue())); 811d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 812d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 813d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen it = otherUnescapableFields.entrySet().iterator(); 814d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (it.hasNext()) { 815d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Map.Entry<String, String> entry = it.next(); 816d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag(entry.getKey().toString(),entry.getValue()); 817d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 818d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 819d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 820d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendOrganization() { 821d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (hasOrganizationFields()) { 822d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("ORG", true, new ContentBuilder() { 823d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addTagContent() { 824d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("ORGNAME", StringUtils.escapeForXML(organization)); 825d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("ORGUNIT", StringUtils.escapeForXML(organizationUnit)); 826d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 827d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 828d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 829d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 830d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 831d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendN() { 832d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("N", true, new ContentBuilder() { 833d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addTagContent() { 834d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("FAMILY", StringUtils.escapeForXML(lastName)); 835d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("GIVEN", StringUtils.escapeForXML(firstName)); 836d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag("MIDDLE", StringUtils.escapeForXML(middleName)); 837d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 838d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 839d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 840d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 841d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendTag(String tag, String attr, String attrValue, boolean hasContent, 842d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ContentBuilder builder) { 843d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('<').append(tag); 844d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (attr != null) { 845d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(' ').append(attr).append('=').append('\'').append(attrValue).append('\''); 846d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 847d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 848d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (hasContent) { 849d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('>'); 850d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen builder.addTagContent(); 851d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("</").append(tag).append(">\n"); 852d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 853d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 854d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("/>\n"); 855d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 856d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 857d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 858d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendTag(String tag, boolean hasContent, ContentBuilder builder) { 859d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag(tag, null, null, hasContent, builder); 860d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 861d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 862d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void appendTag(String tag, final String tagText) { 863d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (tagText == null) return; 864d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final ContentBuilder contentBuilder = new ContentBuilder() { 865d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addTagContent() { 866d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(tagText.trim()); 867d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 868d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 869d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen appendTag(tag, true, contentBuilder); 870d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 871d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 872d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 873d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 874d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //============================================================== 875d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 876d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private interface ContentBuilder { 877d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 878d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen void addTagContent(); 879d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 880d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 881d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //============================================================== 882d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 883d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 884