am 5e332efd
: Merge change I903ce7b1 into eclair-mr2
Merge commit '5e332efd56ffc8bcc6c40b214aca66bec21648b7' into eclair-mr2-plus-aosp * commit '5e332efd56ffc8bcc6c40b214aca66bec21648b7': Fix a problem in which Android custom fields are not emitted correctly in non-Ascii languages.
This commit is contained in:
@ -1536,13 +1536,10 @@ public class VCardBuilder {
|
||||
}
|
||||
|
||||
public void appendAndroidSpecificProperty(final String mimeType, ContentValues contentValues) {
|
||||
List<String> rawValueList = new ArrayList<String>();
|
||||
rawValueList.add(mimeType);
|
||||
final List<String> columnNameList;
|
||||
if (!sAllowedAndroidPropertySet.contains(mimeType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> rawValueList = new ArrayList<String>();
|
||||
for (int i = 1; i <= VCardConstants.MAX_DATA_COLUMN; i++) {
|
||||
String value = contentValues.getAsString("data" + i);
|
||||
if (value == null) {
|
||||
@ -1551,8 +1548,38 @@ public class VCardBuilder {
|
||||
rawValueList.add(value);
|
||||
}
|
||||
|
||||
appendLineWithCharsetAndQPDetection(
|
||||
VCardConstants.PROPERTY_X_ANDROID_CUSTOM, rawValueList);
|
||||
boolean needCharset =
|
||||
(mShouldAppendCharsetParam &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
|
||||
boolean reallyUseQuotedPrintable =
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
|
||||
mBuilder.append(VCardConstants.PROPERTY_X_ANDROID_CUSTOM);
|
||||
if (needCharset) {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
mBuilder.append(mVCardCharsetParameter);
|
||||
}
|
||||
if (reallyUseQuotedPrintable) {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
mBuilder.append(VCARD_PARAM_ENCODING_QP);
|
||||
}
|
||||
mBuilder.append(VCARD_DATA_SEPARATOR);
|
||||
mBuilder.append(mimeType); // Should not be encoded.
|
||||
for (String rawValue : rawValueList) {
|
||||
final String encodedValue;
|
||||
if (reallyUseQuotedPrintable) {
|
||||
encodedValue = encodeQuotedPrintable(rawValue);
|
||||
} else {
|
||||
// TODO: one line may be too huge, which may be invalid in vCard 3.0
|
||||
// (which says "When generating a content line, lines longer than
|
||||
// 75 characters SHOULD be folded"), though several
|
||||
// (even well-known) applications do not care this.
|
||||
encodedValue = escapeCharacters(rawValue);
|
||||
}
|
||||
mBuilder.append(VCARD_ITEM_SEPARATOR);
|
||||
mBuilder.append(encodedValue);
|
||||
}
|
||||
mBuilder.append(VCARD_END_OF_LINE);
|
||||
}
|
||||
|
||||
public void appendLineWithCharsetAndQPDetection(final String propertyName,
|
||||
@ -1560,7 +1587,7 @@ public class VCardBuilder {
|
||||
appendLineWithCharsetAndQPDetection(propertyName, null, rawValue);
|
||||
}
|
||||
|
||||
private void appendLineWithCharsetAndQPDetection(
|
||||
public void appendLineWithCharsetAndQPDetection(
|
||||
final String propertyName, final List<String> rawValueList) {
|
||||
appendLineWithCharsetAndQPDetection(propertyName, null, rawValueList);
|
||||
}
|
||||
@ -1578,22 +1605,12 @@ public class VCardBuilder {
|
||||
|
||||
public void appendLineWithCharsetAndQPDetection(final String propertyName,
|
||||
final List<String> parameterList, final List<String> rawValueList) {
|
||||
boolean needCharset = false;
|
||||
boolean reallyUseQuotedPrintable = false;
|
||||
for (String rawValue : rawValueList) {
|
||||
if (!needCharset && mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyPrintableAscii(rawValue)) {
|
||||
needCharset = true;
|
||||
}
|
||||
if (!reallyUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValue)) {
|
||||
reallyUseQuotedPrintable = true;
|
||||
}
|
||||
if (needCharset && reallyUseQuotedPrintable) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean needCharset =
|
||||
(mShouldAppendCharsetParam &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
|
||||
boolean reallyUseQuotedPrintable =
|
||||
(mShouldUseQuotedPrintable &&
|
||||
!VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
|
||||
appendLine(propertyName, parameterList, rawValueList,
|
||||
needCharset, reallyUseQuotedPrintable);
|
||||
}
|
||||
@ -1610,8 +1627,9 @@ public class VCardBuilder {
|
||||
}
|
||||
|
||||
public void appendLine(final String propertyName,
|
||||
final String rawValue, final boolean needCharset, boolean needQuotedPrintable) {
|
||||
appendLine(propertyName, null, rawValue, needCharset, needQuotedPrintable);
|
||||
final String rawValue, final boolean needCharset,
|
||||
boolean reallyUseQuotedPrintable) {
|
||||
appendLine(propertyName, null, rawValue, needCharset, reallyUseQuotedPrintable);
|
||||
}
|
||||
|
||||
public void appendLine(final String propertyName, final List<String> parameterList,
|
||||
@ -1620,7 +1638,8 @@ public class VCardBuilder {
|
||||
}
|
||||
|
||||
public void appendLine(final String propertyName, final List<String> parameterList,
|
||||
final String rawValue, final boolean needCharset, boolean needQuotedPrintable) {
|
||||
final String rawValue, final boolean needCharset,
|
||||
boolean reallyUseQuotedPrintable) {
|
||||
mBuilder.append(propertyName);
|
||||
if (parameterList != null && parameterList.size() > 0) {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
@ -1632,7 +1651,7 @@ public class VCardBuilder {
|
||||
}
|
||||
|
||||
final String encodedValue;
|
||||
if (needQuotedPrintable) {
|
||||
if (reallyUseQuotedPrintable) {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
mBuilder.append(VCARD_PARAM_ENCODING_QP);
|
||||
encodedValue = encodeQuotedPrintable(rawValue);
|
||||
@ -1664,14 +1683,16 @@ public class VCardBuilder {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
mBuilder.append(mVCardCharsetParameter);
|
||||
}
|
||||
if (needQuotedPrintable) {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
mBuilder.append(VCARD_PARAM_ENCODING_QP);
|
||||
}
|
||||
|
||||
mBuilder.append(VCARD_DATA_SEPARATOR);
|
||||
boolean first = true;
|
||||
for (String rawValue : rawValueList) {
|
||||
final String encodedValue;
|
||||
if (needQuotedPrintable) {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
mBuilder.append(VCARD_PARAM_ENCODING_QP);
|
||||
encodedValue = encodeQuotedPrintable(rawValue);
|
||||
} else {
|
||||
// TODO: one line may be too huge, which may be invalid in vCard 3.0
|
||||
|
@ -117,9 +117,6 @@ public class VCardParser_V21 extends VCardParser {
|
||||
this(detector.getEstimatedType());
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Merge detector and parser mode.
|
||||
*/
|
||||
public VCardParser_V21(int parseType) {
|
||||
super(parseType);
|
||||
if (parseType == VCardConfig.PARSE_TYPE_FOMA) {
|
||||
|
@ -349,6 +349,13 @@ public class VCardUtils {
|
||||
}
|
||||
|
||||
public static boolean containsOnlyPrintableAscii(final String...values) {
|
||||
if (values == null) {
|
||||
return true;
|
||||
}
|
||||
return containsOnlyPrintableAscii(Arrays.asList(values));
|
||||
}
|
||||
|
||||
public static boolean containsOnlyPrintableAscii(final Collection<String> values) {
|
||||
if (values == null) {
|
||||
return true;
|
||||
}
|
||||
@ -375,6 +382,13 @@ public class VCardUtils {
|
||||
* See the definition of "7bit" in vCard 2.1 spec for more information.
|
||||
*/
|
||||
public static boolean containsOnlyNonCrLfPrintableAscii(final String...values) {
|
||||
if (values == null) {
|
||||
return true;
|
||||
}
|
||||
return containsOnlyNonCrLfPrintableAscii(Arrays.asList(values));
|
||||
}
|
||||
|
||||
public static boolean containsOnlyNonCrLfPrintableAscii(final Collection<String> values) {
|
||||
if (values == null) {
|
||||
return true;
|
||||
}
|
||||
@ -398,32 +412,6 @@ public class VCardUtils {
|
||||
private static final Set<Character> sUnAcceptableAsciiInV21WordSet =
|
||||
new HashSet<Character>(Arrays.asList('[', ']', '=', ':', '.', ',', ' '));
|
||||
|
||||
/**
|
||||
* <P>
|
||||
* Returns true when the given String is categorized as "word" specified in vCard spec 2.1.
|
||||
* </P>
|
||||
* <P>
|
||||
* vCard 2.1 specifies:<BR />
|
||||
* word = <any printable 7bit us-ascii except []=:., >
|
||||
* </P>
|
||||
*/
|
||||
public static boolean isV21Word(final String value) {
|
||||
if (TextUtils.isEmpty(value)) {
|
||||
return true;
|
||||
}
|
||||
final int asciiFirst = 0x20;
|
||||
final int asciiLast = 0x7E; // included
|
||||
final int length = value.length();
|
||||
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
|
||||
final int c = value.codePointAt(i);
|
||||
if (!(asciiFirst <= c && c <= asciiLast) ||
|
||||
sUnAcceptableAsciiInV21WordSet.contains((char)c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is useful since vCard 3.0 often requires the ("X-") properties and groups
|
||||
* should contain only alphabets, digits, and hyphen.
|
||||
@ -434,6 +422,13 @@ public class VCardUtils {
|
||||
* to the device which is able to parse the malformed input.
|
||||
*/
|
||||
public static boolean containsOnlyAlphaDigitHyphen(final String...values) {
|
||||
if (values == null) {
|
||||
return true;
|
||||
}
|
||||
return containsOnlyAlphaDigitHyphen(Arrays.asList(values));
|
||||
}
|
||||
|
||||
public static boolean containsOnlyAlphaDigitHyphen(final Collection<String> values) {
|
||||
if (values == null) {
|
||||
return true;
|
||||
}
|
||||
@ -461,7 +456,33 @@ public class VCardUtils {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <P>
|
||||
* Returns true when the given String is categorized as "word" specified in vCard spec 2.1.
|
||||
* </P>
|
||||
* <P>
|
||||
* vCard 2.1 specifies:<BR />
|
||||
* word = <any printable 7bit us-ascii except []=:., >
|
||||
* </P>
|
||||
*/
|
||||
public static boolean isV21Word(final String value) {
|
||||
if (TextUtils.isEmpty(value)) {
|
||||
return true;
|
||||
}
|
||||
final int asciiFirst = 0x20;
|
||||
final int asciiLast = 0x7E; // included
|
||||
final int length = value.length();
|
||||
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
|
||||
final int c = value.codePointAt(i);
|
||||
if (!(asciiFirst <= c && c <= asciiLast) ||
|
||||
sUnAcceptableAsciiInV21WordSet.contains((char)c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String toHalfWidthString(final String orgString) {
|
||||
if (TextUtils.isEmpty(orgString)) {
|
||||
return null;
|
||||
|
@ -18,6 +18,7 @@ package com.android.unit_tests.vcard;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.pim.vcard.VCardConfig;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Nickname;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Note;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Phone;
|
||||
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
|
||||
@ -418,4 +419,16 @@ public class VCardJapanizationTests extends VCardTestsBase {
|
||||
.addExpectedNode("ADR", "", new TypeSet("HOME"))
|
||||
.addExpectedNode("NOTE", "note1\nnote2\nnote3", mContentValuesForQP);
|
||||
}
|
||||
|
||||
public void testAndroidCustomV21() {
|
||||
mVerifier.initForExportTest(VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
|
||||
mVerifier.addInputEntry().addContentValues(Nickname.CONTENT_ITEM_TYPE)
|
||||
.put(Nickname.NAME, "\u304D\u3083\u30FC\u30A8\u30C3\u30C1\u30FC");
|
||||
mVerifier.addPropertyNodesVerifierElemWithEmptyName()
|
||||
.addExpectedNode("X-ANDROID-CUSTOM",
|
||||
Arrays.asList(Nickname.CONTENT_ITEM_TYPE,
|
||||
"\u304D\u3083\u30FC\u30A8\u30C3\u30C1\u30FC",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", ""),
|
||||
mContentValuesForQPAndUtf8);
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,13 @@ import android.pim.vcard.VCardUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VCardUtilsTests extends TestCase {
|
||||
public void testContainsOnlyPrintableAscii() {
|
||||
assertTrue(VCardUtils.containsOnlyPrintableAscii((String)null));
|
||||
assertTrue(VCardUtils.containsOnlyPrintableAscii((String[])null));
|
||||
assertTrue(VCardUtils.containsOnlyPrintableAscii((List<String>)null));
|
||||
assertTrue(VCardUtils.containsOnlyPrintableAscii(""));
|
||||
assertTrue(VCardUtils.containsOnlyPrintableAscii("abcdefghijklmnopqrstuvwxyz"));
|
||||
assertTrue(VCardUtils.containsOnlyPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
|
||||
@ -40,6 +43,7 @@ public class VCardUtilsTests extends TestCase {
|
||||
public void testContainsOnlyNonCrLfPrintableAscii() {
|
||||
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii((String)null));
|
||||
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii((String[])null));
|
||||
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii((List<String>)null));
|
||||
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii(""));
|
||||
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("abcdefghijklmnopqrstuvwxyz"));
|
||||
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
|
||||
@ -57,6 +61,7 @@ public class VCardUtilsTests extends TestCase {
|
||||
public void testContainsOnlyAlphaDigitHyphen() {
|
||||
assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen((String)null));
|
||||
assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen((String[])null));
|
||||
assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen((List<String>)null));
|
||||
assertTrue(VCardUtils.containsOnlyAlphaDigitHyphen(""));
|
||||
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("abcdefghijklmnopqrstuvwxyz"));
|
||||
assertTrue(VCardUtils.containsOnlyNonCrLfPrintableAscii("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
|
||||
|
Reference in New Issue
Block a user