Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e332efd authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change I903ce7b1 into eclair-mr2

* changes:
  Fix a problem in which Android custom fields are not emitted correctly in non-Ascii languages.
parents 50b69062 a750fdd7
Loading
Loading
Loading
Loading
+50 −29
Original line number Diff line number Diff line
@@ -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
+0 −3
Original line number Diff line number Diff line
@@ -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) {
+48 −27
Original line number Diff line number Diff line
@@ -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 = &lt;any printable 7bit us-ascii except []=:., &gt;
     * </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;
        }
@@ -462,6 +457,32 @@ 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 = &lt;any printable 7bit us-ascii except []=:., &gt;
     * </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;
+13 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -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"));