summaryrefslogtreecommitdiff
path: root/src/libical/icalparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libical/icalparser.c')
-rw-r--r--src/libical/icalparser.c234
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
}
}