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

Commit c9a8e0ba authored by Daisuke Miyakawa's avatar Daisuke Miyakawa Committed by The Android Open Source Project
Browse files

Automated import from //branches/master/...@142673,142673

parent a605a51e
Loading
Loading
Loading
Loading
+127 −10
Original line number Diff line number Diff line
@@ -16,25 +16,142 @@

package android.syncml.pim;

import java.util.ArrayList;
import java.util.Collection;

import android.content.ContentValues;
import android.util.Log;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class PropertyNode {

    public String propName;

    public String propValue = "";
    public String propValue;

    public Collection<String> propValue_vector;
    public List<String> propValue_vector;

    /** Store value as byte[],after decode. */
    public byte[] propValue_byts;
    /** Store value as byte[],after decode.
     * Used when propValue is encoded by something like BASE64, QUOTED-PRINTABLE, etc.
     */
    public byte[] propValue_bytes;

    /** param store: key=paramType, value=paramValue */
    public ContentValues paraMap = new ContentValues();
    /** param store: key=paramType, value=paramValue
     * Note that currently PropertyNode class does not support multiple param-values
     * defined in vCard 3.0 (See also RFC 2426). multiple-values are stored as
     * one String value like "A,B", not ["A", "B"]...
     * TODO: fix this. 
     */
    public ContentValues paramMap;

    /** Only for TYPE=??? param store. */
    public ArrayList<String> paraMap_TYPE = new ArrayList<String>();
    public Set<String> paramMap_TYPE;

    /** Store group values. Used only in VCard. */
    public Set<String> propGroupSet;
    
    public PropertyNode() {
        propValue = "";
        paramMap = new ContentValues();
        paramMap_TYPE = new HashSet<String>();
        propGroupSet = new HashSet<String>();
    }
    
    public PropertyNode(
            String propName, String propValue, List<String> propValue_vector,
            byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE,
            Set<String> propGroupSet) {
        this.propName = propName;
        if (propValue != null) {
            this.propValue = propValue;
        } else {
            this.propValue = "";
        }
        this.propValue_vector = propValue_vector;
        this.propValue_bytes = propValue_bytes;
        if (paramMap != null) {
            this.paramMap = paramMap;
        } else {
            this.paramMap = new ContentValues();
        }
        if (paramMap_TYPE != null) {
            this.paramMap_TYPE = paramMap_TYPE;
        } else {
            this.paramMap_TYPE = new HashSet<String>();
        }
        if (propGroupSet != null) {
            this.propGroupSet = propGroupSet;
        } else {
            this.propGroupSet = new HashSet<String>();
        }
    }
    
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof PropertyNode)) {
            return false;
        }
        
        PropertyNode node = (PropertyNode)obj;
        
        if (propName == null || !propName.equals(node.propName)) {
            return false;
        } else if (!paramMap.equals(node.paramMap)) {
            return false;
        } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) {
            return false;
        } else if (!propGroupSet.equals(node.propGroupSet)) {
            return false;
        }
        
        if (propValue_bytes != null && Arrays.equals(propValue_bytes, node.propValue_bytes)) {
            return true;
        } else {
            // Log.d("@@@", propValue + ", " + node.propValue);
            if (!propValue.equals(node.propValue)) {
                return false;
            }

            // The value in propValue_vector is not decoded even if it should be
            // decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector
            // is 1, the encoded value is stored in propValue, so we do not have to
            // check it.
            if (propValue_vector != null) {
                // Log.d("@@@", "===" + propValue_vector + ", " + node.propValue_vector);
                return (propValue_vector.equals(node.propValue_vector) ||
                        (propValue_vector.size() == 1));
            } else if (node.propValue_vector != null) {
                // Log.d("@@@", "===" + propValue_vector + ", " + node.propValue_vector);
                return (node.propValue_vector.equals(propValue_vector) ||
                        (node.propValue_vector.size() == 1));
            } else {
                return true;
            }
        }
    }
    
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("propName: ");
        builder.append(propName);
        builder.append(", paramMap: ");
        builder.append(paramMap.toString());
        builder.append(", propmMap_TYPE: ");
        builder.append(paramMap_TYPE.toString());
        builder.append(", propGroupSet: ");
        builder.append(propGroupSet.toString());
        if (propValue_vector != null && propValue_vector.size() > 1) {
            builder.append(", propValue_vector size: ");
            builder.append(propValue_vector.size());
        }
        if (propValue_bytes != null) {
            builder.append(", propValue_bytes size: ");
            builder.append(propValue_bytes.length);
        }
        builder.append(", propValue: ");
        builder.append(propValue);
        return builder.toString();
    }
}
+9 −4
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package android.syncml.pim;

import java.util.Collection;
import java.util.List;

