mas01mj@732: /* mas01mj@732: Copyright (c) 2008, Adobe Systems Incorporated mas01mj@732: All rights reserved. mas01mj@732: mas01mj@732: Redistribution and use in source and binary forms, with or without mas01mj@732: modification, are permitted provided that the following conditions are mas01mj@732: met: mas01mj@732: mas01mj@732: * Redistributions of source code must retain the above copyright notice, mas01mj@732: this list of conditions and the following disclaimer. mas01mj@732: mas01mj@732: * Redistributions in binary form must reproduce the above copyright mas01mj@732: notice, this list of conditions and the following disclaimer in the mas01mj@732: documentation and/or other materials provided with the distribution. mas01mj@732: mas01mj@732: * Neither the name of Adobe Systems Incorporated nor the names of its mas01mj@732: contributors may be used to endorse or promote products derived from mas01mj@732: this software without specific prior written permission. mas01mj@732: mas01mj@732: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS mas01mj@732: IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, mas01mj@732: THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR mas01mj@732: PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR mas01mj@732: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, mas01mj@732: EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, mas01mj@732: PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR mas01mj@732: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF mas01mj@732: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING mas01mj@732: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS mas01mj@732: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. mas01mj@732: */ mas01mj@732: package com.adobe.fileformats.vcard mas01mj@732: { mas01mj@732: import mx.utils.Base64Decoder; mas01mj@732: import mx.utils.StringUtil; mas01mj@732: mas01mj@732: public class VCardParser mas01mj@732: { mas01mj@732: public static function parse(vcardStr:String):Array mas01mj@732: { mas01mj@732: var vcards:Array = new Array(); mas01mj@732: var lines:Array = vcardStr.split(/\r\n/); mas01mj@732: var vcard:VCard; mas01mj@732: var type:String; mas01mj@732: var typeTmp:String; mas01mj@732: var line:String; mas01mj@732: mas01mj@732: for (var i:uint = 0; i < lines.length; ++i) mas01mj@732: { mas01mj@732: line = lines[i]; mas01mj@732: if (line == "BEGIN:VCARD") mas01mj@732: { mas01mj@732: vcard = new VCard(); mas01mj@732: } mas01mj@732: else if (line == "END:VCARD") mas01mj@732: { mas01mj@732: if (vcard != null) mas01mj@732: { mas01mj@732: vcards.push(vcard); mas01mj@732: } mas01mj@732: } mas01mj@732: else if(line.search(/^ORG/i) != -1) mas01mj@732: { mas01mj@732: var org:String = line.substring(4, line.length); mas01mj@732: var orgArray:Array = org.split(";"); mas01mj@732: for each (var orgToken:String in orgArray) mas01mj@732: { mas01mj@732: if (StringUtil.trim(orgToken).length > 0) mas01mj@732: { mas01mj@732: vcard.orgs.push(orgToken); mas01mj@732: } mas01mj@732: } mas01mj@732: } mas01mj@732: else if(line.search(/^TITLE/i) != -1) mas01mj@732: { mas01mj@732: var title:String = line.substring(6, line.length); mas01mj@732: vcard.title = title; mas01mj@732: } mas01mj@732: else if (line.search(/^FN:/i) != -1) mas01mj@732: { mas01mj@732: var fullName:String = line.substring(3, line.length); mas01mj@732: vcard.fullName = fullName; mas01mj@732: } mas01mj@732: else if (line.search(/^TEL/i) != -1) mas01mj@732: { mas01mj@732: type = new String(); mas01mj@732: typeTmp = new String(); mas01mj@732: var phone:Phone = new Phone(); mas01mj@732: var number:String; mas01mj@732: var phoneTokens:Array = line.split(";"); mas01mj@732: for each (var phoneToken:String in phoneTokens) mas01mj@732: { mas01mj@732: if (phoneToken.search(/^TYPE=/i) != -1) mas01mj@732: { mas01mj@732: if (phoneToken.indexOf(":") != -1) mas01mj@732: { mas01mj@732: typeTmp = phoneToken.substring(5, phoneToken.indexOf(":")); mas01mj@732: number = phoneToken.substring(phoneToken.indexOf(":")+1, phoneToken.length); mas01mj@732: } mas01mj@732: else mas01mj@732: { mas01mj@732: typeTmp = phoneToken.substring(5, phoneToken.length); mas01mj@732: } mas01mj@732: mas01mj@732: typeTmp = typeTmp.toLocaleLowerCase(); mas01mj@732: mas01mj@732: if (typeTmp == "pref") mas01mj@732: { mas01mj@732: continue; mas01mj@732: } mas01mj@732: if (type.length != 0) mas01mj@732: { mas01mj@732: type += (" "); mas01mj@732: } mas01mj@732: type += typeTmp; mas01mj@732: } mas01mj@732: } mas01mj@732: if (type.length > 0 && number != null) mas01mj@732: { mas01mj@732: phone.type = type; mas01mj@732: phone.number = number; mas01mj@732: } mas01mj@732: vcard.phones.push(phone); mas01mj@732: } mas01mj@732: else if (line.search(/^EMAIL/i) != -1) mas01mj@732: { mas01mj@732: type = new String(); mas01mj@732: typeTmp = new String(); mas01mj@732: var email:Email = new Email(); mas01mj@732: var emailAddress:String; mas01mj@732: var emailTokens:Array = line.split(";"); mas01mj@732: for each (var emailToken:String in emailTokens) mas01mj@732: { mas01mj@732: if (emailToken.search(/^TYPE=/i) != -1) mas01mj@732: { mas01mj@732: if (emailToken.indexOf(":") != -1) mas01mj@732: { mas01mj@732: typeTmp = emailToken.substring(5, emailToken.indexOf(":")); mas01mj@732: emailAddress = emailToken.substring(emailToken.indexOf(":")+1, emailToken.length); mas01mj@732: } mas01mj@732: else mas01mj@732: { mas01mj@732: typeTmp = emailToken.substring(5, emailToken.length); mas01mj@732: } mas01mj@732: mas01mj@732: typeTmp = typeTmp.toLocaleLowerCase(); mas01mj@732: mas01mj@732: if (typeTmp == "pref" || typeTmp == "internet") mas01mj@732: { mas01mj@732: continue; mas01mj@732: } mas01mj@732: if (type.length != 0) mas01mj@732: { mas01mj@732: type += (" "); mas01mj@732: } mas01mj@732: type += typeTmp; mas01mj@732: } mas01mj@732: } mas01mj@732: if (type.length > 0 && emailAddress != null) mas01mj@732: { mas01mj@732: email.type = type; mas01mj@732: email.address = emailAddress; mas01mj@732: } mas01mj@732: vcard.emails.push(email); mas01mj@732: } mas01mj@732: else if (line.indexOf("ADR;") != -1) mas01mj@732: { mas01mj@732: var addressTokens:Array = line.split(";"); mas01mj@732: var address:Address = new Address(); mas01mj@732: for (var j:uint = 0; j < addressTokens.length; ++j) mas01mj@732: { mas01mj@732: var addressToken:String = addressTokens[j]; mas01mj@732: if (addressToken.search(/^home:+$/i) != -1) // For Outlook, which uses non-standard vCards. mas01mj@732: { mas01mj@732: address.type = "home"; mas01mj@732: } mas01mj@732: else if (addressToken.search(/^work:+$/i) != -1) // For Outlook, which uses non-standard vCards. mas01mj@732: { mas01mj@732: address.type = "work"; mas01mj@732: } mas01mj@732: if (addressToken.search(/^type=/i) != -1) // The "type" parameter is the standard way (which Address Book uses) mas01mj@732: { mas01mj@732: // First, remove the optional ":" character. mas01mj@732: addressToken = addressToken.replace(/:/,""); mas01mj@732: var addressType:String = addressToken.substring(5, addressToken.length).toLowerCase(); mas01mj@732: if (addressType == "pref") // Not interested in which one is preferred. mas01mj@732: { mas01mj@732: continue; mas01mj@732: } mas01mj@732: else if (addressType.indexOf("home") != -1) // home mas01mj@732: { mas01mj@732: addressType = "home"; mas01mj@732: } mas01mj@732: else if (addressType.indexOf("work") != -1) // work mas01mj@732: { mas01mj@732: addressType = "work"; mas01mj@732: } mas01mj@732: else if (addressType.indexOf(",") != -1) // if the comma technique is used, just use the first one mas01mj@732: { mas01mj@732: var typeTokens:Array = addressType.split(","); mas01mj@732: for each (var typeToken:String in typeTokens) mas01mj@732: { mas01mj@732: if (typeToken != "pref") mas01mj@732: { mas01mj@732: addressType = typeToken; mas01mj@732: break; mas01mj@732: } mas01mj@732: } mas01mj@732: } mas01mj@732: address.type = addressType; mas01mj@732: } mas01mj@732: else if (addressToken.search(/^\d/) != -1 && address.street == null) mas01mj@732: { mas01mj@732: address.street = addressToken.replace(/\\n/, ""); mas01mj@732: address.city = addressTokens[j+1]; mas01mj@732: address.state = addressTokens[j+2]; mas01mj@732: address.postalCode = addressTokens[j+3]; mas01mj@732: } mas01mj@732: } mas01mj@732: if (address.type != null && address.street != null) mas01mj@732: { mas01mj@732: vcard.addresses.push(address); mas01mj@732: } mas01mj@732: mas01mj@732: } mas01mj@732: else if (line.search(/^PHOTO;BASE64/i) != -1) mas01mj@732: { mas01mj@732: var imageStr:String = new String(); mas01mj@732: for (var k:uint = i+1; k < lines.length; ++k) mas01mj@732: { mas01mj@732: imageStr += lines[k]; mas01mj@732: //if (lines[k].search(/.+\=$/) != -1) // Very slow in Mac due to RegEx bug mas01mj@732: if (lines[k].indexOf('=') != -1) mas01mj@732: { mas01mj@732: var decoder:Base64Decoder = new Base64Decoder(); mas01mj@732: decoder.decode(imageStr); mas01mj@732: vcard.image = decoder.flush(); mas01mj@732: break; mas01mj@732: } mas01mj@732: } mas01mj@732: } mas01mj@732: } mas01mj@732: return vcards; mas01mj@732: } mas01mj@732: } mas01mj@732: }