static char* parser_get_next_parameter(char* line,char** end);
static char* parser_get_next_value(char* line, char **end, icalvalue_kind kind);
static char* parser_get_prop_name(char* line, char** end);
-static char* parser_get_param_name(char* line, char **end, char **buf_value);
+static char* parser_get_param_name(char* line, char **end);
#define TMP_BUF_SIZE 80
}
static
-char* parser_get_param_name(char* line, char **end, char **buf)
+char* parser_get_param_name(char* line, char **end)
{
char* next;
char *str;
next = parser_get_next_char('=',line,1);
- *buf = 0;
if (next == 0) {
return 0;
}
return 0;
}
- *buf = *end = make_segment(*end,next);
+ *end = make_segment(*end,next);
+ } else {
+ *end = make_segment(*end, *end + strlen(*end));
}
return str;
char* parser_get_next_value(char* line, char **end, icalvalue_kind kind)
{
- char* next;
+ char* next = 0;
char *p;
char *str;
size_t length = strlen(line);
+ int quoted = 0;
+
+ if( line[0] == '\"' && line[length - 1] == '\"' ) {
+ /* This line is quoted, don't split into multiple values */
+ quoted = 1;
+ }
p = line;
- while(1){
+ while(!quoted){
next = parser_get_next_char(',',p,1);
if (str != 0){
char* name = 0;
char* pvalue = 0;
- char *buf_value = NULL;
icalparameter *param = 0;
icalparameter_kind kind;
icalcomponent *tail = pvl_data(pvl_tail(parser->components));
- name = parser_get_param_name(str,&pvalue,&buf_value);
+ name = parser_get_param_name(str,&pvalue);
if (name == 0){
/* 'tail' defined above */
icalparameter_set_xname(param,name);
icalparameter_set_xvalue(param,pvalue);
}
- icalmemory_free_buffer(buf_value);
- buf_value = NULL;
} else if (kind == ICAL_IANA_PARAMETER){
ical_unknown_token_handling tokHandlingSetting =
ical_get_unknown_token_handling_setting();
icalparameter_set_xname(param,name);
icalparameter_set_xvalue(param,pvalue);
}
- icalmemory_free_buffer(buf_value);
- buf_value = NULL;
-
- } else if (kind != ICAL_NO_PARAMETER){
+ } else if (kind == ICAL_TZID_PARAMETER){
+ /*
+ Special case handling for TZID to workaround invalid incoming data.
+ For example, Google Calendar will send back stuff like this:
+ DTSTART;TZID=GMT+05:30:20120904T020000
+
+ In this case we read to the last colon rather than the first colon.
+ This way the TZID will become GMT+05:30 rather than trying to parse
+ the date-time as 30:20120904T020000.
+ */
+ char *lastColon = 0;
+ char *nextColon = end;
+
+ /* Find the last colon in the line */
+ do {
+ nextColon = parser_get_next_char(':', nextColon, 1);
+
+ if (nextColon) {
+ lastColon = nextColon;
+ }
+ } while (nextColon);
+
+ /*
+ Rebuild str so that it includes everything up to the last colon.
+ So given the above example, str will go from
+ "TZID=GMT+05" to "TZID=GMT+05:30"
+ */
+ if (lastColon && *(lastColon + 1) != 0) {
+ char *strStart = line + sizeof(str);
+
+ end = lastColon + 1;
+
+ icalmemory_free_buffer(str);
+ str = make_segment(strStart, end - 1);
+ }
+
+ icalmemory_free_buffer(name);
+ icalmemory_free_buffer(pvalue);
+
+ /* Reparse the parameter name and value with the new segment */
+ name = parser_get_param_name(str,&pvalue);
+ param = icalparameter_new_from_value_string(kind,pvalue);
+ } else if (kind != ICAL_NO_PARAMETER){
param = icalparameter_new_from_value_string(kind,pvalue);
-
- icalmemory_free_buffer(buf_value);
- buf_value = NULL;
-
} else {
/* Error. Failed to parse the parameter*/
/* 'tail' defined above */
- icalmemory_free_buffer(buf_value);
- buf_value = NULL;
-
/* Change for mozilla */
/* have the option of being flexible towards unsupported parameters */
#if ICAL_ERRORS_ARE_FATAL == 1
ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR);
tail = 0;
parser->state = ICALPARSER_ERROR;
- /* if (pvalue) {
+ if (pvalue) {
free(pvalue);
pvalue = 0;
- }
- */
+ }
if (name) {
free(name);
name = 0;
#endif
}
- /* if (pvalue) {
- free(pvalue);
- pvalue = 0;
- }
- */
+ if (pvalue) {
+ free(pvalue);
+ pvalue = 0;
+ }
+
if (name) {
free(name);
name = 0;
tail = 0;
parser->state = ICALPARSER_ERROR;
- icalmemory_free_buffer(buf_value);
- buf_value = NULL;
icalmemory_free_buffer(name);
name = NULL;
icalmemory_free_buffer(str);
} else {
#if ICAL_ALLOW_EMPTY_PROPERTIES
- /* Don't replace empty properties with an error */
+ /* Don't replace empty properties with an error.
+ Set an empty length string (not null) as the value instead */
+ if (vcount == 0) {
+ icalproperty_set_value(prop, icalvalue_new_text(""));
+ }
+
break;
#else
if (vcount == 0){