161 lines
6.9 KiB
Java
161 lines
6.9 KiB
Java
package org.thoughtcrime.securesms.contactshare;
|
|
|
|
import android.provider.ContactsContract;
|
|
import android.text.TextUtils;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
|
|
import org.thoughtcrime.securesms.logging.Log;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
|
|
import ezvcard.Ezvcard;
|
|
import ezvcard.VCard;
|
|
|
|
public final class VCardUtil {
|
|
|
|
private VCardUtil(){}
|
|
|
|
private static final String TAG = VCardUtil.class.getSimpleName();
|
|
|
|
public static List<Contact> parseContacts(@NonNull String vCardData) {
|
|
List<VCard> vContacts = Ezvcard.parse(vCardData).all();
|
|
List<Contact> contacts = new LinkedList<>();
|
|
for (VCard vCard: vContacts){
|
|
contacts.add(getContactFromVcard(vCard));
|
|
}
|
|
return contacts;
|
|
}
|
|
|
|
static @Nullable Contact getContactFromVcard(@NonNull VCard vcard) {
|
|
ezvcard.property.StructuredName vName = vcard.getStructuredName();
|
|
List<ezvcard.property.Telephone> vPhones = vcard.getTelephoneNumbers();
|
|
List<ezvcard.property.Email> vEmails = vcard.getEmails();
|
|
List<ezvcard.property.Address> vPostalAddresses = vcard.getAddresses();
|
|
|
|
String organization = vcard.getOrganization() != null && !vcard.getOrganization().getValues().isEmpty() ? vcard.getOrganization().getValues().get(0) : null;
|
|
String displayName = vcard.getFormattedName() != null ? vcard.getFormattedName().getValue() : null;
|
|
|
|
if (displayName == null && vName != null) {
|
|
displayName = vName.getGiven();
|
|
}
|
|
|
|
if (displayName == null && vcard.getOrganization() != null) {
|
|
displayName = organization;
|
|
}
|
|
|
|
if (displayName == null) {
|
|
Log.w(TAG, "Failed to parse the vcard: No valid name.");
|
|
return null;
|
|
}
|
|
|
|
Contact.Name name = new Contact.Name(displayName,
|
|
vName != null ? vName.getGiven() : null,
|
|
vName != null ? vName.getFamily() : null,
|
|
vName != null && !vName.getPrefixes().isEmpty() ? vName.getPrefixes().get(0) : null,
|
|
vName != null && !vName.getSuffixes().isEmpty() ? vName.getSuffixes().get(0) : null,
|
|
null);
|
|
|
|
|
|
List<Contact.Phone> phoneNumbers = new ArrayList<>(vPhones.size());
|
|
for (ezvcard.property.Telephone vEmail : vPhones) {
|
|
String label = !vEmail.getTypes().isEmpty() ? getCleanedVcardType(vEmail.getTypes().get(0).getValue()) : null;
|
|
|
|
// Phone number is stored in the uri field in v4.0 only. In other versions, it is in the text field.
|
|
String phoneNumberFromText = vEmail.getText();
|
|
String extractedPhoneNumber = phoneNumberFromText == null ? vEmail.getUri().getNumber() : phoneNumberFromText;
|
|
phoneNumbers.add(new Contact.Phone(extractedPhoneNumber, phoneTypeFromVcardType(label), label));
|
|
}
|
|
|
|
List<Contact.Email> emails = new ArrayList<>(vEmails.size());
|
|
for (ezvcard.property.Email vEmail : vEmails) {
|
|
String label = !vEmail.getTypes().isEmpty() ? getCleanedVcardType(vEmail.getTypes().get(0).getValue()) : null;
|
|
emails.add(new Contact.Email(vEmail.getValue(), emailTypeFromVcardType(label), label));
|
|
}
|
|
|
|
List<Contact.PostalAddress> postalAddresses = new ArrayList<>(vPostalAddresses.size());
|
|
for (ezvcard.property.Address vPostalAddress : vPostalAddresses) {
|
|
String label = !vPostalAddress.getTypes().isEmpty() ? getCleanedVcardType(vPostalAddress.getTypes().get(0).getValue()) : null;
|
|
postalAddresses.add(new Contact.PostalAddress(postalAddressTypeFromVcardType(label),
|
|
label,
|
|
vPostalAddress.getStreetAddress(),
|
|
vPostalAddress.getPoBox(),
|
|
null,
|
|
vPostalAddress.getLocality(),
|
|
vPostalAddress.getRegion(),
|
|
vPostalAddress.getPostalCode(),
|
|
vPostalAddress.getCountry()));
|
|
}
|
|
|
|
return new Contact(name, organization, phoneNumbers, emails, postalAddresses, null);
|
|
}
|
|
|
|
static Contact.Phone.Type phoneTypeFromContactType(int type) {
|
|
switch (type) {
|
|
case ContactsContract.CommonDataKinds.Phone.TYPE_HOME:
|
|
return Contact.Phone.Type.HOME;
|
|
case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE:
|
|
return Contact.Phone.Type.MOBILE;
|
|
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK:
|
|
return Contact.Phone.Type.WORK;
|
|
}
|
|
return Contact.Phone.Type.CUSTOM;
|
|
}
|
|
|
|
private static Contact.Phone.Type phoneTypeFromVcardType(@Nullable String type) {
|
|
if ("home".equalsIgnoreCase(type)) return Contact.Phone.Type.HOME;
|
|
else if ("cell".equalsIgnoreCase(type)) return Contact.Phone.Type.MOBILE;
|
|
else if ("work".equalsIgnoreCase(type)) return Contact.Phone.Type.WORK;
|
|
else return Contact.Phone.Type.CUSTOM;
|
|
}
|
|
|
|
static Contact.Email.Type emailTypeFromContactType(int type) {
|
|
switch (type) {
|
|
case ContactsContract.CommonDataKinds.Email.TYPE_HOME:
|
|
return Contact.Email.Type.HOME;
|
|
case ContactsContract.CommonDataKinds.Email.TYPE_MOBILE:
|
|
return Contact.Email.Type.MOBILE;
|
|
case ContactsContract.CommonDataKinds.Email.TYPE_WORK:
|
|
return Contact.Email.Type.WORK;
|
|
}
|
|
return Contact.Email.Type.CUSTOM;
|
|
}
|
|
|
|
private static Contact.Email.Type emailTypeFromVcardType(@Nullable String type) {
|
|
if ("home".equalsIgnoreCase(type)) return Contact.Email.Type.HOME;
|
|
else if ("cell".equalsIgnoreCase(type)) return Contact.Email.Type.MOBILE;
|
|
else if ("work".equalsIgnoreCase(type)) return Contact.Email.Type.WORK;
|
|
else return Contact.Email.Type.CUSTOM;
|
|
}
|
|
|
|
static Contact.PostalAddress.Type postalAddressTypeFromContactType(int type) {
|
|
switch (type) {
|
|
case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME:
|
|
return Contact.PostalAddress.Type.HOME;
|
|
case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK:
|
|
return Contact.PostalAddress.Type.WORK;
|
|
}
|
|
return Contact.PostalAddress.Type.CUSTOM;
|
|
}
|
|
|
|
private static Contact.PostalAddress.Type postalAddressTypeFromVcardType(@Nullable String type) {
|
|
if ("home".equalsIgnoreCase(type)) return Contact.PostalAddress.Type.HOME;
|
|
else if ("work".equalsIgnoreCase(type)) return Contact.PostalAddress.Type.WORK;
|
|
else return Contact.PostalAddress.Type.CUSTOM;
|
|
}
|
|
|
|
private static String getCleanedVcardType(@Nullable String type) {
|
|
if (TextUtils.isEmpty(type)) return "";
|
|
|
|
if (type.startsWith("x-") && type.length() > 2) {
|
|
return type.substring(2);
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
}
|