diff options
Diffstat (limited to 'src/libical/icalparser.c')
-rw-r--r-- | src/libical/icalparser.c | 234 |
1 files changed, 152 insertions, 82 deletions
diff --git a/src/libical/icalparser.c b/src/libical/icalparser.c index 1c62dd0..43ea903 100644 --- a/src/libical/icalparser.c +++ b/src/libical/icalparser.c @@ -68,16 +68,16 @@ # endif #endif -#ifdef WIN32 -#define snprintf _snprintf -#define strcasecmp stricmp +#if defined(_MSC_VER) +#define snprintf _snprintf +#define strcasecmp stricmp #endif static char* parser_get_next_char(char c, char *str, int qm); 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 @@ -115,14 +115,14 @@ void strstriplt(char *buf) return; } len = strlen(buf); - while ((buf[0] != 0) && (isspace(buf[len - 1]))) { + while ((buf[0] != 0) && (isspace((unsigned char)buf[len - 1]))) { buf[--len] = 0; } if (buf[0] == 0) { return; } a = 0; - while ((buf[0]!=0) && (isspace(buf[a]))) { + while ((buf[0]!=0) && (isspace((unsigned char)buf[a]))) { a++; } if (a > 0) { @@ -192,18 +192,18 @@ char* parser_get_next_char(char c, char *str, int qm) for(p=str; *p!=0; p++){ if (qm == 1) { - if ( quote_mode == 0 && *p=='"' && *(p-1) != '\\' ){ + if ( quote_mode == 0 && *p=='"' && p>str && *(p-1) != '\\' ){ quote_mode =1; continue; } - if ( quote_mode == 1 && *p=='"' && *(p-1) != '\\' ){ + if ( quote_mode == 1 && *p=='"' && p>str && *(p-1) != '\\' ){ quote_mode =0; continue; } } - if (quote_mode == 0 && *p== c && *(p-1) != '\\' ){ + if (quote_mode == 0 && *p== c && p>str && *(p-1) != '\\' ){ return p; } @@ -261,14 +261,13 @@ char* parser_get_prop_name(char* line, char** end) } 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; } @@ -279,10 +278,13 @@ char* parser_get_param_name(char* line, char **end, char **buf) *end = *end+1; next = parser_get_next_char('"',*end,0); if (next == 0) { + free(str); return 0; } - *buf = *end = make_segment(*end,next); + *end = make_segment(*end,next); + } else { + *end = make_segment(*end, *end + strlen(*end)); } return str; @@ -336,13 +338,19 @@ static 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); @@ -877,90 +885,141 @@ icalcomponent* icalparser_add_line(icalparser* parser, 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 */ - insert_error(tail, str, "Cant parse parameter name", - ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR); - tail = 0; - break; + /* 'tail' defined above */ + insert_error(tail, str, "Cant parse parameter name", + ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR); + tail = 0; + break; } kind = icalparameter_string_to_kind(name); if(kind == ICAL_X_PARAMETER){ param = icalparameter_new(ICAL_X_PARAMETER); - - if(param != 0){ - icalparameter_set_xname(param,name); - icalparameter_set_xvalue(param,pvalue); - } - icalmemory_free_buffer(buf_value); - buf_value = NULL; - - } 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 */ - - /* Change for mozilla */ - /* have the option of being flexible towards unsupported parameters */ - #ifndef ICAL_ERRORS_ARE_FATAL + if(param != 0){ + icalparameter_set_xname(param,name); + icalparameter_set_xvalue(param,pvalue); + } + } else if (kind == ICAL_IANA_PARAMETER){ + ical_unknown_token_handling tokHandlingSetting = + ical_get_unknown_token_handling_setting(); + if (tokHandlingSetting == ICAL_DISCARD_TOKEN) continue; - #endif - - insert_error(tail, str, "Cant parse parameter name", - ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR); - tail = 0; - parser->state = ICALPARSER_ERROR; - /* if (pvalue) { - free(pvalue); - pvalue = 0; - } */ - if (name) { - free(name); - name = 0; - } - return 0; + param = icalparameter_new(ICAL_IANA_PARAMETER); + + if(param != 0){ + icalparameter_set_xname(param,name); + icalparameter_set_xvalue(param,pvalue); + } + } 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); + } else { + /* Error. Failed to parse the parameter*/ + /* 'tail' defined above */ + + /* Change for mozilla */ + /* have the option of being flexible towards unsupported parameters */ +#if ICAL_ERRORS_ARE_FATAL == 1 + insert_error(tail, str, "Cant parse parameter name", + ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR); + tail = 0; + parser->state = ICALPARSER_ERROR; + if (pvalue) { + free(pvalue); + pvalue = 0; + } + if (name) { + free(name); + name = 0; + } + icalmemory_free_buffer(str); + str = NULL; + return 0; +#else + if (name) { + free(name); + name = 0; + } + icalmemory_free_buffer(str); + str = NULL; + continue; +#endif } - /* if (pvalue) { - free(pvalue); - pvalue = 0; - } */ + if (pvalue) { + free(pvalue); + pvalue = 0; + } + if (name) { - free(name); - name = 0; + free(name); + name = 0; } if (param == 0){ - /* 'tail' defined above */ - insert_error(tail,str,"Cant parse parameter value", - ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR); + /* 'tail' defined above */ + insert_error(tail,str,"Cant parse parameter value", + ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR); - tail = 0; - parser->state = ICALPARSER_ERROR; + tail = 0; + parser->state = ICALPARSER_ERROR; - icalmemory_free_buffer(buf_value); - buf_value = NULL; - icalmemory_free_buffer(name); - name = NULL; - icalmemory_free_buffer(str); - str = NULL; + icalmemory_free_buffer(name); + name = NULL; + icalmemory_free_buffer(str); + str = NULL; - continue; + continue; } /* If it is a VALUE parameter, set the kind of value*/ @@ -981,7 +1040,6 @@ icalcomponent* icalparser_add_line(icalparser* parser, tail, str, "Got a VALUE parameter with an unknown type", ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR); - icalparameter_free(param); value_kind = icalproperty_kind_to_value_kind( @@ -1067,7 +1125,14 @@ icalcomponent* icalparser_add_line(icalparser* parser, prop = clone; tail = 0; } - + + /* If this is a URI value for an ATTACH property, then change + the value to an ATTACH kind as well. + Now we can support ATTACH;TYPE=URI:http://my.fav.url + */ + if(value_kind == ICAL_URI_VALUE && prop_kind == ICAL_ATTACH_PROPERTY){ + value_kind = ICAL_ATTACH_VALUE; + } value = icalvalue_new_from_string(value_kind, str); /* Don't add properties without value */ @@ -1103,11 +1168,15 @@ icalcomponent* icalparser_add_line(icalparser* parser, str = NULL; } else { - if (str != NULL) { - icalmemory_free_buffer(str); - str = NULL; - } - +#if ICAL_ALLOW_EMPTY_PROPERTIES + /* 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){ char temp[200]; /* HACK */ @@ -1131,6 +1200,7 @@ icalcomponent* icalparser_add_line(icalparser* parser, break; } +#endif } } |