diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java index 0732c5153610d..f01659e86edaf 100644 --- a/core/java/android/pim/vcard/ContactStruct.java +++ b/core/java/android/pim/vcard/ContactStruct.java @@ -730,8 +730,8 @@ public class ContactStruct { // which is correct behavior from the view of vCard 2.1. // But we want it to be separated, so do the separation here. final List phoneticNameList = - VCardUtils.constructListFromValue(propValue, - VCardConfig.isV30(mVCardType)); + VCardUtils.constructListFromValue(propValue, + VCardConfig.isV30(mVCardType)); handlePhoneticNameFromSound(phoneticNameList); } else { // Ignore this field since Android cannot understand what it is. diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java index b8f4cfd7c1e69..9d72c5fcfa0fd 100644 --- a/core/java/android/pim/vcard/VCardComposer.java +++ b/core/java/android/pim/vcard/VCardComposer.java @@ -53,6 +53,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -144,6 +145,7 @@ public class VCardComposer { private static final String VCARD_PARAM_ENCODING_BASE64_V30 = "ENCODING=b"; private static final String SHIFT_JIS = "SHIFT_JIS"; + private static final String UTF_8 = "UTF-8"; /** * Special URI for testing. @@ -359,12 +361,9 @@ public class VCardComposer { mIsV30 = VCardConfig.isV30(vcardType); mUsesQuotedPrintable = VCardConfig.usesQuotedPrintable(vcardType); mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); - mIsJapaneseMobilePhone = VCardConfig - .needsToConvertPhoneticString(vcardType); - mOnlyOneNoteFieldIsAvailable = VCardConfig - .onlyOneNoteFieldIsAvailable(vcardType); - mUsesAndroidProperty = VCardConfig - .usesAndroidSpecificProperty(vcardType); + mIsJapaneseMobilePhone = VCardConfig.needsToConvertPhoneticString(vcardType); + mOnlyOneNoteFieldIsAvailable = VCardConfig.onlyOneNoteFieldIsAvailable(vcardType); + mUsesAndroidProperty = VCardConfig.usesAndroidSpecificProperty(vcardType); mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType); mUsesUtf8 = VCardConfig.usesUtf8(vcardType); mUsesShiftJis = VCardConfig.usesShiftJis(vcardType); @@ -374,17 +373,31 @@ public class VCardComposer { mHandlerList = new ArrayList(); if (mIsDoCoMo) { - mCharsetString = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); + String charset; + try { + charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); + } catch (UnsupportedCharsetException e) { + Log.e(LOG_TAG, "DoCoMo-specific SHIFT_JIS was not found. Use SHIFT_JIS as is."); + charset = SHIFT_JIS; + } + mCharsetString = charset; // Do not use mCharsetString bellow since it is different from "SHIFT_JIS" but // may be "DOCOMO_SHIFT_JIS" or something like that (internal expression used in // Android, not shown to the public). mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS; } else if (mUsesShiftJis) { - mCharsetString = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); + String charset; + try { + charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); + } catch (UnsupportedCharsetException e) { + Log.e(LOG_TAG, "Vendor-specific SHIFT_JIS was not found. Use SHIFT_JIS as is."); + charset = SHIFT_JIS; + } + mCharsetString = charset; mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS; } else { - mCharsetString = "UTF-8"; - mVCardCharsetParameter = "CHARSET=UTF-8"; + mCharsetString = UTF_8; + mVCardCharsetParameter = "CHARSET=" + UTF_8; } } @@ -702,34 +715,46 @@ public class VCardComposer { } } - final String familyName = primaryContentValues - .getAsString(StructuredName.FAMILY_NAME); - final String middleName = primaryContentValues - .getAsString(StructuredName.MIDDLE_NAME); - final String givenName = primaryContentValues - .getAsString(StructuredName.GIVEN_NAME); - final String prefix = primaryContentValues - .getAsString(StructuredName.PREFIX); - final String suffix = primaryContentValues - .getAsString(StructuredName.SUFFIX); - final String displayName = primaryContentValues - .getAsString(StructuredName.DISPLAY_NAME); + final String familyName = primaryContentValues.getAsString(StructuredName.FAMILY_NAME); + final String middleName = primaryContentValues.getAsString(StructuredName.MIDDLE_NAME); + final String givenName = primaryContentValues.getAsString(StructuredName.GIVEN_NAME); + final String prefix = primaryContentValues.getAsString(StructuredName.PREFIX); + final String suffix = primaryContentValues.getAsString(StructuredName.SUFFIX); + final String displayName = primaryContentValues.getAsString(StructuredName.DISPLAY_NAME); if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) { + final boolean shouldAppendCharsetParameterToName = + !(mIsV30 && UTF_8.equalsIgnoreCase(mCharsetString)) && + shouldAppendCharsetParameters(Arrays.asList( + familyName, givenName, middleName, prefix, suffix)); + final boolean reallyUseQuotedPrintableToName = + (!mRefrainsQPToPrimaryProperties && + !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) && + VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) && + VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) && + VCardUtils.containsOnlyNonCrLfPrintableAscii(prefix) && + VCardUtils.containsOnlyNonCrLfPrintableAscii(suffix))); + + final String formattedName; + if (!TextUtils.isEmpty(displayName)) { + formattedName = displayName; + } else { + formattedName = VCardUtils.constructNameFromElements( + VCardConfig.getNameOrderType(mVCardType), + familyName, middleName, givenName, prefix, suffix); + } + final boolean shouldAppendCharsetParameterToFN = + !(mIsV30 && UTF_8.equalsIgnoreCase(mCharsetString)) && + shouldAppendCharsetParameter(formattedName); + final boolean reallyUseQuotedPrintableToFN = + !mRefrainsQPToPrimaryProperties && + !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedName); + final String encodedFamily; final String encodedGiven; final String encodedMiddle; final String encodedPrefix; final String encodedSuffix; - - final boolean reallyUseQuotedPrintableToName = - (!mRefrainsQPToPrimaryProperties && - !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) && - VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) && - VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) && - VCardUtils.containsOnlyNonCrLfPrintableAscii(prefix) && - VCardUtils.containsOnlyNonCrLfPrintableAscii(suffix))); - if (reallyUseQuotedPrintableToName) { encodedFamily = encodeQuotedPrintable(familyName); encodedGiven = encodeQuotedPrintable(givenName); @@ -744,59 +769,61 @@ public class VCardComposer { encodedSuffix = escapeCharacters(suffix); } + final String encodedFormattedname = + (reallyUseQuotedPrintableToFN ? + encodeQuotedPrintable(formattedName) : escapeCharacters(formattedName)); + builder.append(Constants.PROPERTY_N); - if (shouldAppendCharsetParameters(Arrays.asList( - encodedFamily, encodedGiven, encodedMiddle, encodedPrefix, encodedSuffix))) { - builder.append(VCARD_PARAM_SEPARATOR); - builder.append(mVCardCharsetParameter); - } - if (reallyUseQuotedPrintableToName) { - builder.append(VCARD_PARAM_SEPARATOR); - builder.append(VCARD_PARAM_ENCODING_QP); - } - - builder.append(VCARD_DATA_SEPARATOR); - builder.append(encodedFamily); - builder.append(VCARD_ITEM_SEPARATOR); - builder.append(encodedGiven); - builder.append(VCARD_ITEM_SEPARATOR); - builder.append(encodedMiddle); - builder.append(VCARD_ITEM_SEPARATOR); - builder.append(encodedPrefix); - builder.append(VCARD_ITEM_SEPARATOR); - builder.append(encodedSuffix); - builder.append(VCARD_END_OF_LINE); - - final String formattedName; - if (!TextUtils.isEmpty(displayName)) { - formattedName = displayName; + if (mIsDoCoMo) { + if (shouldAppendCharsetParameterToName) { + builder.append(VCARD_PARAM_SEPARATOR); + builder.append(mVCardCharsetParameter); + } + if (reallyUseQuotedPrintableToName) { + builder.append(VCARD_PARAM_SEPARATOR); + builder.append(VCARD_PARAM_ENCODING_QP); + } + builder.append(VCARD_DATA_SEPARATOR); + // DoCoMo phones require that all the elements in the "family name" field. + builder.append(formattedName); + builder.append(VCARD_ITEM_SEPARATOR); + builder.append(VCARD_ITEM_SEPARATOR); + builder.append(VCARD_ITEM_SEPARATOR); + builder.append(VCARD_ITEM_SEPARATOR); } else { - formattedName = VCardUtils.constructNameFromElements( - VCardConfig.getNameOrderType(mVCardType), - encodedFamily, encodedMiddle, encodedGiven, encodedPrefix, encodedSuffix); + if (shouldAppendCharsetParameterToName) { + builder.append(VCARD_PARAM_SEPARATOR); + builder.append(mVCardCharsetParameter); + } + if (reallyUseQuotedPrintableToName) { + builder.append(VCARD_PARAM_SEPARATOR); + builder.append(VCARD_PARAM_ENCODING_QP); + } + builder.append(VCARD_DATA_SEPARATOR); + builder.append(encodedFamily); + builder.append(VCARD_ITEM_SEPARATOR); + builder.append(encodedGiven); + builder.append(VCARD_ITEM_SEPARATOR); + builder.append(encodedMiddle); + builder.append(VCARD_ITEM_SEPARATOR); + builder.append(encodedPrefix); + builder.append(VCARD_ITEM_SEPARATOR); + builder.append(encodedSuffix); } - - final boolean reallyUseQuotedPrintableToFullname = - !mRefrainsQPToPrimaryProperties && - !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedName); - - final String encodedFullname = - reallyUseQuotedPrintableToFullname ? - encodeQuotedPrintable(formattedName) : - escapeCharacters(formattedName); + builder.append(VCARD_END_OF_LINE); // FN property builder.append(Constants.PROPERTY_FN); - if (shouldAppendCharsetParameter(encodedFullname)) { + if (shouldAppendCharsetParameterToFN) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } - if (reallyUseQuotedPrintableToFullname) { + if (reallyUseQuotedPrintableToFN) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(VCARD_PARAM_ENCODING_QP); } builder.append(VCARD_DATA_SEPARATOR); - builder.append(encodedFullname); + builder.append(encodedFormattedname); builder.append(VCARD_END_OF_LINE); } else if (!TextUtils.isEmpty(displayName)) { final boolean reallyUseQuotedPrintableToDisplayName = @@ -808,7 +835,7 @@ public class VCardComposer { escapeCharacters(displayName); builder.append(Constants.PROPERTY_N); - if (shouldAppendCharsetParameter(encodedDisplayName)) { + if (shouldAppendCharsetParameter(displayName)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } @@ -826,7 +853,7 @@ public class VCardComposer { if (mIsV30) { builder.append(Constants.PROPERTY_FN); // TODO: Not allowed formally... - if (shouldAppendCharsetParameter(encodedDisplayName)) { + if (shouldAppendCharsetParameter(displayName)) { builder.append(VCARD_PARAM_SEPARATOR); builder.append(mVCardCharsetParameter); } diff --git a/core/java/android/pim/vcard/VCardUtils.java b/core/java/android/pim/vcard/VCardUtils.java index 8da23a42ab65e..05e67302bd61b 100644 --- a/core/java/android/pim/vcard/VCardUtils.java +++ b/core/java/android/pim/vcard/VCardUtils.java @@ -362,7 +362,7 @@ public class VCardUtils { if (TextUtils.isEmpty(str)) { return true; } - + final int length = str.length(); final int asciiFirst = 0x20; final int asciiLast = 0x126; diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java index 933ff2afc795c..917b18e8a7862 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java @@ -124,23 +124,19 @@ class PropertyNodesVerifierElem { return addNodeWithOrder(propName, propValue, null, null, null, null, null); } + public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue, + ContentValues contentValues) { + return addNodeWithOrder(propName, propValue, null, null, contentValues, null, null); + } + public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue, List propValueList) { return addNodeWithOrder(propName, propValue, propValueList, null, null, null, null); } public PropertyNodesVerifierElem addNodeWithOrder(String propName, List propValueList) { - StringBuffer buffer = new StringBuffer(); - boolean first = true; - for (String propValueElem : propValueList) { - if (first) { - first = false; - } else { - buffer.append(';'); - } - buffer.append(propValueElem); - } - return addNodeWithOrder(propName, buffer.toString(), propValueList, + final String propValue = concatinateListWithSemiColon(propValueList); + return addNodeWithOrder(propName, propValue.toString(), propValueList, null, null, null, null); } @@ -149,6 +145,13 @@ class PropertyNodesVerifierElem { return addNodeWithOrder(propName, propValue, null, null, null, paramMap_TYPE, null); } + public PropertyNodesVerifierElem addNodeWithOrder(String propName, + List propValueList, TypeSet paramMap_TYPE) { + final String propValue = concatinateListWithSemiColon(propValueList); + return addNodeWithOrder(propName, propValue, propValueList, null, null, + paramMap_TYPE, null); + } + public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue, List propValueList, TypeSet paramMap_TYPE) { return addNodeWithOrder(propName, propValue, propValueList, null, null, @@ -176,23 +179,19 @@ class PropertyNodesVerifierElem { return addNodeWithoutOrder(propName, propValue, null, null, null, null, null); } + public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue, + ContentValues contentValues) { + return addNodeWithoutOrder(propName, propValue, null, null, contentValues, null, null); + } + public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue, List propValueList) { return addNodeWithoutOrder(propName, propValue, propValueList, null, null, null, null); } public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, List propValueList) { - StringBuffer buffer = new StringBuffer(); - boolean first = true; - for (String propValueElem : propValueList) { - if (first) { - first = false; - } else { - buffer.append(';'); - } - buffer.append(propValueElem); - } - return addNodeWithoutOrder(propName, buffer.toString(), propValueList, + final String propValue = concatinateListWithSemiColon(propValueList); + return addNodeWithoutOrder(propName, propValue, propValueList, null, null, null, null); } @@ -201,6 +200,13 @@ class PropertyNodesVerifierElem { return addNodeWithoutOrder(propName, propValue, null, null, null, paramMap_TYPE, null); } + public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, + List propValueList, TypeSet paramMap_TYPE) { + final String propValue = concatinateListWithSemiColon(propValueList); + return addNodeWithoutOrder(propName, propValue, propValueList, null, null, + paramMap_TYPE, null); + } + public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue, List propValueList, TypeSet paramMap_TYPE) { return addNodeWithoutOrder(propName, propValue, propValueList, null, null, @@ -291,6 +297,21 @@ class PropertyNodesVerifierElem { } } + private String concatinateListWithSemiColon(List array) { + StringBuffer buffer = new StringBuffer(); + boolean first = true; + for (String propValueElem : array) { + if (first) { + first = false; + } else { + buffer.append(';'); + } + buffer.append(propValueElem); + } + + return buffer.toString(); + } + private boolean tryFoundExpectedNodeFromUnorderedList(PropertyNode actualNode, List expectedButDifferentValueList) { final String propName = actualNode.propName; diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java index f447c771ca47e..169ea71b4362c 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java @@ -16,7 +16,6 @@ package com.android.unit_tests.vcard; -import android.content.ContentValues; import android.pim.vcard.VCardConfig; import android.pim.vcard.exception.VCardException; import android.provider.ContactsContract.Data; @@ -569,10 +568,6 @@ public class VCardImporterTests extends VCardTestsBase { * Tests all the properties in a complicated vCard are correctly parsed by the VCardParser. */ public void testV21ComplicatedCase_Parsing() throws IOException, VCardException { - ContentValues contentValuesForQP = new ContentValues(); - contentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE"); - ContentValues contentValuesForPhoto = new ContentValues(); - contentValuesForPhoto.put("ENCODING", "BASE64"); PropertyNodesVerifier verifier = new PropertyNodesVerifier(this); verifier.addPropertyNodesVerifierElem() .addNodeWithOrder("VERSION", "2.1") @@ -596,7 +591,7 @@ public class VCardImporterTests extends VCardTestsBase { null, null, new TypeSet("WORK"), null) .addNodeWithOrder("LABEL", "100 Waters Edge\r\nBaytown, LA 30314\r\nUnited States of America", - null, null, contentValuesForQP, new TypeSet("WORK"), null) + null, null, mContentValuesForQP, new TypeSet("WORK"), null) .addNodeWithOrder("ADR", ";;42 Plantation St.;Baytown;LA;30314;United States of America", Arrays.asList("", "", "42 Plantation St.", "Baytown", @@ -604,7 +599,7 @@ public class VCardImporterTests extends VCardTestsBase { new TypeSet("HOME"), null) .addNodeWithOrder("LABEL", "42 Plantation St.\r\nBaytown, LA 30314\r\nUnited States of America", - null, null, contentValuesForQP, + null, null, mContentValuesForQP, new TypeSet("HOME"), null) .addNodeWithOrder("EMAIL", "forrestgump@walladalla.com", new TypeSet("PREF", "INTERNET")) @@ -612,9 +607,9 @@ public class VCardImporterTests extends VCardTestsBase { .addNodeWithOrder("NOTE", "The following note is the example from RFC 2045.") .addNodeWithOrder("NOTE", "Now's the time for all folk to come to the aid of their country.", - null, null, contentValuesForQP, null, null) + null, null, mContentValuesForQP, null, null) .addNodeWithOrder("PHOTO", null, - null, sPhotoByteArrayForComplicatedCase, contentValuesForPhoto, + null, sPhotoByteArrayForComplicatedCase, mContentValuesForBase64V21, new TypeSet("JPEG"), null) .addNodeWithOrder("X-ATTRIBUTE", "Some String") .addNodeWithOrder("BDAY", "19800101") @@ -762,17 +757,15 @@ public class VCardImporterTests extends VCardTestsBase { // Though Japanese careers append ";;;;" at the end of the value of "SOUND", // vCard 2.1/3.0 specification does not allow multiple values. // Do not need to handle it as multiple values. - ContentValues contentValuesForShiftJis = new ContentValues(); - contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS"); PropertyNodesVerifier verifier = new PropertyNodesVerifier(this); verifier.addPropertyNodesVerifierElem() .addNodeWithOrder("VERSION", "2.1", null, null, null, null, null) .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9;;;;", Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9", "", "", "", ""), - null, contentValuesForShiftJis, null, null) + null, mContentValuesForSJis, null, null) .addNodeWithOrder("SOUND", "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E;;;;", - null, null, contentValuesForShiftJis, + null, null, mContentValuesForSJis, new TypeSet("X-IRMC-N"), null) .addNodeWithOrder("TEL", "0300000000", null, null, null, new TypeSet("VOICE", "PREF"), null); @@ -829,23 +822,18 @@ public class VCardImporterTests extends VCardTestsBase { } public void testV21Japanese2_Parsing() throws IOException, VCardException { - ContentValues contentValuesForShiftJis = new ContentValues(); - contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS"); - ContentValues contentValuesForQPAndSJ = new ContentValues(); - contentValuesForQPAndSJ.put("ENCODING", "QUOTED-PRINTABLE"); - contentValuesForQPAndSJ.put("CHARSET", "SHIFT_JIS"); PropertyNodesVerifier verifier = new PropertyNodesVerifier(this); verifier.addPropertyNodesVerifierElem() .addNodeWithOrder("VERSION", "2.1") .addNodeWithOrder("N", "\u5B89\u85E4;\u30ED\u30A4\u30C9\u0031;;;", Arrays.asList("\u5B89\u85E4", "\u30ED\u30A4\u30C9\u0031", "", "", ""), - null, contentValuesForShiftJis, null, null) + null, mContentValuesForSJis, null, null) .addNodeWithOrder("FN", "\u5B89\u85E4\u0020\u30ED\u30A4\u30C9\u0020\u0031", - null, null, contentValuesForShiftJis, null, null) + null, null, mContentValuesForSJis, null, null) .addNodeWithOrder("SOUND", "\uFF71\uFF9D\uFF84\uFF9E\uFF73;\uFF9B\uFF72\uFF84\uFF9E\u0031;;;", - null, null, contentValuesForShiftJis, + null, null, mContentValuesForSJis, new TypeSet("X-IRMC-N"), null) .addNodeWithOrder("ADR", ";\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" + @@ -857,9 +845,9 @@ public class VCardImporterTests extends VCardTestsBase { "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" + "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" + "\u0036\u968E", "", "", "", "150-8512", ""), - null, contentValuesForQPAndSJ, new TypeSet("HOME"), null) + null, mContentValuesForQPAndSJis, new TypeSet("HOME"), null) .addNodeWithOrder("NOTE", "\u30E1\u30E2", null, null, - contentValuesForQPAndSJ, null, null); + mContentValuesForQPAndSJis, null, null); verifier.verify(R.raw.v21_japanese_2, VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS); } @@ -895,17 +883,15 @@ public class VCardImporterTests extends VCardTestsBase { } public void testV21MultipleEntryCase_Parse() throws IOException, VCardException { - ContentValues contentValuesForShiftJis = new ContentValues(); - contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS"); PropertyNodesVerifier verifier = new PropertyNodesVerifier(this); verifier.addPropertyNodesVerifierElem() .addNodeWithOrder("VERSION", "2.1") .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033;;;;", Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0033", "", "", "", ""), - null, contentValuesForShiftJis, null, null) + null, mContentValuesForSJis, null, null) .addNodeWithOrder("SOUND", "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0033;;;;", - null, null, contentValuesForShiftJis, + null, null, mContentValuesForSJis, new TypeSet("X-IRMC-N"), null) .addNodeWithOrder("TEL", "9", new TypeSet("X-NEC-SECRET")) .addNodeWithOrder("TEL", "10", new TypeSet("X-NEC-HOTEL")) @@ -916,10 +902,10 @@ public class VCardImporterTests extends VCardTestsBase { .addNodeWithOrder("VERSION", "2.1") .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034;;;;", Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0034", "", "", "", ""), - null, contentValuesForShiftJis, null, null) + null, mContentValuesForSJis, null, null) .addNodeWithOrder("SOUND", "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0034;;;;", - null, null, contentValuesForShiftJis, + null, null, mContentValuesForSJis, new TypeSet("X-IRMC-N"), null) .addNodeWithOrder("TEL", "13", new TypeSet("MODEM")) .addNodeWithOrder("TEL", "14", new TypeSet("PAGER")) @@ -930,10 +916,10 @@ public class VCardImporterTests extends VCardTestsBase { .addNodeWithOrder("VERSION", "2.1") .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035;;;;", Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0035", "", "", "", ""), - null, contentValuesForShiftJis, null, null) + null, mContentValuesForSJis, null, null) .addNodeWithOrder("SOUND", "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0035;;;;", - null, null, contentValuesForShiftJis, + null, null, mContentValuesForSJis, new TypeSet("X-IRMC-N"), null) .addNodeWithOrder("TEL", "17", new TypeSet("X-NEC-BOY")) .addNodeWithOrder("TEL", "18", new TypeSet("X-NEC-FRIEND")) diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java new file mode 100644 index 0000000000000..4b65008f1bb23 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.vcard; + +import android.content.ContentValues; +import android.pim.vcard.VCardConfig; +import android.provider.ContactsContract.CommonDataKinds.StructuredName; + +import com.android.unit_tests.vcard.PropertyNodesVerifierElem.TypeSet; + +import java.util.Arrays; + +public class VCardJapanizationTests extends VCardTestsBase { + private void testNameUtf8Common(int vcardType) { + ExportTestResolver resolver = new ExportTestResolver(); + resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE) + .put(StructuredName.FAMILY_NAME, "\u3075\u308B\u3069") + .put(StructuredName.GIVEN_NAME, "\u3091\u308A\u304B") + .put(StructuredName.MIDDLE_NAME, "B") + .put(StructuredName.PREFIX, "Dr.") + .put(StructuredName.SUFFIX, "Ph.D"); + + VCardVerifier verifier = new VCardVerifier(resolver, vcardType); + ContentValues contentValues = + (VCardConfig.isV30(vcardType) ? null : mContentValuesForQPAndUtf8); + verifier.addPropertyNodesVerifierElem() + .addNodeWithoutOrder("FN", "Dr. \u3075\u308B\u3069 B \u3091\u308A\u304B Ph.D", + contentValues) + .addNodeWithoutOrder("N", "\u3075\u308B\u3069;\u3091\u308A\u304B;B;Dr.;Ph.D", + Arrays.asList( + "\u3075\u308B\u3069", "\u3091\u308A\u304B", "B", "Dr.", "Ph.D"), + null, contentValues, null, null); + verifier.verify(); + } + + public void testNameUtf8V21() { + testNameUtf8Common(VCardConfig.VCARD_TYPE_V21_JAPANESE_UTF8); + } + + public void testNameUtf8V30() { + testNameUtf8Common(VCardConfig.VCARD_TYPE_V30_JAPANESE_UTF8); + } + + public void testNameShiftJis() { + ExportTestResolver resolver = new ExportTestResolver(); + resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE) + .put(StructuredName.FAMILY_NAME, "\u3075\u308B\u3069") + .put(StructuredName.GIVEN_NAME, "\u3091\u308A\u304B") + .put(StructuredName.MIDDLE_NAME, "B") + .put(StructuredName.PREFIX, "Dr.") + .put(StructuredName.SUFFIX, "Ph.D"); + + VCardVerifier verifier = new VCardVerifier(resolver, + VCardConfig.VCARD_TYPE_V30_JAPANESE_SJIS); + verifier.addPropertyNodesVerifierElem() + .addNodeWithoutOrder("FN", "Dr. \u3075\u308B\u3069 B \u3091\u308A\u304B Ph.D", + mContentValuesForSJis) + .addNodeWithoutOrder("N", "\u3075\u308B\u3069;\u3091\u308A\u304B;B;Dr.;Ph.D", + Arrays.asList( + "\u3075\u308B\u3069", "\u3091\u308A\u304B", "B", "Dr.", "Ph.D"), + null, mContentValuesForSJis, null, null); + verifier.verify(); + } + + /** + * DoCoMo phones require all name elements should be in "family name" field. + */ + public void testNameDoCoMo() { + ExportTestResolver resolver = new ExportTestResolver(); + resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE) + .put(StructuredName.FAMILY_NAME, "\u3075\u308B\u3069") + .put(StructuredName.GIVEN_NAME, "\u3091\u308A\u304B") + .put(StructuredName.MIDDLE_NAME, "B") + .put(StructuredName.PREFIX, "Dr.") + .put(StructuredName.SUFFIX, "Ph.D"); + + VCardVerifier verifier = new VCardVerifier(resolver, + VCardConfig.VCARD_TYPE_DOCOMO); + final String fullName = "Dr. \u3075\u308B\u3069 B \u3091\u308A\u304B Ph.D"; + verifier.addPropertyNodesVerifierElem() + .addNodeWithoutOrder("N", fullName + ";;;;", + Arrays.asList(fullName, "", "", "", ""), + null, mContentValuesForSJis, null, null) + .addNodeWithoutOrder("FN", fullName, mContentValuesForSJis) + .addNodeWithoutOrder("SOUND", ";;;;", new TypeSet("X-IRMC-N")) + .addNodeWithoutOrder("TEL", "", new TypeSet("HOME")) + .addNodeWithoutOrder("EMAIL", "", new TypeSet("HOME")) + .addNodeWithoutOrder("ADR", "", new TypeSet("HOME")) + .addNodeWithoutOrder("X-CLASS", "PUBLIC") + .addNodeWithoutOrder("X-REDUCTION", "") + .addNodeWithoutOrder("X-NO", "") + .addNodeWithoutOrder("X-DCM-HMN-MODE", ""); + verifier.verify(); + } +} \ No newline at end of file diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java index 9ec6e05051ef3..bd4d13af69104 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java +++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java @@ -66,7 +66,6 @@ import android.test.mock.MockContentResolver; import android.test.mock.MockContext; import android.test.mock.MockCursor; import android.text.TextUtils; -import android.util.Log; import junit.framework.TestCase; @@ -185,6 +184,35 @@ class CustomMockContext extends MockContext { public static final int V21 = VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8; public static final int V30 = VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8; + // Do not modify these during tests. + protected final ContentValues mContentValuesForQP; + protected final ContentValues mContentValuesForSJis; + protected final ContentValues mContentValuesForUtf8; + protected final ContentValues mContentValuesForQPAndSJis; + protected final ContentValues mContentValuesForQPAndUtf8; + protected final ContentValues mContentValuesForBase64V21; + protected final ContentValues mContentValuesForBase64V30; + + public VCardTestsBase() { + super(); + mContentValuesForQP = new ContentValues(); + mContentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE"); + mContentValuesForSJis = new ContentValues(); + mContentValuesForSJis.put("CHARSET", "SHIFT_JIS"); + mContentValuesForUtf8 = new ContentValues(); + mContentValuesForUtf8.put("CHARSET", "UTF-8"); + mContentValuesForQPAndSJis = new ContentValues(); + mContentValuesForQPAndSJis.put("ENCODING", "QUOTED-PRINTABLE"); + mContentValuesForQPAndSJis.put("CHARSET", "SHIFT_JIS"); + mContentValuesForQPAndUtf8 = new ContentValues(); + mContentValuesForQPAndUtf8.put("ENCODING", "QUOTED-PRINTABLE"); + mContentValuesForQPAndUtf8.put("CHARSET", "UTF-8"); + mContentValuesForBase64V21 = new ContentValues(); + mContentValuesForBase64V21.put("ENCODING", "BASE64"); + mContentValuesForBase64V30 = new ContentValues(); + mContentValuesForBase64V30.put("ENCODING", "b"); + } + public class ImportTestResolver extends MockContentResolver { ImportTestProvider mProvider = new ImportTestProvider(); @Override @@ -834,7 +862,9 @@ class CustomMockContext extends MockContext { InputStream is = null; try { - is = new ByteArrayInputStream(vcard.getBytes("UTF-8")); + String charset = + (VCardConfig.usesShiftJis(mVCardType) ? "SHIFT_JIS" : "UTF-8"); + is = new ByteArrayInputStream(vcard.getBytes(charset)); testCase.assertEquals(true, parser.parse(is, null, builder)); } catch (IOException e) { testCase.fail("Unexpected IOException: " + e.getMessage());