summaryrefslogtreecommitdiffstats
path: root/core/java/android/syncml/pim/vcard/VCardParser_V21.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/syncml/pim/vcard/VCardParser_V21.java')
-rw-r--r--core/java/android/syncml/pim/vcard/VCardParser_V21.java970
1 files changed, 970 insertions, 0 deletions
diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V21.java b/core/java/android/syncml/pim/vcard/VCardParser_V21.java
new file mode 100644
index 0000000..b6fa032
--- /dev/null
+++ b/core/java/android/syncml/pim/vcard/VCardParser_V21.java
@@ -0,0 +1,970 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.syncml.pim.vcard;
+
+import android.syncml.pim.VParser;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class is used to parse vcard. Please refer to vCard Specification 2.1
+ */
+public class VCardParser_V21 extends VParser {
+
+ /** Store the known-type */
+ private static final HashSet<String> mKnownTypeSet = new HashSet<String>(
+ Arrays.asList("DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK",
+ "PREF", "VOICE", "FAX", "MSG", "CELL", "PAGER", "BBS",
+ "MODEM", "CAR", "ISDN", "VIDEO", "AOL", "APPLELINK",
+ "ATTMAIL", "CIS", "EWORLD", "INTERNET", "IBMMAIL",
+ "MCIMAIL", "POWERSHARE", "PRODIGY", "TLX", "X400", "GIF",
+ "CGM", "WMF", "BMP", "MET", "PMB", "DIB", "PICT", "TIFF",
+ "PDF", "PS", "JPEG", "QTIME", "MPEG", "MPEG2", "AVI",
+ "WAVE", "AIFF", "PCM", "X509", "PGP"));
+
+ /** Store the name */
+ private static final HashSet<String> mName = new HashSet<String>(Arrays
+ .asList("LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND",
+ "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL",
+ "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER"));
+
+ /**
+ * Create a new VCard parser.
+ */
+ public VCardParser_V21() {
+ super();
+ }
+
+ /**
+ * Parse the file at the given position
+ *
+ * @param offset
+ * the given position to parse
+ * @return vcard length
+ */
+ protected int parseVFile(int offset) {
+ return parseVCardFile(offset);
+ }
+
+ /**
+ * [wsls] vcard [wsls]
+ */
+ int parseVCardFile(int offset) {
+ int ret = 0, sum = 0;
+
+ /* remove \t \r\n */
+ while ((ret = parseWsls(offset)) != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ ret = parseVCard(offset); // BEGIN:VCARD ... END:VCARD
+ if (ret != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ } else {
+ return PARSE_ERROR;
+ }
+
+ /* remove \t \r\n */
+ while ((ret = parseWsls(offset)) != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+ return sum;
+ }
+
+ /**
+ * "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF items *CRLF "END" [ws] ":"
+ * "VCARD"
+ */
+ private int parseVCard(int offset) {
+ int ret = 0, sum = 0;
+
+ /* BEGIN */
+ ret = parseString(offset, "BEGIN", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ /* [ws] */
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ /* colon */
+ ret = parseString(offset, ":", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ /* [ws] */
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ /* VCARD */
+ ret = parseString(offset, "VCARD", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.startRecord("VCARD");
+ }
+
+ /* [ws] */
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ /* 1*CRLF */
+ ret = parseCrlf(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ while ((ret = parseCrlf(offset)) != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ ret = parseItems(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ /* *CRLF */
+ while ((ret = parseCrlf(offset)) != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ /* END */
+ ret = parseString(offset, "END", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ /* [ws] */
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ /* colon */
+ ret = parseString(offset, ":", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ /* [ws] */
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ /* VCARD */
+ ret = parseString(offset, "VCARD", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ // offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.endRecord();
+ }
+
+ return sum;
+ }
+
+ /**
+ * items *CRLF item / item
+ */
+ private int parseItems(int offset) {
+ /* items *CRLF item / item */
+ int ret = 0, sum = 0;
+
+ if (mBuilder != null) {
+ mBuilder.startProperty();
+ }
+ ret = parseItem(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.endProperty();
+ }
+
+ for (;;) {
+ while ((ret = parseCrlf(offset)) != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+ // follow VCARD ,it wont reach endProperty
+ if (mBuilder != null) {
+ mBuilder.startProperty();
+ }
+
+ ret = parseItem(offset);
+ if (ret == PARSE_ERROR) {
+ break;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.endProperty();
+ }
+ }
+
+ return sum;
+ }
+
+ /**
+ * item0 / item1 / item2
+ */
+ private int parseItem(int offset) {
+ int ret = 0, sum = 0;
+ mEncoding = mDefaultEncoding;
+
+ ret = parseItem0(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ ret = parseItem1(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ ret = parseItem2(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ return PARSE_ERROR;
+ }
+
+ /** [groups "."] name [params] ":" value CRLF */
+ private int parseItem0(int offset) {
+ int ret = 0, sum = 0, start = offset;
+ String proName = "", proValue = "";
+
+ ret = parseGroupsWithDot(offset);
+ if (ret != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ ret = parseName(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ proName = mBuffer.substring(start, offset).trim();
+ mBuilder.propertyName(proName);
+ }
+
+ ret = parseParams(offset);
+ if (ret != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ ret = parseString(offset, ":", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ start = offset;
+ ret = parseValue(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ proValue = mBuffer.substring(start, offset);
+ if (proName.equals("VERSION") && !proValue.equals("2.1")) {
+ return PARSE_ERROR;
+ }
+ if (mBuilder != null) {
+ ArrayList<String> v = new ArrayList<String>();
+ v.add(proValue);
+ mBuilder.propertyValues(v);
+ }
+
+ ret = parseCrlf(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ sum += ret;
+
+ return sum;
+ }
+
+ /** "ADR" "ORG" "N" with semi-colon separated content */
+ private int parseItem1(int offset) {
+ int ret = 0, sum = 0, start = offset;
+
+ ret = parseGroupsWithDot(offset);
+ if (ret != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ if ((ret = parseString(offset, "ADR", true)) == PARSE_ERROR
+ && (ret = parseString(offset, "ORG", true)) == PARSE_ERROR
+ && (ret = parseString(offset, "N", true)) == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyName(mBuffer.substring(start, offset).trim());
+ }
+
+ ret = parseParams(offset);
+ if (ret != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ ret = parseString(offset, ":", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ start = offset;
+ ret = parseValue(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ int end = 0;
+ ArrayList<String> v = new ArrayList<String>();
+ Pattern p = Pattern
+ .compile("([^;\\\\]*(\\\\[\\\\;:,])*[^;\\\\]*)(;?)");
+ Matcher m = p.matcher(mBuffer.substring(start, offset));
+ while (m.find()) {
+ String s = escapeTranslator(m.group(1));
+ v.add(s);
+ end = m.end();
+ if (offset == start + end) {
+ String endValue = m.group(3);
+ if (";".equals(endValue)) {
+ v.add("");
+ }
+ break;
+ }
+ }
+ mBuilder.propertyValues(v);
+ }
+
+ ret = parseCrlf(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ sum += ret;
+
+ return sum;
+ }
+
+ /** [groups] "." "AGENT" [params] ":" vcard CRLF */
+ private int parseItem2(int offset) {
+ int ret = 0, sum = 0, start = offset;
+
+ ret = parseGroupsWithDot(offset);
+ if (ret != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ ret = parseString(offset, "AGENT", true);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyName(mBuffer.substring(start, offset));
+ }
+
+ ret = parseParams(offset);
+ if (ret != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ ret = parseString(offset, ":", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = parseCrlf(offset);
+ if (ret != PARSE_ERROR) {
+ offset += ret;
+ sum += ret;
+ }
+
+ ret = parseVCard(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyValues(new ArrayList<String>());
+ }
+
+ ret = parseCrlf(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ sum += ret;
+
+ return sum;
+ }
+
+ private int parseGroupsWithDot(int offset) {
+ int ret = 0, sum = 0;
+ /* [groups "."] */
+ ret = parseGroups(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = parseString(offset, ".", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ sum += ret;
+
+ return sum;
+ }
+
+ /** ";" [ws] paramlist */
+ private int parseParams(int offset) {
+ int ret = 0, sum = 0;
+
+ ret = parseString(offset, ";", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ ret = parseParamList(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ sum += ret;
+
+ return sum;
+ }
+
+ /**
+ * paramlist [ws] ";" [ws] param / param
+ */
+ private int parseParamList(int offset) {
+ int ret = 0, sum = 0;
+
+ ret = parseParam(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ int offsetTemp = offset;
+ int sumTemp = sum;
+ for (;;) {
+ ret = removeWs(offsetTemp);
+ offsetTemp += ret;
+ sumTemp += ret;
+
+ ret = parseString(offsetTemp, ";", false);
+ if (ret == PARSE_ERROR) {
+ return sum;
+ }
+ offsetTemp += ret;
+ sumTemp += ret;
+
+ ret = removeWs(offsetTemp);
+ offsetTemp += ret;
+ sumTemp += ret;
+
+ ret = parseParam(offsetTemp);
+ if (ret == PARSE_ERROR) {
+ break;
+ }
+ offsetTemp += ret;
+ sumTemp += ret;
+
+ // offset = offsetTemp;
+ sum = sumTemp;
+ }
+ return sum;
+ }
+
+ /**
+ * param0 / param1 / param2 / param3 / param4 / param5 / knowntype<BR>
+ * TYPE / VALUE / ENDCODING / CHARSET / LANGUAGE ...
+ */
+ private int parseParam(int offset) {
+ int ret = 0, sum = 0;
+
+ ret = parseParam0(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ ret = parseParam1(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ ret = parseParam2(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ ret = parseParam3(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ ret = parseParam4(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ ret = parseParam5(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ int start = offset;
+ ret = parseKnownType(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamType(null);
+ mBuilder.propertyParamValue(mBuffer.substring(start, offset));
+ }
+
+ return sum;
+ }
+
+ /** "TYPE" [ws] "=" [ws] ptypeval */
+ private int parseParam0(int offset) {
+ int ret = 0, sum = 0, start = offset;
+
+ ret = parseString(offset, "TYPE", true);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamType(mBuffer.substring(start, offset));
+ }
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ ret = parseString(offset, "=", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ start = offset;
+ ret = parsePTypeVal(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamValue(mBuffer.substring(start, offset));
+ }
+
+ return sum;
+
+ }
+
+ /** "VALUE" [ws] "=" [ws] pvalueval */
+ private int parseParam1(int offset) {
+ int ret = 0, sum = 0, start = offset;
+
+ ret = parseString(offset, "VALUE", true);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamType(mBuffer.substring(start, offset));
+ }
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ ret = parseString(offset, "=", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ start = offset;
+ ret = parsePValueVal(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamValue(mBuffer.substring(start, offset));
+ }
+
+ return sum;
+ }
+
+ /** "ENCODING" [ws] "=" [ws] pencodingval */
+ private int parseParam2(int offset) {
+ int ret = 0, sum = 0, start = offset;
+
+ ret = parseString(offset, "ENCODING", true);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamType(mBuffer.substring(start, offset));
+ }
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ ret = parseString(offset, "=", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ start = offset;
+ ret = parsePEncodingVal(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamValue(mBuffer.substring(start, offset));
+ }
+
+ return sum;
+
+ }
+
+ /** "CHARSET" [ws] "=" [ws] charsetval */
+ private int parseParam3(int offset) {
+ int ret = 0, sum = 0, start = offset;
+
+ ret = parseString(offset, "CHARSET", true);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamType(mBuffer.substring(start, offset));
+ }
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ ret = parseString(offset, "=", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ start = offset;
+ ret = parseCharsetVal(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamValue(mBuffer.substring(start, offset));
+ }
+
+ return sum;
+ }
+
+ /** "LANGUAGE" [ws] "=" [ws] langval */
+ private int parseParam4(int offset) {
+ int ret = 0, sum = 0, start = offset;
+
+ ret = parseString(offset, "LANGUAGE", true);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamType(mBuffer.substring(start, offset));
+ }
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ ret = parseString(offset, "=", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ start = offset;
+ ret = parseLangVal(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamValue(mBuffer.substring(start, offset));
+ }
+
+ return sum;
+
+ }
+
+ /** "X-" word [ws] "=" [ws] word */
+ private int parseParam5(int offset) {
+ int ret = 0, sum = 0, start = offset;
+
+ ret = parseXWord(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamType(mBuffer.substring(start, offset));
+ }
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ ret = parseString(offset, "=", false);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ ret = removeWs(offset);
+ offset += ret;
+ sum += ret;
+
+ start = offset;
+ ret = parseWord(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+ if (mBuilder != null) {
+ mBuilder.propertyParamValue(mBuffer.substring(start, offset));
+ }
+
+ return sum;
+ }
+
+ /**
+ * knowntype: "DOM" / "INTL" / ...
+ */
+ private int parseKnownType(int offset) {
+ String word = getWord(offset);
+
+ if (mKnownTypeSet.contains(word.toUpperCase())) {
+ return word.length();
+ }
+ return PARSE_ERROR;
+ }
+
+ /** knowntype / "X-" word */
+ private int parsePTypeVal(int offset) {
+ int ret = 0, sum = 0;
+
+ ret = parseKnownType(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+
+ ret = parseXWord(offset);
+ if (ret != PARSE_ERROR) {
+ sum += ret;
+ return sum;
+ }
+ sum += ret;
+
+ return sum;
+ }
+
+ /** "LOGO" /.../ XWord, case insensitive */
+ private int parseName(int offset) {
+ int ret = 0;
+ ret = parseXWord(offset);
+ if (ret != PARSE_ERROR) {
+ return ret;
+ }
+ String word = getWord(offset).toUpperCase();
+ if (mName.contains(word)) {
+ return word.length();
+ }
+ return PARSE_ERROR;
+ }
+
+ /** groups "." word / word */
+ private int parseGroups(int offset) {
+ int ret = 0, sum = 0;
+
+ ret = parseWord(offset);
+ if (ret == PARSE_ERROR) {
+ return PARSE_ERROR;
+ }
+ offset += ret;
+ sum += ret;
+
+ for (;;) {
+ ret = parseString(offset, ".", false);
+ if (ret == PARSE_ERROR) {
+ break;
+ }
+
+ int ret1 = parseWord(offset);
+ if (ret1 == PARSE_ERROR) {
+ break;
+ }
+ offset += ret + ret1;
+ sum += ret + ret1;
+ }
+ return sum;
+ }
+
+ /**
+ * Translate escape characters("\\", "\;") which define in vcard2.1 spec.
+ * But for fault tolerance, we will translate "\:" and "\,", which isn't
+ * define in vcard2.1 explicitly, as the same behavior as other client.
+ *
+ * @param str:
+ * the string will be translated.
+ * @return the string which do not contain any escape character in vcard2.1
+ */
+ private String escapeTranslator(String str) {
+ if (null == str)
+ return null;
+
+ String tmp = str.replace("\\\\", "\n\r\n");
+ tmp = tmp.replace("\\;", ";");
+ tmp = tmp.replace("\\:", ":");
+ tmp = tmp.replace("\\,", ",");
+ tmp = tmp.replace("\n\r\n", "\\");
+ return tmp;
+ }
+}