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