| /* |
| * Copyright (C) 2007 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.vcalendar; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import android.syncml.pim.VParser; |
| |
| public class VCalParser_V10 extends VParser { |
| |
| /* |
| * The names of the properties whose value are not separated by ";" |
| */ |
| private static final HashSet<String> mEvtPropNameGroup1 = new HashSet<String>( |
| Arrays.asList("ATTACH", "ATTENDEE", "DCREATED", "COMPLETED", |
| "DESCRIPTION", "DUE", "DTEND", "EXRULE", "LAST-MODIFIED", |
| "LOCATION", "RNUM", "PRIORITY", "RELATED-TO", "RRULE", |
| "SEQUENCE", "DTSTART", "SUMMARY", "TRANSP", "URL", "UID", |
| // above belong to simprop |
| "CLASS", "STATUS")); |
| |
| /* |
| * The names of properties whose value are separated by ";" |
| */ |
| private static final HashSet<String> mEvtPropNameGroup2 = new HashSet<String>( |
| Arrays.asList("AALARM", "CATEGORIES", "DALARM", "EXDATE", "MALARM", |
| "PALARM", "RDATE", "RESOURCES")); |
| |
| private static final HashSet<String> mValueCAT = new HashSet<String>(Arrays |
| .asList("APPOINTMENT", "BUSINESS", "EDUCATION", "HOLIDAY", |
| "MEETING", "MISCELLANEOUS", "PERSONAL", "PHONE CALL", |
| "SICK DAY", "SPECIAL OCCASION", "TRAVEL", "VACATION")); |
| |
| private static final HashSet<String> mValueCLASS = new HashSet<String>(Arrays |
| .asList("PUBLIC", "PRIVATE", "CONFIDENTIAL")); |
| |
| private static final HashSet<String> mValueRES = new HashSet<String>(Arrays |
| .asList("CATERING", "CHAIRS", "EASEL", "PROJECTOR", "VCR", |
| "VEHICLE")); |
| |
| private static final HashSet<String> mValueSTAT = new HashSet<String>(Arrays |
| .asList("ACCEPTED", "NEEDS ACTION", "SENT", "TENTATIVE", |
| "CONFIRMED", "DECLINED", "COMPLETED", "DELEGATED")); |
| |
| /* |
| * The names of properties whose value can contain escape characters |
| */ |
| private static final HashSet<String> mEscAllowedProps = new HashSet<String>( |
| Arrays.asList("DESCRIPTION", "SUMMARY", "AALARM", "DALARM", |
| "MALARM", "PALARM")); |
| |
| private static final HashMap<String, HashSet<String>> mSpecialValueSetMap = |
| new HashMap<String, HashSet<String>>(); |
| |
| static { |
| mSpecialValueSetMap.put("CATEGORIES", mValueCAT); |
| mSpecialValueSetMap.put("CLASS", mValueCLASS); |
| mSpecialValueSetMap.put("RESOURCES", mValueRES); |
| mSpecialValueSetMap.put("STATUS", mValueSTAT); |
| } |
| |
| public VCalParser_V10() { |
| } |
| |
| protected int parseVFile(int offset) { |
| return parseVCalFile(offset); |
| } |
| |
| private int parseVCalFile(int offset) { |
| int ret = 0, sum = 0; |
| |
| /* remove wsls */ |
| while (PARSE_ERROR != (ret = parseWsls(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| ret = parseVCal(offset); // BEGIN:VCAL ... END:VCAL |
| if (PARSE_ERROR != ret) { |
| offset += ret; |
| sum += ret; |
| } else { |
| return PARSE_ERROR; |
| } |
| |
| /* remove wsls */ |
| while (PARSE_ERROR != (ret = parseWsls(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| return sum; |
| } |
| |
| /** |
| * "BEGIN" [ws] ":" [ws] "VCALENDAR" [ws] 1*crlf calprop calentities [ws] |
| * *crlf "END" [ws] ":" [ws] "VCALENDAR" [ws] 1*CRLF |
| */ |
| private int parseVCal(int offset) { |
| int ret = 0, sum = 0; |
| |
| /* BEGIN */ |
| ret = parseString(offset, "BEGIN", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // ":" |
| ret = parseString(offset, ":", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // "VCALENDAR |
| ret = parseString(offset, "VCALENDAR", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.startRecord("VCALENDAR"); |
| } |
| |
| /* [ws] */ |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // 1*CRLF |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| // calprop |
| ret = parseCalprops(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // calentities |
| ret = parseCalentities(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // *CRLF |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| // "END" |
| ret = parseString(offset, "END", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // ":" |
| // ":" |
| ret = parseString(offset, ":", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // "VCALENDAR" |
| ret = parseString(offset, "VCALENDAR", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.endRecord(); |
| } |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // 1 * CRLF |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * calprops * CRLF calprop / calprop |
| */ |
| private int parseCalprops(int offset) { |
| int ret = 0, sum = 0; |
| |
| if (mBuilder != null) { |
| mBuilder.startProperty(); |
| } |
| ret = parseCalprop(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.endProperty(); |
| } |
| |
| for (;;) { |
| /* *CRLF */ |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| // follow VEVENT ,it wont reach endProperty |
| if (mBuilder != null) { |
| mBuilder.startProperty(); |
| } |
| ret = parseCalprop(offset); |
| if (PARSE_ERROR == ret) { |
| break; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.endProperty(); |
| } |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * calentities *CRLF calentity / calentity |
| */ |
| private int parseCalentities(int offset) { |
| int ret = 0, sum = 0; |
| |
| ret = parseCalentity(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| for (;;) { |
| /* *CRLF */ |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| ret = parseCalentity(offset); |
| if (PARSE_ERROR == ret) { |
| break; |
| } |
| offset += ret; |
| sum += ret; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * calprop = DAYLIGHT/ GEO/ PRODID/ TZ/ VERSION |
| */ |
| private int parseCalprop(int offset) { |
| int ret = 0; |
| |
| ret = parseCalprop0(offset, "DAYLIGHT"); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseCalprop0(offset, "GEO"); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseCalprop0(offset, "PRODID"); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseCalprop0(offset, "TZ"); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseCalprop1(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| return PARSE_ERROR; |
| } |
| |
| /** |
| * evententity / todoentity |
| */ |
| private int parseCalentity(int offset) { |
| int ret = 0; |
| |
| ret = parseEvententity(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseTodoentity(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| return PARSE_ERROR; |
| |
| } |
| |
| /** |
| * propName [params] ":" value CRLF |
| */ |
| private int parseCalprop0(int offset, String propName) { |
| int ret = 0, sum = 0, start = 0; |
| |
| ret = parseString(offset, propName, true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyName(propName); |
| } |
| |
| ret = parseParams(offset); |
| if (PARSE_ERROR != ret) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| ret = parseString(offset, ":", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parseValue(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| ArrayList<String> v = new ArrayList<String>(); |
| v.add(mBuffer.substring(start, offset)); |
| mBuilder.propertyValues(v); |
| } |
| |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| sum += ret; |
| |
| return sum; |
| } |
| |
| /** |
| * "VERSION" [params] ":" "1.0" CRLF |
| */ |
| private int parseCalprop1(int offset) { |
| int ret = 0, sum = 0; |
| |
| ret = parseString(offset, "VERSION", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyName("VERSION"); |
| } |
| |
| ret = parseParams(offset); |
| if (PARSE_ERROR != ret) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| ret = parseString(offset, ":", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| ret = parseString(offset, "1.0", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| ArrayList<String> v = new ArrayList<String>(); |
| v.add("1.0"); |
| mBuilder.propertyValues(v); |
| } |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| sum += ret; |
| |
| return sum; |
| } |
| |
| /** |
| * "BEGIN" [ws] ":" [ws] "VEVENT" [ws] 1*CRLF entprops [ws] *CRLF "END" [ws] |
| * ":" [ws] "VEVENT" [ws] 1*CRLF |
| */ |
| private int parseEvententity(int offset) { |
| int ret = 0, sum = 0; |
| |
| ret = parseString(offset, "BEGIN", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // ":" |
| ret = parseString(offset, ":", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // "VEVNET" |
| ret = parseString(offset, "VEVENT", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.startRecord("VEVENT"); |
| } |
| |
| /* [ws] */ |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // 1*CRLF |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| ret = parseEntprops(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // *CRLF |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| // "END" |
| ret = parseString(offset, "END", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // ":" |
| ret = parseString(offset, ":", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // "VEVENT" |
| ret = parseString(offset, "VEVENT", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.endRecord(); |
| } |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // 1 * CRLF |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * "BEGIN" [ws] ":" [ws] "VTODO" [ws] 1*CRLF entprops [ws] *CRLF "END" [ws] |
| * ":" [ws] "VTODO" [ws] 1*CRLF |
| */ |
| private int parseTodoentity(int offset) { |
| int ret = 0, sum = 0; |
| |
| ret = parseString(offset, "BEGIN", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // ":" |
| ret = parseString(offset, ":", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // "VTODO" |
| ret = parseString(offset, "VTODO", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.startRecord("VTODO"); |
| } |
| |
| // 1*CRLF |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| ret = parseEntprops(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // *CRLF |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| // "END" |
| ret = parseString(offset, "END", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // ":" |
| ret = parseString(offset, ":", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // "VTODO" |
| ret = parseString(offset, "VTODO", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.endRecord(); |
| } |
| |
| // [ws] |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| // 1 * CRLF |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * entprops *CRLF entprop / entprop |
| */ |
| private int parseEntprops(int offset) { |
| int ret = 0, sum = 0; |
| if (mBuilder != null) { |
| mBuilder.startProperty(); |
| } |
| |
| ret = parseEntprop(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.endProperty(); |
| } |
| |
| for (;;) { |
| while (PARSE_ERROR != (ret = parseCrlf(offset))) { |
| offset += ret; |
| sum += ret; |
| } |
| if (mBuilder != null) { |
| mBuilder.startProperty(); |
| } |
| |
| ret = parseEntprop(offset); |
| if (PARSE_ERROR == ret) { |
| break; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.endProperty(); |
| } |
| } |
| return sum; |
| } |
| |
| /** |
| * for VEVENT,VTODO prop. entprop0 / entprop1 |
| */ |
| private int parseEntprop(int offset) { |
| int ret = 0; |
| ret = parseEntprop0(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseEntprop1(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| return PARSE_ERROR; |
| } |
| |
| /** |
| * Same with card. ";" [ws] paramlist |
| */ |
| private int parseParams(int offset) { |
| int ret = 0, sum = 0; |
| |
| ret = parseString(offset, ";", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| ret = parseParamlist(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| sum += ret; |
| |
| return sum; |
| } |
| |
| /** |
| * Same with card. paramlist [ws] ";" [ws] param / param |
| */ |
| private int parseParamlist(int offset) { |
| int ret = 0, sum = 0; |
| |
| ret = parseParam(offset); |
| if (PARSE_ERROR == ret) { |
| 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 (PARSE_ERROR == ret) { |
| return sum; |
| } |
| offsetTemp += ret; |
| sumTemp += ret; |
| |
| ret = removeWs(offsetTemp); |
| offsetTemp += ret; |
| sumTemp += ret; |
| |
| ret = parseParam(offsetTemp); |
| if (PARSE_ERROR == ret) { |
| break; |
| } |
| offsetTemp += ret; |
| sumTemp += ret; |
| |
| // offset = offsetTemp; |
| sum = sumTemp; |
| } |
| return sum; |
| } |
| |
| /** |
| * param0 - param7 / knowntype |
| */ |
| private int parseParam(int offset) { |
| int ret = 0; |
| |
| ret = parseParam0(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseParam1(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseParam2(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseParam3(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseParam4(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseParam5(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseParam6(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseParam7(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| int start = offset; |
| ret = parseKnownType(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyParamType(null); |
| mBuilder.propertyParamValue(mBuffer.substring(start, offset)); |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * simprop AND "CLASS" AND "STATUS" The value of these properties are not |
| * seperated by ";" |
| * |
| * [ws] simprop [params] ":" value CRLF |
| */ |
| private int parseEntprop0(int offset) { |
| int ret = 0, sum = 0, start = 0; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| String propName = getWord(offset).toUpperCase(); |
| if (!mEvtPropNameGroup1.contains(propName)) { |
| if (PARSE_ERROR == parseXWord(offset)) |
| return PARSE_ERROR; |
| } |
| ret = propName.length(); |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyName(propName); |
| } |
| |
| ret = parseParams(offset); |
| if (PARSE_ERROR != ret) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| ret = parseString(offset, ":", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parseValue(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| ArrayList<String> v = new ArrayList<String>(); |
| v.add(exportEntpropValue(propName, mBuffer.substring(start, |
| offset))); |
| mBuilder.propertyValues(v); |
| // Filter value,match string, REFER:RFC |
| if (PARSE_ERROR == valueFilter(propName, v)) |
| return PARSE_ERROR; |
| } |
| |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| sum += ret; |
| return sum; |
| } |
| |
| /** |
| * other event prop names except simprop AND "CLASS" AND "STATUS" The value |
| * of these properties are seperated by ";" [ws] proper name [params] ":" |
| * value CRLF |
| */ |
| private int parseEntprop1(int offset) { |
| int ret = 0, sum = 0; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| String propName = getWord(offset).toUpperCase(); |
| if (!mEvtPropNameGroup2.contains(propName)) { |
| return PARSE_ERROR; |
| } |
| ret = propName.length(); |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyName(propName); |
| } |
| |
| ret = parseParams(offset); |
| if (PARSE_ERROR != ret) { |
| offset += ret; |
| sum += ret; |
| } |
| |
| ret = parseString(offset, ":", false); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| int start = offset; |
| ret = parseValue(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| // mutil-values |
| 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 = exportEntpropValue(propName, 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); |
| // Filter value,match string, REFER:RFC |
| if (PARSE_ERROR == valueFilter(propName, v)) |
| return PARSE_ERROR; |
| } |
| |
| ret = parseCrlf(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| sum += ret; |
| return sum; |
| } |
| |
| /** |
| * "TYPE" [ws] = [ws] ptypeval |
| */ |
| private int parseParam0(int offset) { |
| int ret = 0, sum = 0, start = offset; |
| |
| ret = parseString(offset, "TYPE", true); |
| if (PARSE_ERROR == ret) { |
| 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 (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parsePtypeval(offset); |
| if (PARSE_ERROR == ret) { |
| 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; |
| boolean flag = false; |
| |
| ret = parseString(offset, "VALUE", true); |
| if (PARSE_ERROR != ret) { |
| offset += ret; |
| sum += ret; |
| flag = true; |
| } |
| if (flag == true && mBuilder != null) { |
| mBuilder.propertyParamType(mBuffer.substring(start, offset)); |
| } |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| ret = parseString(offset, "=", true); |
| if (PARSE_ERROR != ret) { |
| if (flag == false) { // "VALUE" does not exist |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| } else { |
| if (flag == true) { // "VALUE" exists |
| return PARSE_ERROR; |
| } |
| } |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parsePValueVal(offset); |
| if (PARSE_ERROR == ret) { |
| 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; |
| boolean flag = false; |
| |
| ret = parseString(offset, "ENCODING", true); |
| if (PARSE_ERROR != ret) { |
| offset += ret; |
| sum += ret; |
| flag = true; |
| } |
| if (flag == true && mBuilder != null) { |
| mBuilder.propertyParamType(mBuffer.substring(start, offset)); |
| } |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| ret = parseString(offset, "=", true); |
| if (PARSE_ERROR != ret) { |
| if (flag == false) { // "VALUE" does not exist |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| } else { |
| if (flag == true) { // "VALUE" exists |
| return PARSE_ERROR; |
| } |
| } |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parsePEncodingVal(offset); |
| if (PARSE_ERROR == ret) { |
| 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 (PARSE_ERROR == ret) { |
| 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, "=", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parseCharsetVal(offset); |
| if (PARSE_ERROR == ret) { |
| 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 (PARSE_ERROR == ret) { |
| 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, "=", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parseLangVal(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyParamValue(mBuffer.substring(start, offset)); |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * "ROLE" [ws] "=" [ws] roleval |
| */ |
| private int parseParam5(int offset) { |
| int ret = 0, sum = 0, start = offset; |
| |
| ret = parseString(offset, "ROLE", true); |
| if (PARSE_ERROR == ret) { |
| 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, "=", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parseRoleVal(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyParamValue(mBuffer.substring(start, offset)); |
| } |
| |
| return sum; |
| } |
| |
| /** |
| * "STATUS" [ws] = [ws] statuval |
| */ |
| private int parseParam6(int offset) { |
| int ret = 0, sum = 0, start = offset; |
| |
| ret = parseString(offset, "STATUS", true); |
| if (PARSE_ERROR == ret) { |
| 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, "=", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parseStatuVal(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyParamValue(mBuffer.substring(start, offset)); |
| } |
| |
| return sum; |
| |
| } |
| |
| /** |
| * XWord [ws] "=" [ws] word |
| */ |
| private int parseParam7(int offset) { |
| int ret = 0, sum = 0, start = offset; |
| |
| ret = parseXWord(offset); |
| if (PARSE_ERROR == ret) { |
| 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, "=", true); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| |
| ret = removeWs(offset); |
| offset += ret; |
| sum += ret; |
| |
| start = offset; |
| ret = parseWord(offset); |
| if (PARSE_ERROR == ret) { |
| return PARSE_ERROR; |
| } |
| offset += ret; |
| sum += ret; |
| if (mBuilder != null) { |
| mBuilder.propertyParamValue(mBuffer.substring(start, offset)); |
| } |
| |
| return sum; |
| |
| } |
| |
| /* |
| * "WAVE" / "PCM" / "VCARD" / XWORD |
| */ |
| private int parseKnownType(int offset) { |
| int ret = 0; |
| |
| ret = parseString(offset, "WAVE", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseString(offset, "PCM", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseString(offset, "VCARD", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseXWord(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| return PARSE_ERROR; |
| } |
| |
| /* |
| * knowntype / Xword |
| */ |
| private int parsePtypeval(int offset) { |
| int ret = 0; |
| |
| ret = parseKnownType(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseXWord(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| return PARSE_ERROR; |
| } |
| |
| /** |
| * "ATTENDEE" / "ORGANIZER" / "OWNER" / XWORD |
| */ |
| private int parseRoleVal(int offset) { |
| int ret = 0; |
| |
| ret = parseString(offset, "ATTENDEE", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseString(offset, "ORGANIZER", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseString(offset, "OWNER", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseXWord(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| return PARSE_ERROR; |
| } |
| |
| /** |
| * "ACCEPTED" / "NEED ACTION" / "SENT" / "TENTATIVE" / "CONFIRMED" / |
| * "DECLINED" / "COMPLETED" / "DELEGATED / XWORD |
| */ |
| private int parseStatuVal(int offset) { |
| int ret = 0; |
| |
| ret = parseString(offset, "ACCEPTED", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseString(offset, "NEED ACTION", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseString(offset, "TENTATIVE", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| ret = parseString(offset, "CONFIRMED", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| ret = parseString(offset, "DECLINED", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| ret = parseString(offset, "COMPLETED", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| ret = parseString(offset, "DELEGATED", true); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| ret = parseXWord(offset); |
| if (PARSE_ERROR != ret) { |
| return ret; |
| } |
| |
| return PARSE_ERROR; |
| } |
| |
| /** |
| * Check 4 special propName and it's value to match Hash. |
| * |
| * @return PARSE_ERROR:value not match. 1:go on,like nothing happen. |
| */ |
| private int valueFilter(String propName, ArrayList<String> values) { |
| if (propName == null || propName.equals("") || values == null |
| || values.isEmpty()) |
| return 1; // go on, like nothing happen. |
| |
| if (mSpecialValueSetMap.containsKey(propName)) { |
| for (String value : values) { |
| if (!mSpecialValueSetMap.get(propName).contains(value)) { |
| if (!value.startsWith("X-")) |
| return PARSE_ERROR; |
| } |
| } |
| } |
| |
| return 1; |
| } |
| |
| /** |
| * |
| * Translate escape characters("\\", "\;") which define in vcalendar1.0 |
| * spec. But for fault tolerance, we will translate "\:" and "\,", which |
| * isn't define in vcalendar1.0 explicitly, as the same behavior as other |
| * client. |
| * |
| * Though vcalendar1.0 spec does not defined the value of property |
| * "description", "summary", "aalarm", "dalarm", "malarm" and "palarm" could |
| * contain escape characters, we do support escape characters in these |
| * properties. |
| * |
| * @param str: |
| * the value string will be translated. |
| * @return the string which do not contain any escape character in |
| * vcalendar1.0 |
| */ |
| private String exportEntpropValue(String propName, String str) { |
| if (null == propName || null == str) |
| return null; |
| if ("".equals(propName) || "".equals(str)) |
| return ""; |
| |
| if (!mEscAllowedProps.contains(propName)) |
| return str; |
| |
| String tmp = str.replace("\\\\", "\n\r\n"); |
| tmp = tmp.replace("\\;", ";"); |
| tmp = tmp.replace("\\:", ":"); |
| tmp = tmp.replace("\\,", ","); |
| tmp = tmp.replace("\n\r\n", "\\"); |
| return tmp; |
| } |
| } |