diff options
author | Daisuke Miyakawa <dmiyakawa@google.com> | 2009-09-30 09:46:59 -0700 |
---|---|---|
committer | Daisuke Miyakawa <dmiyakawa@google.com> | 2009-09-30 10:52:27 -0700 |
commit | 30a2e36754fb2d26f699dfcd66064dfcb57cce50 (patch) | |
tree | c99980b699e7abdd86a6246dbb4196c63673ffc5 /core/java/android/pim/vcard | |
parent | a3431e4c7d6307b845d7008955d99425d842ff72 (diff) | |
download | frameworks_base-30a2e36754fb2d26f699dfcd66064dfcb57cce50.zip frameworks_base-30a2e36754fb2d26f699dfcd66064dfcb57cce50.tar.gz frameworks_base-30a2e36754fb2d26f699dfcd66064dfcb57cce50.tar.bz2 |
Fix vCard composer in three points.
- Make it allow composer users to emit Quoted-Printabled primary ("N", "FN", etc.) properties.
- Make it strictly check whether it is necessary for the composer to emit CHARSET infomation.
-- Added the logic "not vCard 3.0, or, CHARSET is not UTF-8".
- Clean up the code (again...)
Diffstat (limited to 'core/java/android/pim/vcard')
-rw-r--r-- | core/java/android/pim/vcard/VCardComposer.java | 278 | ||||
-rw-r--r-- | core/java/android/pim/vcard/VCardConfig.java | 46 |
2 files changed, 249 insertions, 75 deletions
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java index b0376c4..c943d85 100644 --- a/core/java/android/pim/vcard/VCardComposer.java +++ b/core/java/android/pim/vcard/VCardComposer.java @@ -284,7 +284,9 @@ public class VCardComposer { private final boolean mUsesQuotedPrintable; private final boolean mUsesAndroidProperty; private final boolean mUsesDefactProperty; + private final boolean mUsesUtf8; private final boolean mUsesShiftJis; + private final boolean mUsesQPToPrimaryProperties; private Cursor mCursor; private int mIdColumn; @@ -366,7 +368,9 @@ public class VCardComposer { mUsesAndroidProperty = VCardConfig .usesAndroidSpecificProperty(vcardType); mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType); + mUsesUtf8 = VCardConfig.usesUtf8(vcardType); mUsesShiftJis = VCardConfig.usesShiftJis(vcardType); + mUsesQPToPrimaryProperties = VCardConfig.usesQPToPrimaryProperties(vcardType); if (mIsDoCoMo) { mCharsetString = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); @@ -400,6 +404,7 @@ public class VCardComposer { if (!(VCardUtils.containsOnlyPrintableAscii(phoneName))) { needCharset = true; } + // TODO: QP should be used? Using mUsesQPToPrimaryProperties should help. appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, phoneName, needCharset, false); appendVCardLine(builder, VCARD_PROPERTY_NAME, phoneName, needCharset, false); @@ -598,6 +603,7 @@ public class VCardComposer { name = mCursor.getString(NUMBER_COLUMN_INDEX); } final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name)); + // TODO: QP should be used? Using mUsesQPToPrimaryProperties should help. appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, name, needCharset, false); appendVCardLine(builder, VCARD_PROPERTY_NAME, name, needCharset, false); @@ -634,8 +640,8 @@ public class VCardComposer { ContentValues contentValues = namedContentValues.values; String key = contentValues.getAsString(Data.MIMETYPE); if (key != null) { - List<ContentValues> contentValuesList = contentValuesListMap - .get(key); + List<ContentValues> contentValuesList = + contentValuesListMap.get(key); if (contentValuesList == null) { contentValuesList = new ArrayList<ContentValues>(); contentValuesListMap.put(key, contentValuesList); @@ -788,26 +794,46 @@ public class VCardComposer { final String displayName = primaryContentValues .getAsString(StructuredName.DISPLAY_NAME); - // For now, some primary element is not encoded into Quoted-Printable, which is not - // valid in vCard spec strictly. In the future, we may have to have some flag to - // enable composer to encode these primary field into Quoted-Printable. if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) { - final String encodedFamily = escapeCharacters(familyName); - final String encodedGiven = escapeCharacters(givenName); - final String encodedMiddle = escapeCharacters(middleName); - final String encodedPrefix = escapeCharacters(prefix); - final String encodedSuffix = escapeCharacters(suffix); + final String encodedFamily; + final String encodedGiven; + final String encodedMiddle; + final String encodedPrefix; + final String encodedSuffix; + + final boolean reallyUseQuotedPrintableToName = + (mUsesQPToPrimaryProperties && + !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) && + VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) && + VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) && + VCardUtils.containsOnlyNonCrLfPrintableAscii(prefix) && + VCardUtils.containsOnlyNonCrLfPrintableAscii(suffix))); + + if (reallyUseQuotedPrintableToName) { + encodedFamily = encodeQuotedPrintable(familyName); + encodedGiven = encodeQuotedPrintable(givenName); + encodedMiddle = encodeQuotedPrintable(middleName); + encodedPrefix = encodeQuotedPrintable(prefix); + encodedSuffix = encodeQuotedPrintable(suffix); + } else { + encodedFamily = escapeCharacters(familyName); + encodedGiven = escapeCharacters(givenName); + encodedMiddle = escapeCharacters(middleName); + encodedPrefix = escapeCharacters(prefix); + encodedSuffix = escapeCharacters(suffix); + } // N property. This order is specified by vCard spec and does not depend on countries. builder.append(VCARD_PROPERTY_NAME); - if (!(VCardUtils.containsOnlyPrintableAscii(familyName) && - VCardUtils.containsOnlyPrintableAscii(givenName) && - VCardUtils.containsOnlyPrintableAscii(middleName) && - VCardUtils.containsOnlyPrintableAscii(prefix) && - VCardUtils.containsOnlyPrintableAscii(suffix))) { + if (shouldAppendCharsetAttribute(Arrays.asList( + familyName, givenName, middleName, prefix, suffix))) { builder.append(VCARD_ATTR_SEPARATOR); builder.append(mVCardAttributeCharset); } + if (reallyUseQuotedPrintableToName) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(VCARD_ATTR_ENCODING_QP); + } builder.append(VCARD_DATA_SEPARATOR); builder.append(encodedFamily); @@ -821,25 +847,51 @@ public class VCardComposer { builder.append(encodedSuffix); builder.append(VCARD_COL_SEPARATOR); - final String encodedFullname = VCardUtils.constructNameFromElements( + final String fullname = VCardUtils.constructNameFromElements( VCardConfig.getNameOrderType(mVCardType), encodedFamily, encodedMiddle, encodedGiven, encodedPrefix, encodedSuffix); + final boolean reallyUseQuotedPrintableToFullname = + mUsesQPToPrimaryProperties && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(fullname); + + final String encodedFullname = + reallyUseQuotedPrintableToFullname ? + encodeQuotedPrintable(fullname) : + escapeCharacters(fullname); // FN property builder.append(VCARD_PROPERTY_FULL_NAME); - if (!VCardUtils.containsOnlyPrintableAscii(encodedFullname)) { + if (shouldAppendCharsetAttribute(encodedFullname)) { builder.append(VCARD_ATTR_SEPARATOR); builder.append(mVCardAttributeCharset); } + if (reallyUseQuotedPrintableToFullname) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(VCARD_ATTR_ENCODING_QP); + } builder.append(VCARD_DATA_SEPARATOR); builder.append(encodedFullname); builder.append(VCARD_COL_SEPARATOR); } else if (!TextUtils.isEmpty(displayName)) { + final boolean reallyUseQuotedPrintableToDisplayName = + (mUsesQPToPrimaryProperties && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(displayName)); + final String encodedDisplayName = + reallyUseQuotedPrintableToDisplayName ? + encodeQuotedPrintable(displayName) : + escapeCharacters(displayName); + builder.append(VCARD_PROPERTY_NAME); - builder.append(VCARD_ATTR_SEPARATOR); - builder.append(mVCardAttributeCharset); + if (shouldAppendCharsetAttribute(encodedDisplayName)) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(mVCardAttributeCharset); + } + if (reallyUseQuotedPrintableToDisplayName) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(VCARD_ATTR_ENCODING_QP); + } builder.append(VCARD_DATA_SEPARATOR); - builder.append(escapeCharacters(displayName)); + builder.append(encodedDisplayName); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR); @@ -873,54 +925,65 @@ public class VCardComposer { if (mIsV30) { final String sortString = VCardUtils .constructNameFromElements(mVCardType, - phoneticFamilyName, phoneticMiddleName, + phoneticFamilyName, + phoneticMiddleName, phoneticGivenName); builder.append(VCARD_PROPERTY_SORT_STRING); - if (!VCardUtils.containsOnlyPrintableAscii(sortString)) { - // Strictly, adding charset information is NOT valid in - // VCard 3.0, - // but we'll add this info since parser side may be able to - // use the charset via - // this attribute field. - // - // e.g. Japanese mobile phones use Shift_Jis while RFC 2426 - // recommends - // UTF-8. By adding this field, parsers may be able to know - // this text - // is NOT UTF-8 but Shift_Jis. + // Do not need to care about QP, since vCard 3.0 does not allow it. + final String encodedSortString = escapeCharacters(sortString); + if (shouldAppendCharsetAttribute(encodedSortString)) { builder.append(VCARD_ATTR_SEPARATOR); builder.append(mVCardAttributeCharset); } - builder.append(VCARD_DATA_SEPARATOR); - builder.append(sortString); + builder.append(encodedSortString); builder.append(VCARD_COL_SEPARATOR); } else { // Note: There is no appropriate property for expressing - // phonetic name in - // VCard 2.1, while there is in VCard 3.0 (SORT-STRING). - // We chose to use DoCoMo's way since it is supported by a - // lot of Japanese mobile phones. - // - // TODO: should use Quoted-Pritable? + // phonetic name in vCard 2.1, while there is in + // vCard 3.0 (SORT-STRING). + // We chose to use DoCoMo's way since it is supported by + // a lot of Japanese mobile phones. This is "X-" property, so + // any parser hopefully would not get confused with this. builder.append(VCARD_PROPERTY_SOUND); builder.append(VCARD_ATTR_SEPARATOR); builder.append(Constants.ATTR_TYPE_X_IRMC_N); - builder.append(VCARD_ATTR_SEPARATOR); - if (!(VCardUtils.containsOnlyPrintableAscii(phoneticFamilyName) && - VCardUtils.containsOnlyPrintableAscii(phoneticMiddleName) && - VCardUtils.containsOnlyPrintableAscii(phoneticGivenName))) { - builder.append(mVCardAttributeCharset); - builder.append(VCARD_DATA_SEPARATOR); + boolean reallyUseQuotedPrintable = + (mUsesQPToPrimaryProperties && + !(VCardUtils.containsOnlyNonCrLfPrintableAscii( + phoneticFamilyName) && + VCardUtils.containsOnlyNonCrLfPrintableAscii( + phoneticMiddleName) && + VCardUtils.containsOnlyNonCrLfPrintableAscii( + phoneticGivenName))); + + final String encodedPhoneticFamilyName; + final String encodedPhoneticMiddleName; + final String encodedPhoneticGivenName; + if (reallyUseQuotedPrintable) { + encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); + encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); + encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); + } else { + encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); + encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); + encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); } - builder.append(escapeCharacters(phoneticFamilyName)); + if (shouldAppendCharsetAttribute(Arrays.asList( + encodedPhoneticFamilyName, encodedPhoneticMiddleName, + encodedPhoneticGivenName))) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(mVCardAttributeCharset); + } + builder.append(VCARD_DATA_SEPARATOR); + builder.append(encodedPhoneticFamilyName); builder.append(VCARD_ITEM_SEPARATOR); - builder.append(escapeCharacters(phoneticMiddleName)); + builder.append(encodedPhoneticGivenName); builder.append(VCARD_ITEM_SEPARATOR); - builder.append(escapeCharacters(phoneticGivenName)); + builder.append(encodedPhoneticMiddleName); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_ITEM_SEPARATOR); builder.append(VCARD_COL_SEPARATOR); @@ -939,21 +1002,72 @@ public class VCardComposer { if (mUsesDefactProperty) { if (!TextUtils.isEmpty(phoneticGivenName)) { + final boolean reallyUseQuotedPrintable = + (mUsesQPToPrimaryProperties && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName)); + final String encodedPhoneticGivenName; + if (reallyUseQuotedPrintable) { + encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName); + } else { + encodedPhoneticGivenName = escapeCharacters(phoneticGivenName); + } builder.append(VCARD_PROPERTY_X_PHONETIC_FIRST_NAME); + if (shouldAppendCharsetAttribute(encodedPhoneticGivenName)) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(mVCardAttributeCharset); + } + if (reallyUseQuotedPrintable) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(VCARD_ATTR_ENCODING_QP); + } builder.append(VCARD_DATA_SEPARATOR); - builder.append(phoneticGivenName); + builder.append(encodedPhoneticGivenName); builder.append(VCARD_COL_SEPARATOR); } if (!TextUtils.isEmpty(phoneticMiddleName)) { + final boolean reallyUseQuotedPrintable = + (mUsesQPToPrimaryProperties && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName)); + final String encodedPhoneticMiddleName; + if (reallyUseQuotedPrintable) { + encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName); + } else { + encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName); + } builder.append(VCARD_PROPERTY_X_PHONETIC_MIDDLE_NAME); + if (shouldAppendCharsetAttribute(encodedPhoneticMiddleName)) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(mVCardAttributeCharset); + } + if (reallyUseQuotedPrintable) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(VCARD_ATTR_ENCODING_QP); + } builder.append(VCARD_DATA_SEPARATOR); - builder.append(phoneticMiddleName); + builder.append(encodedPhoneticMiddleName); builder.append(VCARD_COL_SEPARATOR); } if (!TextUtils.isEmpty(phoneticFamilyName)) { + final boolean reallyUseQuotedPrintable = + (mUsesQPToPrimaryProperties && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName)); + final String encodedPhoneticFamilyName; + if (reallyUseQuotedPrintable) { + encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName); + } else { + encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName); + } builder.append(VCARD_PROPERTY_X_PHONETIC_LAST_NAME); + if (shouldAppendCharsetAttribute(encodedPhoneticFamilyName)) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(mVCardAttributeCharset); + } + if (reallyUseQuotedPrintable) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(VCARD_ATTR_ENCODING_QP); + } builder.append(VCARD_DATA_SEPARATOR); - builder.append(phoneticFamilyName); + builder.append(encodedPhoneticFamilyName); builder.append(VCARD_COL_SEPARATOR); } } @@ -975,21 +1089,32 @@ public class VCardComposer { } for (ContentValues contentValues : contentValuesList) { - final String nickname = contentValues - .getAsString(Nickname.NAME); + final String nickname = contentValues.getAsString(Nickname.NAME); if (TextUtils.isEmpty(nickname)) { continue; } - builder.append(propertyNickname); - if (!VCardUtils.containsOnlyPrintableAscii(propertyNickname)) { - // Strictly, this is not valid in vCard 3.0. See above. + final String encodedNickname; + final boolean reallyUseQuotedPrintable = + (mUsesQuotedPrintable && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(nickname)); + if (reallyUseQuotedPrintable) { + encodedNickname = encodeQuotedPrintable(nickname); + } else { + encodedNickname = escapeCharacters(nickname); + } + + builder.append(propertyNickname); + if (shouldAppendCharsetAttribute(propertyNickname)) { builder.append(VCARD_ATTR_SEPARATOR); builder.append(mVCardAttributeCharset); } - + if (reallyUseQuotedPrintable) { + builder.append(VCARD_ATTR_SEPARATOR); + builder.append(VCARD_ATTR_ENCODING_QP); + } builder.append(VCARD_DATA_SEPARATOR); - builder.append(escapeCharacters(nickname)); + builder.append(encodedNickname); builder.append(VCARD_COL_SEPARATOR); } } @@ -1048,7 +1173,6 @@ public class VCardComposer { continue; } emailAddressExists = true; - // Do not allow completely same email address line emitted into each file. if (!addressSet.contains(emailAddress)) { addressSet.add(emailAddress); appendVCardEmailLine(builder, type, label, emailAddress); @@ -1065,7 +1189,6 @@ public class VCardComposer { final Map<String, List<ContentValues>> contentValuesListMap) { final List<ContentValues> contentValuesList = contentValuesListMap .get(StructuredPostal.CONTENT_ITEM_TYPE); - if (contentValuesList != null) { if (mIsDoCoMo) { appendPostalsForDoCoMo(builder, contentValuesList); @@ -1082,7 +1205,7 @@ public class VCardComposer { } /** - * Try to append just one line. If there's no appropriate address + * Tries to append just one line. If there's no appropriate address * information, append an empty line. */ private void appendPostalsForDoCoMo(final StringBuilder builder, @@ -1751,6 +1874,35 @@ public class VCardComposer { builder.append(type); } + /** + * Returns true when the property line should contain charset attribute + * information. This method may return true even when vCard version is 3.0. + * + * Strictly, adding charset information is invalid in VCard 3.0. + * However we'll add the info only when used charset is not UTF-8 + * in vCard 3.0 format, since parser side may be able to use the charset + * via this field, though we may encounter another problem by adding it... + * + * e.g. Japanese mobile phones use Shift_Jis while RFC 2426 + * recommends UTF-8. By adding this field, parsers may be able + * to know this text is NOT UTF-8 but Shift_Jis. + */ + private boolean shouldAppendCharsetAttribute(final String propertyValue) { + return (!VCardUtils.containsOnlyPrintableAscii(propertyValue) && + (!mIsV30 || !mUsesUtf8)); + } + + private boolean shouldAppendCharsetAttribute(final List<String> propertyValueList) { + boolean shouldAppendBasically = false; + for (String propertyValue : propertyValueList) { + if (!VCardUtils.containsOnlyPrintableAscii(propertyValue)) { + shouldAppendBasically = true; + break; + } + } + return shouldAppendBasically && (!mIsV30 || !mUsesUtf8); + } + private String encodeQuotedPrintable(String str) { if (TextUtils.isEmpty(str)) { return ""; diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java index bc19551..68cd0df 100644 --- a/core/java/android/pim/vcard/VCardConfig.java +++ b/core/java/android/pim/vcard/VCardConfig.java @@ -55,7 +55,7 @@ public class VCardConfig { private static final int FLAG_CHARSET_UTF8 = 0; private static final int FLAG_CHARSET_SHIFT_JIS = 0x20; - + /** * The flag indicating the vCard composer will add some "X-" properties used only in Android * when the formal vCard specification does not have appropriate fields for that data. @@ -85,7 +85,7 @@ public class VCardConfig { * in vCard 3.0). Some external parsers may get confused with non-valid, non-"X-" properties. */ private static final int FLAG_USE_DEFACT_PROPERTY = 0x40000000; - + /** * The flag indicating some specific dialect seen in vcard of DoCoMo (one of Japanese * mobile careers) should be used. This flag does not include any other information like @@ -94,10 +94,20 @@ public class VCardConfig { */ private static final int FLAG_DOCOMO = 0x20000000; + /** + * The flag indicating the vCard composer use Quoted-Printable toward even "primary" types. + * In this context, "primary" types means "N", "FN", etc. which are usually "not" encoded + * into Quoted-Printable format in external exporters. + * This flag is useful when some target importer does not accept "primary" property values + * without Quoted-Printable encoding. + * + * @hide Temporaly made public. We don't strictly define "primary", so we may change the + * behavior around this flag in the future. Do not use this flag without any reason. + */ + public static final int FLAG_USE_QP_TO_PRIMARY_PROPERTIES = 0x10000000; // VCard types - /** * General vCard format with the version 2.1. Uses UTF-8 for the charset. * When composing a vCard entry, the US convension will be used. @@ -114,10 +124,10 @@ public class VCardConfig { /** * General vCard format with the version 3.0. Uses UTF-8 for the charset. * - * Note that this type is not fully implemented, so probably some bugs remain especially - * in parsing part. - * - * TODO: implement this type. + * Note that this type is not fully implemented, so probably some bugs remain both in + * parsing and composing. + * + * TODO: implement this type correctly. */ public static final int VCARD_TYPE_V30_GENERIC = (FLAG_V30 | NAME_ORDER_DEFAULT | FLAG_CHARSET_UTF8 | @@ -243,6 +253,10 @@ public class VCardConfig { (vcardType == VCARD_TYPE_DOCOMO)); } + public static boolean usesUtf8(int vcardType) { + return ((vcardType & FLAG_CHARSET_UTF8) != 0); + } + public static boolean usesShiftJis(int vcardType) { return ((vcardType & FLAG_CHARSET_SHIFT_JIS) != 0); } @@ -257,7 +271,7 @@ public class VCardConfig { public static boolean needsToConvertPhoneticString(int vcardType) { return (vcardType == VCARD_TYPE_DOCOMO); } - + public static int getNameOrderType(int vcardType) { return vcardType & NAME_ORDER_MASK; } @@ -265,19 +279,27 @@ public class VCardConfig { public static boolean usesAndroidSpecificProperty(int vcardType) { return ((vcardType & FLAG_USE_ANDROID_PROPERTY) != 0); } - + public static boolean usesDefactProperty(int vcardType) { return ((vcardType & FLAG_USE_DEFACT_PROPERTY) != 0); } - + public static boolean onlyOneNoteFieldIsAvailable(int vcardType) { return vcardType == VCARD_TYPE_DOCOMO; } - + public static boolean showPerformanceLog() { return (VCardConfig.LOG_LEVEL & VCardConfig.LOG_LEVEL_PERFORMANCE_MEASUREMENT) != 0; } - + + /** + * @hide + */ + public static boolean usesQPToPrimaryProperties(int vcardType) { + return (usesQuotedPrintable(vcardType) && + ((vcardType & FLAG_USE_QP_TO_PRIMARY_PROPERTIES) != 0)); + } + private VCardConfig() { } }
\ No newline at end of file |