001/* 002 * 003 * Copyright 2003-2007 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.vcardtemp.provider; 018 019import java.io.IOException; 020 021import org.jivesoftware.smack.packet.IqData; 022import org.jivesoftware.smack.packet.XmlEnvironment; 023import org.jivesoftware.smack.provider.IqProvider; 024import org.jivesoftware.smack.util.StringUtils; 025import org.jivesoftware.smack.xml.XmlPullParser; 026import org.jivesoftware.smack.xml.XmlPullParserException; 027 028import org.jivesoftware.smackx.vcardtemp.packet.VCard; 029 030import org.jxmpp.JxmppContext; 031 032/** 033 * vCard provider. 034 * 035 * @author Gaston Dombiak 036 * @author Derek DeMoro 037 * @author Chris Deering 038 */ 039public class VCardProvider extends IqProvider<VCard> { 040 041 // @formatter:off 042 private static final String[] ADR = new String[] { 043 "POSTAL", 044 "PARCEL", 045 "DOM", 046 "INTL", 047 "PREF", 048 "POBOX", 049 "EXTADR", 050 "STREET", 051 "LOCALITY", 052 "REGION", 053 "PCODE", 054 "CTRY", 055 "FF", 056 }; 057 058 private static final String[] TEL = new String[] { 059 "VOICE", 060 "FAX", 061 "PAGER", 062 "MSG", 063 "CELL", 064 "VIDEO", 065 "BBS", 066 "MODEM", 067 "ISDN", 068 "PCS", 069 "PREF", 070 }; 071 // @formatter:on 072 073 @Override 074 public VCard parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException { 075 VCard vCard = new VCard(); 076 String name = null; 077 078 outerloop: while (true) { 079 XmlPullParser.Event eventType = parser.next(); 080 switch (eventType) { 081 case START_ELEMENT: 082 name = parser.getName(); 083 switch (name) { 084 case "N": 085 parseName(parser, vCard); 086 break; 087 case "ORG": 088 parseOrg(parser, vCard); 089 break; 090 case "TEL": 091 parseTel(parser, vCard); 092 break; 093 case "ADR": 094 parseAddress(parser, vCard); 095 break; 096 case "EMAIL": 097 parseEmail(parser, vCard); 098 break; 099 case "NICKNAME": 100 vCard.setNickName(parser.nextText()); 101 break; 102 case "JABBERID": 103 vCard.setJabberId(parser.nextText()); 104 break; 105 case "PHOTO": 106 parsePhoto(parser, vCard); 107 break; 108 default: 109 break; 110 } 111 break; 112 case TEXT_CHARACTERS: 113 if (initialDepth + 1 == parser.getDepth()) { 114 String text = parser.getText(); 115 vCard.setField(name, text); 116 } 117 break; 118 case END_ELEMENT: 119 if (parser.getDepth() == initialDepth) { 120 break outerloop; 121 } 122 break; 123 default: 124 break; 125 } 126 } 127 128 return vCard; 129 } 130 131 private static void parseAddress(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 132 final int initialDepth = parser.getDepth(); 133 boolean isWork = true; 134 outerloop: while (true) { 135 XmlPullParser.Event eventType = parser.next(); 136 switch (eventType) { 137 case START_ELEMENT: 138 String name = parser.getName(); 139 if ("HOME".equals(name)) { 140 isWork = false; 141 } 142 else { 143 for (String adr : ADR) { 144 if (adr.equals(name)) { 145 if (isWork) { 146 vCard.setAddressFieldWork(name, parser.nextText()); 147 } 148 else { 149 vCard.setAddressFieldHome(name, parser.nextText()); 150 } 151 } 152 } 153 } 154 break; 155 case END_ELEMENT: 156 if (parser.getDepth() == initialDepth) { 157 break outerloop; 158 } 159 break; 160 default: 161 break; 162 } 163 } 164 } 165 166 private static void parseTel(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 167 final int initialDepth = parser.getDepth(); 168 boolean isWork = true; 169 String telLabel = null; 170 171 outerloop: while (true) { 172 XmlPullParser.Event eventType = parser.next(); 173 switch (eventType) { 174 case START_ELEMENT: 175 String name = parser.getName(); 176 if ("HOME".equals(name)) { 177 isWork = false; 178 } 179 else { 180 if ("NUMBER".equals(name)) { 181 if (StringUtils.isNullOrEmpty(telLabel)) { 182 // RFC 2426 ยง 3.3.1: 183 // "The default type is 'voice'" 184 telLabel = "VOICE"; 185 } 186 if (isWork) { 187 vCard.setPhoneWork(telLabel, parser.nextText()); 188 } 189 else { 190 vCard.setPhoneHome(telLabel, parser.nextText()); 191 } 192 } 193 else { 194 for (String tel : TEL) { 195 if (tel.equals(name)) { 196 telLabel = name; 197 } 198 } 199 } 200 } 201 break; 202 case END_ELEMENT: 203 if (parser.getDepth() == initialDepth) { 204 break outerloop; 205 } 206 break; 207 default: 208 break; 209 } 210 } 211 } 212 213 private static void parseOrg(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 214 final int initialDepth = parser.getDepth(); 215 216 outerloop: while (true) { 217 XmlPullParser.Event eventType = parser.next(); 218 switch (eventType) { 219 case START_ELEMENT: 220 String name = parser.getName(); 221 switch (name) { 222 case "ORGNAME": 223 vCard.setOrganization(parser.nextText()); 224 break; 225 case "ORGUNIT": 226 vCard.setOrganizationUnit(parser.nextText()); 227 break; 228 default: 229 break; 230 } 231 break; 232 case END_ELEMENT: 233 if (parser.getDepth() == initialDepth) { 234 break outerloop; 235 } 236 break; 237 default: 238 break; 239 } 240 } 241 } 242 243 private static void parseEmail(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 244 final int initialDepth = parser.getDepth(); 245 boolean isWork = false; 246 247 outerloop: while (true) { 248 XmlPullParser.Event eventType = parser.next(); 249 switch (eventType) { 250 case START_ELEMENT: 251 String name = parser.getName(); 252 switch (name) { 253 case "WORK": 254 isWork = true; 255 break; 256 case "USERID": 257 if (isWork) { 258 vCard.setEmailWork(parser.nextText()); 259 } 260 else { 261 vCard.setEmailHome(parser.nextText()); 262 } 263 break; 264 default: 265 break; 266 } 267 break; 268 case END_ELEMENT: 269 if (parser.getDepth() == initialDepth) { 270 break outerloop; 271 } 272 break; 273 default: 274 break; 275 } 276 } 277 } 278 279 private static void parseName(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 280 final int initialDepth = parser.getDepth(); 281 282 outerloop: while (true) { 283 XmlPullParser.Event eventType = parser.next(); 284 switch (eventType) { 285 case START_ELEMENT: 286 String name = parser.getName(); 287 switch (name) { 288 case "FAMILY": 289 vCard.setLastName(parser.nextText()); 290 break; 291 case "GIVEN": 292 vCard.setFirstName(parser.nextText()); 293 break; 294 case "MIDDLE": 295 vCard.setMiddleName(parser.nextText()); 296 break; 297 case "PREFIX": 298 vCard.setPrefix(parser.nextText()); 299 break; 300 case "SUFFIX": 301 vCard.setSuffix(parser.nextText()); 302 break; 303 default: 304 break; 305 } 306 break; 307 case END_ELEMENT: 308 if (parser.getDepth() == initialDepth) { 309 break outerloop; 310 } 311 break; 312 default: 313 break; 314 315 } 316 } 317 } 318 319 private static void parsePhoto(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 320 final int initialDepth = parser.getDepth(); 321 String binval = null; 322 String mimetype = null; 323 324 outerloop: while (true) { 325 XmlPullParser.Event eventType = parser.next(); 326 switch (eventType) { 327 case START_ELEMENT: 328 String name = parser.getName(); 329 switch (name) { 330 case "BINVAL": 331 binval = parser.nextText(); 332 break; 333 case "TYPE": 334 mimetype = parser.nextText(); 335 break; 336 default: 337 break; 338 } 339 break; 340 case END_ELEMENT: 341 if (parser.getDepth() == initialDepth) { 342 break outerloop; 343 } 344 break; 345 default: 346 break; 347 } 348 } 349 350 if (binval == null || mimetype == null) { 351 return; 352 } 353 354 vCard.setAvatar(binval, mimetype); 355 } 356}