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

Commit 931a0a94 authored by Daisuke Miyakawa's avatar Daisuke Miyakawa
Browse files

Refactor vCard so that it correctly choose charset while importing

some files.

Change-Id: I27600e260cd7ca42a25481d5ff61f262c9328d61
parent e6b205bb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -376,7 +376,7 @@ public class VCardComposer {
                mCharset = charset;
            }
        }
        Log.d(LOG_TAG, "use the charset \"" + mCharset + "\""); 
        Log.d(LOG_TAG, "Use the charset \"" + mCharset + "\"");
    }

    /**
+94 −83
Original line number Diff line number Diff line
@@ -39,12 +39,12 @@ public class VCardConfig {
    /* package */ static final int LOG_LEVEL = LOG_LEVEL_NONE;

    /**
     * <P>
     * <p>
     * The charset used during import.
     * </P>
     * <P>
     * We cannot determine which charset should be used to interpret a given vCard file,
     * while we have to decode sime encoded data (e.g. BASE64) to binary.
     * </p>
     * <p>
     * We cannot determine which charset should be used to interpret a given vCard file
     * at first, while we have to decode sime encoded data (e.g. BASE64) to binary.
     * In order to avoid "misinterpretation" of charset as much as possible,
     * "ISO-8859-1" (a.k.a Latin-1) is first used for reading a stream.
     * When charset is specified in a property (with "CHARSET=..." parameter),
@@ -52,12 +52,15 @@ public class VCardConfig {
     * assuming "ISO-8859-1" is able to map "all" 8bit characters to some unicode,
     * and it has 1 to 1 mapping in all 8bit characters.
     * If the assumption is not correct, this setting will cause some bug.
     * </P>
     * </p>
     */
    /* package */ static final String DEFAULT_TEMPORARY_CHARSET = "ISO-8859-1";
    /* package */ static final String DEFAULT_INTERMEDIATE_CHARSET = "ISO-8859-1";

    // TODO: still intermediate procedures uses this charset. Fix it.
    public static final String DEFAULT_IMPORT_CHARSET = "ISO-8859-1";
    /**
     * The charset used when there's no information affbout what charset should be used to
     * encode the binary given from vCard.
     */
    public static final String DEFAULT_IMPORT_CHARSET = "UTF-8";
    public static final String DEFAULT_EXPORT_CHARSET = "UTF-8";

    public static final int FLAG_V21 = 0;
