Make vCard importer/exporter aware of multi-byte parameters.
Bug: 2922186 Change-Id: Ic877940242d87ef918bf8d4dac601d37b296259b
This commit is contained in:
@@ -1463,6 +1463,9 @@ public class VCardBuilder {
|
||||
parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
|
||||
} else if (VCardUtils.isMobilePhoneLabel(label)) {
|
||||
parameterList.add(VCardConstants.PARAM_TYPE_CELL);
|
||||
} else if (mIsV30) {
|
||||
// This label is appropriately encoded in appendTypeParameters.
|
||||
parameterList.add(label);
|
||||
} else {
|
||||
final String upperLabel = label.toUpperCase();
|
||||
if (VCardUtils.isValidInV21ButUnknownToContactsPhoteType(upperLabel)) {
|
||||
@@ -1741,21 +1744,30 @@ public class VCardBuilder {
|
||||
// which would be recommended way in vcard 3.0 though not valid in vCard 2.1.
|
||||
boolean first = true;
|
||||
for (final String typeValue : types) {
|
||||
// Note: vCard 3.0 specifies the different type of acceptable type Strings, but
|
||||
// we don't emit that kind of vCard 3.0 specific type since there should be
|
||||
// high probabilyty in which external importers cannot understand them.
|
||||
//
|
||||
// e.g. TYPE="\u578B\u306B\u3087" (vCard 3.0 allows non-Ascii characters if they
|
||||
// are quoted.)
|
||||
if (!VCardUtils.isV21Word(typeValue)) {
|
||||
continue;
|
||||
if (VCardConfig.isV30(mVCardType)) {
|
||||
// Note: vCard 3.0 specifies the different type of acceptable type Strings, but
|
||||
// we don't emit that kind of vCard 3.0 specific type since there should be
|
||||
// high probabilyty in which external importers cannot understand them.
|
||||
//
|
||||
// e.g. TYPE="\u578B\u306B\u3087" (vCard 3.0 allows non-Ascii characters if they
|
||||
// are quoted.)
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
}
|
||||
appendTypeParameter(VCardUtils.toStringAvailableAsV30ParameValue(typeValue));
|
||||
} else { // vCard 2.1
|
||||
if (!VCardUtils.isV21Word(typeValue)) {
|
||||
continue;
|
||||
}
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
}
|
||||
appendTypeParameter(typeValue);
|
||||
}
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
mBuilder.append(VCARD_PARAM_SEPARATOR);
|
||||
}
|
||||
appendTypeParameter(typeValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,11 +157,15 @@ public class VCardEntryConstructor implements VCardInterpreter {
|
||||
mParamType = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyParamValue(String value) {
|
||||
if (mParamType == null) {
|
||||
// From vCard 2.1 specification. vCard 3.0 formally does not allow this case.
|
||||
mParamType = "TYPE";
|
||||
}
|
||||
if (!VCardUtils.containsOnlyAlphaDigitHyphen(value)) {
|
||||
value = encodeString(value, mCharsetForDecodedBytes);
|
||||
}
|
||||
mCurrentProperty.addParameter(mParamType, value);
|
||||
mParamType = null;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
package android.pim.vcard;
|
||||
|
||||
import android.content.ContentProviderOperation;
|
||||
import android.provider.ContactsContract.Data;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Im;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Phone;
|
||||
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
|
||||
import android.provider.ContactsContract.Data;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
import android.text.TextUtils;
|
||||
|
||||
@@ -477,6 +477,43 @@ public class VCardUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <P>
|
||||
* Returns String available as parameter value in vCard 3.0.
|
||||
* </P>
|
||||
* <P>
|
||||
* RFC 2426 requires vCard composer to quote parameter values when it contains
|
||||
* semi-colon, for example (See RFC 2426 for more information).
|
||||
* This method checks whether the given String can be used without quotes.
|
||||
* </P>
|
||||
* <P>
|
||||
* Note: We remove DQUOTE silently for now.
|
||||
* </P>
|
||||
*/
|
||||
public static String toStringAvailableAsV30ParameValue(String value) {
|
||||
if (TextUtils.isEmpty(value)) {
|
||||
value = "";
|
||||
}
|
||||
final int asciiFirst = 0x20;
|
||||
final int asciiLast = 0x7E; // included
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final int length = value.length();
|
||||
boolean needQuote = false;
|
||||
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
|
||||
final int codePoint = value.codePointAt(i);
|
||||
if (codePoint < asciiFirst || codePoint == '"') {
|
||||
// CTL characters and DQUOTE are never accepted. Remove them.
|
||||
continue;
|
||||
}
|
||||
builder.appendCodePoint(codePoint);
|
||||
if (codePoint == ':' || codePoint == ',' || codePoint == ' ') {
|
||||
needQuote = true;
|
||||
}
|
||||
}
|
||||
final String result = builder.toString();
|
||||
return ((needQuote || result.isEmpty()) ? ('"' + result + '"') : result);
|
||||
}
|
||||
|
||||
public static String toHalfWidthString(final String orgString) {
|
||||
if (TextUtils.isEmpty(orgString)) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user