bump to 1.0.0 and clean up spec file
[platform/upstream/libical.git] / src / libical / icalparser.c
index 04ce463..43ea903 100644 (file)
@@ -77,7 +77,7 @@ 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
 
@@ -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;
     }
@@ -283,7 +282,9 @@ char* parser_get_param_name(char* line, char **end, char **buf)
                    return 0;
            }
 
-           *buf = *end = make_segment(*end,next);
+        *end = make_segment(*end,next);
+    } else {
+        *end = make_segment(*end, *end + strlen(*end));
     }
 
     return str;
@@ -337,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);
 
@@ -878,13 +885,12 @@ 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 */
@@ -902,8 +908,6 @@ icalcomponent* icalparser_add_line(icalparser* parser,
                 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();
@@ -915,22 +919,54 @@ icalcomponent* icalparser_add_line(icalparser* parser,
                 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
@@ -938,11 +974,10 @@ icalcomponent* icalparser_add_line(icalparser* parser,
                                     ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR);
                        tail = 0;
                        parser->state = ICALPARSER_ERROR;
-                       /* if (pvalue) {
+                       if (pvalue) {
                               free(pvalue);
                               pvalue = 0;
-                          }
-                       */
+            }
                    if (name) {
                            free(name);
                            name = 0;
@@ -961,11 +996,11 @@ icalcomponent* icalparser_add_line(icalparser* parser,
 #endif
            }
 
-           /* if (pvalue) {
-                      free(pvalue);
-                      pvalue = 0;
-              }
-               */
+           if (pvalue) {
+                  free(pvalue);
+                  pvalue = 0;
+           }
+               
            if (name) {
                    free(name);
                    name = 0;
@@ -979,8 +1014,6 @@ icalcomponent* icalparser_add_line(icalparser* parser,
                    tail = 0;
                    parser->state = ICALPARSER_ERROR;
                
-                       icalmemory_free_buffer(buf_value);
-                       buf_value = NULL;
                        icalmemory_free_buffer(name);
                        name = NULL;
                        icalmemory_free_buffer(str);
@@ -1136,7 +1169,12 @@ icalcomponent* icalparser_add_line(icalparser* parser,
 
        } 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){