@@ -82,130 +85,138 @@ public class VCardConfig {
    private static final int FLAG_CHARSET_MASK_FOR_EKPORT = 0xF00;

    /**
     * <p>
     * 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.
     * 
     * </p>
     * <p>
     * For example, Android accepts nickname information while vCard 2.1 does not.
     * When this flag is on, vCard composer emits alternative "X-" property (like "X-NICKNAME")
     * instead of just dropping it.
     * 
     * </p>
     * <p>
     * vCard parser code automatically parses the field emitted even when this flag is off.
     * 
     * Note that this flag does not assure all the information must be hold in the emitted vCard.
     * </p>
     */
    private static final int FLAG_USE_ANDROID_PROPERTY = 0x80000000;
    
    /**
     * <p>
     * The flag indicating the vCard composer will add some "X-" properties seen in the
     * vCard data emitted by the other softwares/devices when the formal vCard specification
     * does not have appropriate field(s) for that data.
     * 
     * </p> 
     * <p>
     * One example is X-PHONETIC-FIRST-NAME/X-PHONETIC-MIDDLE-NAME/X-PHONETIC-LAST-NAME, which are
     * for phonetic name (how the name is pronounced), seen in the vCard emitted by some other
     * non-Android devices/softwares. We chose to enable the vCard composer to use those
     * defact properties since they are also useful for Android devices.
     * 
     * </p>
     * <p>
     * Note for developers: only "X-" properties should be added with this flag. vCard 2.1/3.0
     * allows any kind of "X-" properties but does not allow non-"X-" properties (except IANA tokens
     * in vCard 3.0). Some external parsers may get confused with non-valid, non-"X-" properties.
     * </p>
     */
    private static final int FLAG_USE_DEFACT_PROPERTY = 0x40000000;

    /**
     * <p>
     * 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
     * that "the vCard is for Japanese". So it is "possible" that "the vCard should have DoCoMo's
     * dialect but the name order should be European", but it is not recommended.
     * </p>
     */
    private static final int FLAG_DOCOMO = 0x20000000;

    /**
     * <P>
     * <p>
     * The flag indicating the vCard composer does "NOT" use Quoted-Printable toward "primary"
     * properties even though it is required by vCard 2.1 (QP is prohibited in vCard 3.0).
     * </P>
     * <P>
     * </p>
     * <p>
     * We actually cannot define what is the "primary" property. Note that this is NOT defined
     * in vCard specification either. Also be aware that it is NOT related to "primary" notion
     * used in {@link android.provider.ContactsContract}.
     * This notion is just for vCard composition in Android.
     * </P>
     * <P>
     * </p>
     * <p>
     * We added this Android-specific notion since some (incomplete) vCard exporters for vCard 2.1
     * do NOT use Quoted-Printable encoding toward some properties related names like "N", "FN", etc.
     * even when their values contain non-ascii or/and CR/LF, while they use the encoding in the
     * other properties like "ADR", "ORG", etc.
     * <P>
     * <p>
     * We are afraid of the case where some vCard importer also forget handling QP presuming QP is
     * not used in such fields.
     * </P>
     * <P>
     * </p>
     * <p>
     * This flag is useful when some target importer you are going to focus on does not accept
     * such properties with Quoted-Printable encoding.
     * </P>
     * <P>
     * </p>
     * <p>
     * Again, we should not use this flag at all for complying vCard 2.1 spec.
     * </P>
     * <P>
     * </p>
     * <p>
     * In vCard 3.0, Quoted-Printable is explicitly "prohibitted", so we don't need to care this
     * kind of problem (hopefully).
     * </P>
     * </p>
     */
    public static final int FLAG_REFRAIN_QP_TO_NAME_PROPERTIES = 0x10000000;

    /**
     * <P>
     * <p>
     * The flag indicating that phonetic name related fields must be converted to
     * appropriate form. Note that "appropriate" is not defined in any vCard specification.
     * This is Android-specific.
     * </P>
     * <P>
     * </p>
     * <p>
     * One typical (and currently sole) example where we need this flag is the time when
     * we need to emit Japanese phonetic names into vCard entries. The property values
     * should be encoded into half-width katakana when the target importer is Japanese mobile
     * phones', which are probably not able to parse full-width hiragana/katakana for
     * historical reasons, while the vCard importers embedded to softwares for PC should be
     * able to parse them as we expect.
     * </P>
     * </p>
     */
    public static final int FLAG_CONVERT_PHONETIC_NAME_STRINGS = 0x0800000;

    /**
     * <P>
     * <p>
     * The flag indicating the vCard composer "for 2.1" emits "TYPE=" string toward TYPE params
     * every time possible. The default behavior does not emit it and is valid in the spec.
     * In vCrad 3.0, this flag is unnecessary, since "TYPE=" is MUST in vCard 3.0 specification.
     * </P>
     * <P>
     * </p>
     * <p>
     * Detail:
     * How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0.
     * </p>
     * <P>
     * <p>
     * e.g.<BR />
     * 1) Probably valid in both vCard 2.1 and vCard 3.0: "ADR;TYPE=DOM;TYPE=HOME:..."<BR />
     * 2) Valid in vCard 2.1 but not in vCard 3.0: "ADR;DOM;HOME:..."<BR />
     * 3) Valid in vCard 3.0 but not in vCard 2.1: "ADR;TYPE=DOM,HOME:..."<BR />
     * </P>
     * <P>
     * </p>
     * <p>
     * 2) had been the default of VCard exporter/importer in Android, but it is found that
     * some external exporter is not able to parse the type format like 2) but only 3).
     * </P>
     * <P>
     * </p>
     * <p>
     * If you are targeting to the importer which cannot accept TYPE params without "TYPE="
     * strings (which should be rare though), please use this flag.
     * </P>
     * <P>
     * </p>
     * <p>
     * Example usage: int vcardType = (VCARD_TYPE_V21_GENERIC | FLAG_APPEND_TYPE_PARAM);
     * </P>
     * </p>
     */
    public static final int FLAG_APPEND_TYPE_PARAM = 0x04000000;

    /**
     * <P>
     * <p>
     * The flag indicating the vCard composer does touch nothing toward phone number Strings
     * but leave it as is.
     * </P>
     * <P>
     * </p>
     * <p>
     * The vCard specifications mention nothing toward phone numbers, while some devices
     * do (wrongly, but with innevitable reasons).
     * For example, there's a possibility Japanese mobile phones are expected to have
@@ -216,11 +227,11 @@ public class VCardConfig {
     * becomes "111-222-3333").
     * Unfortunate side effect of that use was some control characters used in the other
     * areas may be badly affected by the formatting.
     * </P>
     * <P>
     * </p>
     * <p>
     * This flag disables that formatting, affecting both importer and exporter.
     * If the user is aware of some side effects due to the implicit formatting, use this flag.
     * </P>
     * </p>
     */
    public static final int FLAG_REFRAIN_PHONE_NUMBER_FORMATTING = 0x02000000;

@@ -284,12 +295,12 @@ public class VCardConfig {
    /* package */ static String VCARD_TYPE_V21_GENERIC_STR = "v21_generic";
    
    /**
     * <P>
     * <p>
     * General vCard format with the version 3.0. Uses UTF-8 for the charset.
     * </P>
     * <P>
     * </p>
     * <p>
     * Not fully ready yet. Use with caution when you use this.
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_V30_GENERIC =
        (FLAG_V30 | NAME_ORDER_DEFAULT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
@@ -297,10 +308,10 @@ public class VCardConfig {
    /* package */ static final String VCARD_TYPE_V30_GENERIC_STR = "v30_generic";
    
    /**
     * <P>
     * <p>
     * General vCard format for the vCard 2.1 with some Europe convension. Uses Utf-8.
     * Currently, only name order is considered ("Prefix Middle Given Family Suffix")
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_V21_EUROPE =
        (FLAG_V21 | NAME_ORDER_EUROPE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
@@ -308,12 +319,12 @@ public class VCardConfig {
    /* package */ static final String VCARD_TYPE_V21_EUROPE_STR = "v21_europe";
    
    /**
     * <P>
     * <p>
     * General vCard format with the version 3.0 with some Europe convension. Uses UTF-8.
     * </P>
     * <P>
     * </p>
     * <p>
     * Not ready yet. Use with caution when you use this.
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_V30_EUROPE =
        (FLAG_V30 | NAME_ORDER_EUROPE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
@@ -321,12 +332,12 @@ public class VCardConfig {
    /* package */ static final String VCARD_TYPE_V30_EUROPE_STR = "v30_europe";

    /**
     * <P>
     * <p>
     * The vCard 2.1 format for miscellaneous Japanese devices, using UTF-8 as default charset.
     * </P>
     * <P>
     * </p>
     * <p>
     * Not ready yet. Use with caution when you use this.
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_V21_JAPANESE =
        (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
@@ -334,13 +345,13 @@ public class VCardConfig {
    /* package */ static final String VCARD_TYPE_V21_JAPANESE_STR = "v21_japanese_utf8";

    /**
     * <P>
     * <p>
     * vCard 2.1 format for miscellaneous Japanese devices. Shift_Jis is used for
     * parsing/composing the vCard data.
     * </P>
     * <P>
     * </p>
     * <p>
     * Not ready yet. Use with caution when you use this.
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_V21_JAPANESE_SJIS =
        (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_USE_SHIFT_JIS_FOR_EXPORT |
@@ -349,13 +360,13 @@ public class VCardConfig {
    /* package */ static final String VCARD_TYPE_V21_JAPANESE_SJIS_STR = "v21_japanese_sjis";
    
    /**
     * <P>
     * <p>
     * vCard format for miscellaneous Japanese devices, using Shift_Jis for
     * parsing/composing the vCard data.
     * </P>
     * <P>
     * </p>
     * <p>
     * Not ready yet. Use with caution when you use this.
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_V30_JAPANESE_SJIS =
        (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_USE_SHIFT_JIS_FOR_EXPORT |
@@ -364,12 +375,12 @@ public class VCardConfig {
    /* package */ static final String VCARD_TYPE_V30_JAPANESE_SJIS_STR = "v30_japanese_sjis";
    
    /**
     * <P>
     * <p>
     * The vCard 3.0 format for miscellaneous Japanese devices, using UTF-8 as default charset.
     * </P>
     * <P>
     * </p>
     * <p>
     * Not ready yet. Use with caution when you use this.
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_V30_JAPANESE =
        (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY);
@@ -377,14 +388,14 @@ public class VCardConfig {
    /* package */ static final String VCARD_TYPE_V30_JAPANESE_STR = "v30_japanese_utf8";

    /**
     * <P>
     * <p>
     * The vCard 2.1 based format which (partially) considers the convention in Japanese
     * mobile phones, where phonetic names are translated to half-width katakana if
     * possible, etc.
     * </P>
     * <P>
     * </p>
     * <p>
     * Not ready yet. Use with caution when you use this.
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_V21_JAPANESE_MOBILE =
        (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_USE_SHIFT_JIS_FOR_EXPORT |
@@ -393,14 +404,14 @@ public class VCardConfig {
    /* package */ static final String VCARD_TYPE_V21_JAPANESE_MOBILE_STR = "v21_japanese_mobile";

    /**
     * <P>
     * <p>
     * The vCard format used in DoCoMo, which is one of Japanese mobile phone careers.
     * </p>
     * <P>
     * <p>
     * Base version is vCard 2.1, but the data has several DoCoMo-specific convensions.
     * No Android-specific property nor defact property is included. The "Primary" properties
     * are NOT encoded to Quoted-Printable.
     * </P>
     * </p>
     */
    public static final int VCARD_TYPE_DOCOMO =
        (VCARD_TYPE_V21_JAPANESE_MOBILE | FLAG_DOCOMO);
+2 −2
Original line number Diff line number Diff line
@@ -52,9 +52,9 @@ public class VCardEntryCommitter implements VCardEntryHandler {
        }
    }

    public void onEntryCreated(final VCardEntry contactStruct) {
    public void onEntryCreated(final VCardEntry vcardEntry) {
        long start = System.currentTimeMillis();
        mCreatedUris.add(contactStruct.pushIntoContentResolver(mContentResolver));
        mCreatedUris.add(vcardEntry.pushIntoContentResolver(mContentResolver));
        mTimeToCommit += System.currentTimeMillis() - start;
    }

+49 −58
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package android.pim.vcard;

import android.accounts.Account;
import android.text.TextUtils;
import android.util.CharsetUtils;
import android.util.Log;

@@ -33,28 +34,19 @@ import java.util.List;
public class VCardEntryConstructor implements VCardInterpreter {
    private static String LOG_TAG = "VCardEntryConstructor";

    /**
     * If there's no other information available, this class uses this charset for encoding
     * byte arrays to String.
     */
    /* package */ static final String DEFAULT_CHARSET_FOR_DECODED_BYTES = "UTF-8";

    private VCardEntry.Property mCurrentProperty = new VCardEntry.Property();
    private VCardEntry mCurrentContactStruct;
    private VCardEntry mCurrentVCardEntry;
    private String mParamType;
    
    /**
     * The charset using which {@link VCardInterpreter} parses the text.
     */
    private String mInputCharset;
    // The charset using which {@link VCardInterpreter} parses the text.
    // Each String is first decoded into binary stream with this charset, and encoded back
    // to "target charset", which may be explicitly specified by the vCard with "CHARSET"
    // property or implicitly mentioned by its version (e.g. vCard 3.0 recommends UTF-8).
    private final String mSourceCharset;

    /**
     * The charset with which byte array is encoded to String.
     */
    final private String mCharsetForDecodedBytes;
    final private boolean mStrictLineBreakParsing;
    final private int mVCardType;
    final private Account mAccount;
    private final boolean mStrictLineBreakParsing;
    private final int mVCardType;
    private final Account mAccount;
    
    /** For measuring performance. */
    private long mTimePushIntoContentResolver;
@@ -62,30 +54,25 @@ public class VCardEntryConstructor implements VCardInterpreter {
    final private List<VCardEntryHandler> mEntryHandlers = new ArrayList<VCardEntryHandler>();

    public VCardEntryConstructor() {
        this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC, null);
        this(null, false, VCardConfig.VCARD_TYPE_V21_GENERIC, null);
    }

    public VCardEntryConstructor(final int vcardType) {
        this(null, null, false, vcardType, null);
        this(null, false, vcardType, null);
    }

    public VCardEntryConstructor(final String charset, final boolean strictLineBreakParsing,
    public VCardEntryConstructor(final String inputCharset,
            final int vcardType, final Account account) {
        this(null, charset, strictLineBreakParsing, vcardType, account);
        this(inputCharset, false, vcardType, account);
    }

    public VCardEntryConstructor(final String inputCharset, final String charsetForDetodedBytes,
    public VCardEntryConstructor(final String inputCharset,
            final boolean strictLineBreakParsing, final int vcardType,
            final Account account) {
        if (inputCharset != null) {
            mInputCharset = inputCharset;
        } else {
            mInputCharset = VCardConfig.DEFAULT_TEMPORARY_CHARSET;
        }
        if (charsetForDetodedBytes != null) {
            mCharsetForDecodedBytes = charsetForDetodedBytes;
            mSourceCharset = inputCharset;
        } else {
            mCharsetForDecodedBytes = DEFAULT_CHARSET_FOR_DECODED_BYTES;
            mSourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
        }
        mStrictLineBreakParsing = strictLineBreakParsing;
        mVCardType = vcardType;
@@ -112,7 +99,7 @@ public class VCardEntryConstructor implements VCardInterpreter {
     * Called when the parse failed between {@link #startEntry()} and {@link #endEntry()}.
     */
    public void clear() {
        mCurrentContactStruct = null;
        mCurrentVCardEntry = null;
        mCurrentProperty = new VCardEntry.Property();
    }

@@ -120,18 +107,18 @@ public class VCardEntryConstructor implements VCardInterpreter {
     * Assume that VCard is not nested. In other words, this code does not accept 
     */
    public void startEntry() {
        if (mCurrentContactStruct != null) {
        if (mCurrentVCardEntry != null) {
            Log.e(LOG_TAG, "Nested VCard code is not supported now.");
        }
        mCurrentContactStruct = new VCardEntry(mVCardType, mAccount);
        mCurrentVCardEntry = new VCardEntry(mVCardType, mAccount);
    }

    public void endEntry() {
        mCurrentContactStruct.consolidateFields();
        mCurrentVCardEntry.consolidateFields();
        for (VCardEntryHandler entryHandler : mEntryHandlers) {
            entryHandler.onEntryCreated(mCurrentContactStruct);
            entryHandler.onEntryCreated(mCurrentVCardEntry);
        }
        mCurrentContactStruct = null;
        mCurrentVCardEntry = null;
    }

    public void startProperty() {
@@ -139,7 +126,7 @@ public class VCardEntryConstructor implements VCardInterpreter {
    }

    public void endProperty() {
        mCurrentContactStruct.addProperty(mCurrentProperty);
        mCurrentVCardEntry.addProperty(mCurrentProperty);
    }
    
    public void propertyName(String name) {
@@ -166,25 +153,28 @@ public class VCardEntryConstructor implements VCardInterpreter {
        mParamType = null;
    }

    private String encodeString(String originalString, String charsetForDecodedBytes) {
        if (mInputCharset.equalsIgnoreCase(charsetForDecodedBytes)) {
    private static String encodeToSystemCharset(String originalString,
            String sourceCharset, String targetCharset) {
        if (sourceCharset.equalsIgnoreCase(targetCharset)) {
            return originalString;
        }
        Charset charset = Charset.forName(mInputCharset);
        ByteBuffer byteBuffer = charset.encode(originalString);
        final Charset charset = Charset.forName(sourceCharset);
        final ByteBuffer byteBuffer = charset.encode(originalString);
        // byteBuffer.array() "may" return byte array which is larger than
        // byteBuffer.remaining(). Here, we keep on the safe side.
        byte[] bytes = new byte[byteBuffer.remaining()];
        final byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);
        try {
            return new String(bytes, charsetForDecodedBytes);
            String ret = new String(bytes, targetCharset);
            return ret;
        } catch (UnsupportedEncodingException e) {
            Log.e(LOG_TAG, "Failed to encode: charset=" + charsetForDecodedBytes);
            Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
            return null;
        }
    }

    private String handleOneValue(String value, String charsetForDecodedBytes, String encoding) {
    private String handleOneValue(String value,
            String sourceCharset, String targetCharset, String encoding) {
        if (encoding != null) {
            if (encoding.equals("BASE64") || encoding.equals("B")) {
                mCurrentProperty.setPropertyBytes(Base64.decodeBase64(value.getBytes()));
@@ -250,9 +240,9 @@ public class VCardEntryConstructor implements VCardInterpreter {
                }
                byte[] bytes;
                try {
                    bytes = builder.toString().getBytes(mInputCharset);
                    bytes = builder.toString().getBytes(sourceCharset);
                } catch (UnsupportedEncodingException e1) {
                    Log.e(LOG_TAG, "Failed to encode: charset=" + mInputCharset);
                    Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
                    bytes = builder.toString().getBytes();
                }
                
@@ -264,15 +254,18 @@ public class VCardEntryConstructor implements VCardInterpreter {
                }

                try {
                    return new String(bytes, charsetForDecodedBytes);
                    String ret = new String(bytes, targetCharset);
                    return ret;
                } catch (UnsupportedEncodingException e) {
                    Log.e(LOG_TAG, "Failed to encode: charset=" + charsetForDecodedBytes);
                    Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
                    return new String(bytes);
                }
            }
            // Unknown encoding. Fall back to default.
            Log.w(LOG_TAG, "Unknown encoding. Fall back to default.");
        }
        return encodeString(value, charsetForDecodedBytes);

        // Just translate the charset of a given String from inputCharset to a system one. 
        return encodeToSystemCharset(value, sourceCharset, targetCharset);
    }
    
    public void propertyValues(List<String> values) {
@@ -281,20 +274,18 @@ public class VCardEntryConstructor implements VCardInterpreter {
        }

        final Collection<String> charsetCollection = mCurrentProperty.getParameters("CHARSET");
        final String charset =
            ((charsetCollection != null) ? charsetCollection.iterator().next() : null);
        final Collection<String> encodingCollection = mCurrentProperty.getParameters("ENCODING");
        final String encoding =
            ((encodingCollection != null) ? encodingCollection.iterator().next() : null);

        String charsetForDecodedBytes = CharsetUtils.nameForDefaultVendor(charset);
        if (charsetForDecodedBytes == null || charsetForDecodedBytes.length() == 0) {
            charsetForDecodedBytes = mCharsetForDecodedBytes;
        String targetCharset = CharsetUtils.nameForDefaultVendor(
                ((charsetCollection != null) ? charsetCollection.iterator().next() : null));
        if (TextUtils.isEmpty(targetCharset)) {
            targetCharset = VCardConfig.DEFAULT_IMPORT_CHARSET;
        }

        for (final String value : values) {
            mCurrentProperty.addToPropertyValueList(
                    handleOneValue(value, charsetForDecodedBytes, encoding));
                    handleOneValue(value, mSourceCharset, targetCharset, encoding));
        }
    }

+1 −16
Original line number Diff line number Diff line
@@ -38,24 +38,9 @@ public interface VCardParser {
     *
     * @param is The source to parse.
     * @param interepreter A {@link VCardInterpreter} object which used to construct data.
     * @return Returns true for success. Otherwise returns false.
     * @throws IOException, VCardException
     */
    public boolean parse(InputStream is, VCardInterpreter interepreter)
            throws IOException, VCardException;

    /**
     * <p>
     * The method variants which accept charset.
     * </p>
     *
     * @param is The source to parse.
     * @param charset Charset to be used.
     * @param interpreter The VCardBuilderBase object.
     * @return Returns true when successful. Otherwise returns false.
     * @throws IOException, VCardException
     */
    public boolean parse(InputStream is, String charset, VCardInterpreter interpreter)
    public void parse(InputStream is, VCardInterpreter interepreter)
            throws IOException, VCardException;

    /**
Loading