public interface VBuilder {
    void start();
@@ -37,10 +37,15 @@ public interface VBuilder {

    void endProperty();

    /**
     * @param group 
     */
    void propertyGroup(String group);
    
    /**
     * @param name
     *            a.N <br>
     *            a.N
     *            N <br>
     *            N
     */
    void propertyName(String name);

@@ -58,5 +63,5 @@ public interface VBuilder {
     */
    void propertyParamValue(String value);

    void propertyValues(Collection<String> values);
    void propertyValues(List<String> values);
}
+169 −51
Original line number Diff line number Diff line
@@ -16,11 +16,19 @@

package android.syncml.pim;

import android.content.ContentValues;
import android.util.Log;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.net.QuotedPrintableCodec;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Vector;

/**
 * Store the parse result to custom datastruct: VNode, PropertyNode
@@ -29,13 +37,31 @@ import java.util.Collection;
 * PropertyNode: standy by a property line of a card.
 */
public class VDataBuilder implements VBuilder {
    static private String LOG_TAG = "VDATABuilder"; 

    /** type=VNode */
    public ArrayList<VNode> vNodeList = new ArrayList<VNode>();
    int nodeListPos = 0;
    VNode curVNode;
    PropertyNode curPropNode;
    String curParamType;
    public List<VNode> vNodeList = new ArrayList<VNode>();
    private int mNodeListPos = 0;
    private VNode mCurrentVNode;
    private PropertyNode mCurrentPropNode;
    private String mCurrentParamType;
    
    /**
     * Assumes that each String can be encoded into byte array using this encoding.
     */
    private String mCharset;
    
    private boolean mStrictLineBreakParsing;
    
    public VDataBuilder() {
        mCharset = "ISO-8859-1";
        mStrictLineBreakParsing = false;
    }

    public VDataBuilder(String encoding, boolean strictLineBreakParsing) {
        mCharset = encoding;
        mStrictLineBreakParsing = strictLineBreakParsing;
    }
    
    public void start() {
    }
@@ -48,19 +74,19 @@ public class VDataBuilder implements VBuilder {
        vnode.parseStatus = 1;
        vnode.VName = type;
        vNodeList.add(vnode);
        nodeListPos = vNodeList.size()-1;
        curVNode = vNodeList.get(nodeListPos);
        mNodeListPos = vNodeList.size()-1;
        mCurrentVNode = vNodeList.get(mNodeListPos);
    }

    public void endRecord() {
        VNode endNode = vNodeList.get(nodeListPos);
        VNode endNode = vNodeList.get(mNodeListPos);
        endNode.parseStatus = 0;
        while(nodeListPos > 0){
            nodeListPos--;
            if((vNodeList.get(nodeListPos)).parseStatus == 1)
        while(mNodeListPos > 0){
            mNodeListPos--;
            if((vNodeList.get(mNodeListPos)).parseStatus == 1)
                break;
        }
        curVNode = vNodeList.get(nodeListPos);
        mCurrentVNode = vNodeList.get(mNodeListPos);
    }

    public void startProperty() {
@@ -72,55 +98,147 @@ public class VDataBuilder implements VBuilder {
    }
    
    public void propertyName(String name) {
        curPropNode = new PropertyNode();
        curPropNode.propName = name;
        mCurrentPropNode = new PropertyNode();
        mCurrentPropNode.propName = name;
    }

    // Used only in VCard.
    public void propertyGroup(String group) {
        mCurrentPropNode.propGroupSet.add(group);
    }
    
    public void propertyParamType(String type) {
        curParamType = type;
        mCurrentParamType = type;
    }

    public void propertyParamValue(String value) {
        if(curParamType == null)
            curPropNode.paraMap_TYPE.add(value);
        else if(curParamType.equalsIgnoreCase("TYPE"))
            curPropNode.paraMap_TYPE.add(value);
        else
            curPropNode.paraMap.put(curParamType, value);

        curParamType = null;
    }

    public void propertyValues(Collection<String> values) {
        curPropNode.propValue_vector = values;
        curPropNode.propValue = listToString(values);
        //decode value string to propValue_byts
        if(curPropNode.paraMap.containsKey("ENCODING")){
            if(curPropNode.paraMap.getAsString("ENCODING").
                                        equalsIgnoreCase("BASE64")){
                curPropNode.propValue_byts =
                    Base64.decodeBase64(curPropNode.propValue.
        if (mCurrentParamType == null ||
                mCurrentParamType.equalsIgnoreCase("TYPE")) {
            mCurrentPropNode.paramMap_TYPE.add(value);
        } else {
            mCurrentPropNode.paramMap.put(mCurrentParamType, value);
        }

        mCurrentParamType = null;
    }

    private String encodeString(String originalString, String targetEncoding) {
        Charset charset = Charset.forName(mCharset);
        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()];
        byteBuffer.get(bytes);
        try {
            return new String(bytes, targetEncoding);
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }
    
    public void propertyValues(List<String> values) {
        ContentValues paramMap = mCurrentPropNode.paramMap;
        
        String charsetString = paramMap.getAsString("CHARSET"); 

        boolean setupParamValues = false;
        //decode value string to propValue_bytes
        if (paramMap.containsKey("ENCODING")) {
            String encoding = paramMap.getAsString("ENCODING"); 
            if (encoding.equalsIgnoreCase("BASE64") ||
                    encoding.equalsIgnoreCase("B")) {
                if (values.size() > 1) {
                    Log.e(LOG_TAG,
                            ("BASE64 encoding is used while " +
                             "there are multiple values (" + values.size()));
                }
                mCurrentPropNode.propValue_bytes =
                    Base64.decodeBase64(values.get(0).
                            replaceAll(" ","").replaceAll("\t","").
                            replaceAll("\r\n","").
                            getBytes());
            }
            if(curPropNode.paraMap.getAsString("ENCODING").
                                        equalsIgnoreCase("QUOTED-PRINTABLE")){

            if(encoding.equalsIgnoreCase("QUOTED-PRINTABLE")){
                // if CHARSET is defined, we translate each String into the Charset.
                List<String> tmpValues = new ArrayList<String>();
                Vector<byte[]> byteVector = new Vector<byte[]>();
                int size = 0;
                try{
                    curPropNode.propValue_byts =
                        QuotedPrintableCodec.decodeQuotedPrintable(
                                curPropNode.propValue.
                                replaceAll("= ", " ").replaceAll("=\t", "\t").
                                getBytes() );
                    curPropNode.propValue =
                        new String(curPropNode.propValue_byts);
                    for (String value : values) {                                    
                        String quotedPrintable = value
                        .replaceAll("= ", " ").replaceAll("=\t", "\t");
                        String[] lines;
                        if (mStrictLineBreakParsing) {
                            lines = quotedPrintable.split("\r\n");
                        } else {
                            lines = quotedPrintable
                            .replace("\r\n", "\n").replace("\r", "\n").split("\n");
                        }
                        StringBuilder builder = new StringBuilder();
                        for (String line : lines) {
                            if (line.endsWith("=")) {
                                line = line.substring(0, line.length() - 1);
                            }
                            builder.append(line);
                        }
                        byte[] bytes = QuotedPrintableCodec.decodeQuotedPrintable(
                                builder.toString().getBytes());
                        if (charsetString != null) {
                            try {
                                tmpValues.add(new String(bytes, charsetString));
                            } catch (UnsupportedEncodingException e) {
                                Log.e(LOG_TAG, "Failed to encode: charset=" + charsetString);
                                tmpValues.add(new String(bytes));
                            }
                        } else {
                            tmpValues.add(new String(bytes));
                        }
                        byteVector.add(bytes);
                        size += bytes.length;
                    }  // for (String value : values) {
                    mCurrentPropNode.propValue_vector = tmpValues;
                    mCurrentPropNode.propValue = listToString(tmpValues);

                    mCurrentPropNode.propValue_bytes = new byte[size];

                    {
                        byte[] tmpBytes = mCurrentPropNode.propValue_bytes;
                        int index = 0;
                        for (byte[] bytes : byteVector) {
                            int length = bytes.length;
                            for (int i = 0; i < length; i++, index++) {
                                tmpBytes[index] = bytes[i];
                            }
                        }
                    }
                    setupParamValues = true;
                } catch(Exception e) {
                    System.out.println("=Decode quoted-printable exception.");
                    e.printStackTrace();
                    Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e);
                }
            }  // QUOTED-PRINTABLE
        }  //  ENCODING
        
        if (!setupParamValues) {
            // if CHARSET is defined, we translate each String into the Charset.
            if (charsetString != null) {
                List<String> tmpValues = new ArrayList<String>();
                for (String value : values) {
                    String result = encodeString(value, charsetString);
                    if (result != null) {
                        tmpValues.add(result);
                    } else {
                        Log.e(LOG_TAG, "Failed to encode: charset=" + charsetString);
                        tmpValues.add(value);
                    }
                }
                values = tmpValues;
            }
            
            mCurrentPropNode.propValue_vector = values;
            mCurrentPropNode.propValue = listToString(values);
        }
        curVNode.propList.add(curPropNode);
        mCurrentVNode.propList.add(mCurrentPropNode);
    }

    private String listToString(Collection<String> list){
+2 −1
Original line number Diff line number Diff line
@@ -26,7 +26,8 @@ import java.io.IOException;

public class VCardParser {

    VParser mParser = null;
    // TODO: fix this.
    VCardParser_V21 mParser = null;

    public final static String VERSION_VCARD21 = "vcard2.1";

+545 −834

File changed.

Preview size limit exceeded, changes collapsed.

Loading