diff options
Diffstat (limited to 'libical/src/libical/icalparser.c')
-rw-r--r-- | libical/src/libical/icalparser.c | 963 |
1 files changed, 526 insertions, 437 deletions
diff --git a/libical/src/libical/icalparser.c b/libical/src/libical/icalparser.c index b4c1822a68..8541ae4fab 100644 --- a/libical/src/libical/icalparser.c +++ b/libical/src/libical/icalparser.c @@ -16,25 +16,30 @@ the License for the specific language governing rights and limitations under the License. - The Original Code is eric. The Initial Developer of the Original - Code is + The Initial Developer of the Original Code is Eric Busboom (C) COPYRIGHT 1999 The Software Studio. http://www.softwarestudio.org ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + #include "ical.h" #include "pvl.h" #include "icalparser.h" #include "icalmemory.h" -#include <string.h> /* For strncpy */ +#include <string.h> /* For strncpy & size_t */ #include <stdio.h> /* For FILE and fgets and sprintf */ #include <stdlib.h> /* for free */ extern icalvalue* icalparser_yy_value; void set_parser_value_state(icalvalue_kind kind); -int icalparser_yyparse(void); +int ical_yy_parse(void); char* icalparser_get_next_char(char c, char *str); char* icalparser_get_next_parameter(char* line,char** end); @@ -42,7 +47,77 @@ char* icalparser_get_next_value(char* line, char **end, icalvalue_kind kind); char* icalparser_get_prop_name(char* line, char** end); char* icalparser_get_param_name(char* line, char **end); -icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind, char* str, icalproperty **error); +#define TMP_BUF_SIZE 80 + +struct icalparser_impl +{ + int buffer_full; + size_t tmp_buf_size; + char temp[TMP_BUF_SIZE]; + icalcomponent *root_component; + icalcomponent *tail; + int version; + int level; + int lineno; + icalparser_state state; + pvl_list components; + + void *line_gen_data; + +}; + + +icalparser* icalparser_new() +{ + struct icalparser_impl* impl = 0; + + if ( ( impl = (struct icalparser_impl*) + malloc(sizeof(struct icalparser_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + impl->root_component = 0; + impl->components = pvl_newlist(); + impl->level = 0; + impl->state = ICALPARSER_SUCCESS; + + impl->tmp_buf_size = TMP_BUF_SIZE; + impl->buffer_full = 0; + impl->lineno = 0; + + memset(impl->temp,0, TMP_BUF_SIZE); + + return (icalparser*)impl; +} + +void icalparser_free(icalparser* parser) +{ + struct icalparser_impl* impl = (struct icalparser_impl*)parser; + icalcomponent *c; + + if (impl->root_component != 0){ + icalcomponent_free(impl->root_component); + } + + while( (c=pvl_pop(impl->components)) != 0){ + icalcomponent_free(c); + } + + pvl_free(impl->components); +} + +void icalparser_set_gen_data(icalparser* parser, void* data) +{ + struct icalparser_impl* impl = (struct icalparser_impl*)parser; + + impl->line_gen_data = data; +} + + +icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind, + char* str, + icalproperty **error); @@ -114,7 +189,7 @@ void icalparser_clear_flex_input() /* Cal the flex parser to parse a complex value */ icalvalue* icalparser_parse_value(icalvalue_kind kind, - char* str, icalproperty** error) + char* str, icalproperty** error) { int r; input_buffer_p = input_buffer = str; @@ -122,7 +197,7 @@ icalvalue* icalparser_parse_value(icalvalue_kind kind, set_parser_value_state(kind); icalparser_yy_value = 0; - r = icalparser_yyparse(); + r = ical_yy_parse(); /* Error. Parse failed */ if( icalparser_yy_value == 0 || r != 0){ @@ -176,7 +251,7 @@ char* icalparser_get_param_name(char* line, char **end) next = icalparser_get_next_char('=',line); if (next == 0) { - return 0; + return 0; } str = make_segment(line,next); @@ -223,50 +298,50 @@ char* icalparser_get_next_value(char* line, char **end, icalvalue_kind kind) p = line; while(1){ - next = icalparser_get_next_char(',',p); + next = icalparser_get_next_char(',',p); - /* Unforunately, RFC2445 says that for the RECUR value, COMMA - can both seperate digits in a list, and it can seperate - multiple recurrence specifications. This is not a friendly - part of the spec. This weirdness tries to - distinguish the two uses. it is probably a HACK*/ + /* Unforunately, RFC2445 says that for the RECUR value, COMMA + can both seperate digits in a list, and it can seperate + multiple recurrence specifications. This is not a friendly + part of the spec. This weirdness tries to + distinguish the two uses. it is probably a HACK*/ - if( kind == ICAL_RECUR_VALUE ) { - if ( next != 0 && - (*end+length) > next+5 && - strncmp(next,"FREQ",4) == 0 - ) { - /* The COMMA was followed by 'FREQ', is it a real seperator*/ - /* Fall through */ - printf("%s\n",next); - } else if (next != 0){ - /* Not real, get the next COMMA */ - p = next+1; - next = 0; - continue; - } - } - - /* If the comma is preceeded by a '\', then it is a literal and - not a value seperator*/ + if( kind == ICAL_RECUR_VALUE ) { + if ( next != 0 && + (*end+length) > next+5 && + strncmp(next,"FREQ",4) == 0 + ) { + /* The COMMA was followed by 'FREQ', is it a real seperator*/ + /* Fall through */ + printf("%s\n",next); + } else if (next != 0){ + /* Not real, get the next COMMA */ + p = next+1; + next = 0; + continue; + } + } + + /* If the comma is preceeded by a '\', then it is a literal and + not a value seperator*/ - if ( (next!=0 && *(next-1) == '\\') || - (next!=0 && *(next-3) == '\\') - ) - /*second clause for '/' is on prev line. HACK may be out of bounds */ - { - p = next+1; - } else { - break; - } + if ( (next!=0 && *(next-1) == '\\') || + (next!=0 && *(next-3) == '\\') + ) + /*second clause for '/' is on prev line. HACK may be out of bounds */ + { + p = next+1; + } else { + break; + } } if (next == 0){ next = (char*)(size_t)line+length; - *end = next; + *end = next; } else { - *end = next+1; + *end = next+1; } if (next == line){ @@ -305,22 +380,18 @@ char* icalparser_get_next_parameter(char* line,char** end) } } -/* HACK. This is not threadsafe */ -int buffer_full=0; -size_t tmp_buf_size = 80; -char temp[80]; - - /* Get a single property line, from the property name through the final new line, and include any continuation lines */ -char* icalparser_get_line(char* (*line_gen_func)(char *s, size_t size, void *d), int *lineno) +char* icalparser_get_line(icalparser *parser, + char* (*line_gen_func)(char *s, size_t size, void *d)) { char *line; char *line_p; - size_t buf_size = tmp_buf_size; - + struct icalparser_impl* impl = (struct icalparser_impl*)parser; + size_t buf_size = impl->tmp_buf_size; + line_p = line = icalmemory_new_buffer(buf_size); line[0] = '\0'; @@ -328,43 +399,63 @@ char* icalparser_get_line(char* (*line_gen_func)(char *s, size_t size, void *d), /* The buffer is not clear, so transfer the data in it to the output. This may be left over from a previous call */ - if (temp[0] != '\0' ) { - if (temp[tmp_buf_size-1] == 0){ - buffer_full = 1; + if (impl->temp[0] != '\0' ) { + + /* If the last position in the temp buffer is occupied, + mark the buffer as full. The means we will do another + read later, because the line is not finished */ + if (impl->temp[impl->tmp_buf_size-1] == 0){ + impl->buffer_full = 1; } else { - buffer_full = 0; + impl->buffer_full = 0; } - icalmemory_append_string(&line,&line_p,&buf_size,temp); - temp[0] = '\0' ; + + /* Copy the temp to the output and clear the temp buffer. */ + icalmemory_append_string(&line,&line_p,&buf_size,impl->temp); + impl->temp[0] = '\0' ; } - temp[tmp_buf_size-1] = 1; /* Mark end of buffer */ + impl->temp[impl->tmp_buf_size-1] = 1; /* Mark end of buffer */ + + if ((*line_gen_func)(impl->temp,impl->tmp_buf_size,impl->line_gen_data) + ==0){/* Get more data */ + + /* If the first position is clear, it means we didn't get + any more data from the last call to line_ge_func*/ + if (impl->temp[0] == '\0'){ - if ((*line_gen_func)(temp,tmp_buf_size,0)==0){/* Get more data */ - if (temp[0] == '\0'){ if(line[0] != '\0'){ + /* There is data in the output, so fall trhough and process it*/ break; } else { + /* No data in output; return and signal that there + is no more input*/ free(line); return 0; } } } + + + /* If the output line ends in a '\n' and the temp buffer + begins with a ' ', then the buffer holds a continuation + line, so keep reading. */ - if ( line_p > line+1 && *(line_p-1) == '\n' && temp[0] == ' ') { - - /* If the output line ends in a '\n' and the temp buffer - begins with a ' ', then the buffer holds a continuation - line, so keep reading. */ + if ( line_p > line+1 && *(line_p-1) == '\n' && impl->temp[0] == ' ') { /* back up the pointer to erase the continuation characters */ line_p--; + if ( *(line_p-1) == '\r'){ + line_p--; + } + /* shift the temp buffer down to eliminate the leading space*/ - memmove(&(temp[0]),&(temp[1]),tmp_buf_size); - temp[tmp_buf_size-1] = temp[tmp_buf_size-2]; + memmove(&(impl->temp[0]),&(impl->temp[1]),impl->tmp_buf_size); + + impl->temp[impl->tmp_buf_size-1] = impl->temp[impl->tmp_buf_size-2]; - } else if ( buffer_full == 1 ) { + } else if ( impl->buffer_full == 1 ) { /* The buffer was filled on the last read, so read again */ @@ -377,10 +468,13 @@ char* icalparser_get_line(char* (*line_gen_func)(char *s, size_t size, void *d), } - /* Erase the final newline */ - if ( line_p > line+1 && *(line_p-1) == '\n') { - + /* Erase the final newline and/or carriage return*/ + if ( line_p > line+1 && *(line_p-1) == '\n') { *(line_p-1) = '\0'; + if ( *(line_p-2) == '\r'){ + *(line_p-2) = '\0'; + } + } else { *(line_p) = '\0'; } @@ -389,111 +483,6 @@ char* icalparser_get_line(char* (*line_gen_func)(char *s, size_t size, void *d), } -#if 0 -char* icalparser_old_get_line(char* (*line_gen_func)(char *s, size_t size, void *d), int *lineno) -{ - char *line, *output_line; - char *line_p; - char last_line = 0; - size_t buf_size = tmp_buf_size; - int break_flag = 0; - - line_p = line = icalmemory_new_buffer(buf_size); - - /* If the hold buffer is empty, read a line. Otherwise, use the data that - is still in 'temp'*/ - if (hold == 1){ - /* Do nothing */ - } else { - temp[tmp_buf_size-1] = 1; /* Mark end of buffer */ - (*line_gen_func)(temp,tmp_buf_size,0); - } - - /* Append the hold buffer or new line into the output */ - icalmemory_append_string(&line,&line_p,&buf_size,temp); - - if ( temp[tmp_buf_size-1] == 0 ) { /* Check if mark was overwritten */ - buffer_full = 1; - } else { - buffer_full = 0; - } - - /* Try to suck up any continuation lines */ - while(last_line == 0){ - - temp[tmp_buf_size-1] = 1; /* Mark end of buffer */ - if ((*line_gen_func)(temp,tmp_buf_size,0) == 0){ - /* No more lines -- we are finished */ - if (hold == 1) { - hold = 0; - break_flag = 1; - } else { - icalmemory_free_buffer(line); - return 0; - } - } else { - if ( temp[tmp_buf_size-1] == 0 ) { - buffer_full = 1; - } else { - buffer_full = 0; - } - } - - /* keep track of line numbers */ - if (lineno != 0){ - (*lineno)++; - } - - - /* Determine wether to copy the line to the output, or - save it in the hold buffer */ - - if ( line_p > line+1 && *(line_p-1) == '\n' && temp[0] == ' ') { - - /* If the last line ( in the 'line' string ) ends in a '\n' - and the current line begins with a ' ', then the current line - is a continuation line, so append it. */ - - /* back up the pointer to erase the continuation characters */ - line_p--; - icalmemory_append_string(&line,&line_p,&buf_size,&(temp[1])); - - hold = 0; - buffer_full= 0; - - } else if (buffer_full == 1) { - - /* The last line that was read filled up the read - buffer. Append it and read again */ - - icalmemory_append_string(&line,&line_p,&buf_size,temp); - - hold = 0; - - } else if (break_flag != 1 ){ - /* Nope -- the line was not a continuation line. - Save the line for the next call */ - - hold =1; - break; - } else { - break; - } - } - - /* Erase the final newline */ - if ( line_p > line+1 && *(line_p-1) == '\n') { - - *(line_p-1) = '\0'; - } - - output_line = icalmemory_tmp_copy(line); - icalmemory_free_buffer(line); - - return output_line; -} -#endif - void insert_error(icalcomponent* comp, char* text, char* message, icalparameter_xlicerrortype type) { @@ -513,389 +502,489 @@ void insert_error(icalcomponent* comp, char* text, 0)); } -icalcomponent* icalparser_parse(char* (*line_gen_func)(char *s, size_t size, void* d)) +icalcomponent* icalparser_parse(icalparser *parser, + char* (*line_gen_func)(char *s, size_t size, + void* d)) { - char *line = 0; + char* line; + icalcomponent *c=0; + icalcomponent *root_component=0; + + icalerror_check_arg_rz((parser !=0),"parser"); + + do{ + line = icalparser_get_line(parser, line_gen_func); + + if ((c = icalparser_add_line(parser,line)) != 0){ + if (root_component == 0){ + /* Just one component */ + icalparser_claim(parser); + root_component = c; + } else if(icalcomponent_isa(root_component) + != ICAL_XROOT_COMPONENT) { + /*Got a second component, so move the two components under + an XROOT container */ + icalcomponent *tempc; + tempc = icalcomponent_new(ICAL_XROOT_COMPONENT); + icalcomponent_add_component(tempc, root_component); + icalparser_claim(parser); + icalcomponent_add_component(tempc, c); + root_component = tempc; + } else { + /* Already have an XROOT container, so add the component + to it*/ + icalcomponent_add_component(root_component, c); + icalparser_claim(parser); + } + } + } while ( line != 0); + + return root_component; + +} + +icalcomponent* icalparser_add_line(icalparser* parser, + char* line) +{ char *p; char *str; char *end; - int lineno = 0; - int vcount = 0; - - icalcomponent *root_component = 0; - icalcomponent *tail = 0; icalproperty *prop; icalvalue *value; + icalvalue_kind value_kind = ICAL_NO_VALUE; - icalvalue_kind value_kind; - - pvl_list components = pvl_newlist(); - - do { - value_kind = ICAL_NO_VALUE; + struct icalparser_impl *impl = (struct icalparser_impl*)parser; + icalerror_check_arg_rz((parser != 0),"parser"); - /* Get a single property line, from a property name through a - newline */ - if (line!=0){ - free(line); - } - - line = icalparser_get_line(line_gen_func,&lineno); - if (line == 0){ - continue; - } + if (line == 0) + { + impl->state = ICALPARSER_ERROR; + return 0; + } - end = 0; + /* Begin by getting the property name at the start of the line. The + property name may end up being "BEGIN" or "END" in which case it + is not really a property, but the market for the start or end of + a component */ - str = icalparser_get_prop_name(line, &end); + end = 0; + str = icalparser_get_prop_name(line, &end); - if (str == 0){ - tail = pvl_data(pvl_tail(components)); + if (str == 0){ + /* Could not get a property name */ + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); - if (tail){ - insert_error(tail,line, - "Got a data line, but could not find a property name or component begin tag", - ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); - } - tail = 0; - continue; + if (tail){ + insert_error(tail,line, + "Got a data line, but could not find a property name or component begin tag", + ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); } + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } -/********************************************************************** - * Handle begin and end of components - **********************************************************************/ + /********************************************************************** + * Handle begin and end of components + **********************************************************************/ - /* If the property name is BEGIN or END, we are actually - starting or ending a new component */ + /* If the property name is BEGIN or END, we are actually + starting or ending a new component */ - if(strcmp(str,"BEGIN") == 0){ - icalcomponent *c; ; + if(strcmp(str,"BEGIN") == 0){ + icalcomponent *c; - str = icalparser_get_next_value(end,&end, value_kind); + impl->level++; + str = icalparser_get_next_value(end,&end, value_kind); - c = icalcomponent_new_from_string(str); + c = icalcomponent_new_from_string(str); - if (c == 0){ - c = icalcomponent_new(ICAL_XLICINVALID_COMPONENT); - insert_error(c,str,"Parse error in component name", - ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); - } + if (c == 0){ + c = icalcomponent_new(ICAL_XLICINVALID_COMPONENT); + insert_error(c,str,"Parse error in component name", + ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); + } - pvl_push(components,c); + pvl_push(impl->components,c); - continue; - } else if (strcmp(str,"END") == 0 ) { + impl->state = ICALPARSER_BEGIN_COMP; + return 0; - str = icalparser_get_next_value(end,&end, value_kind); + } else if (strcmp(str,"END") == 0 ) { + icalcomponent* tail; - root_component = pvl_pop(components); + impl->level--; + str = icalparser_get_next_value(end,&end, value_kind); - tail = pvl_data(pvl_tail(components)); + impl->root_component = pvl_pop(impl->components); - if(tail != 0){ - icalcomponent_add_component(tail,root_component); - } + tail = pvl_data(pvl_tail(impl->components)); - tail = 0; - continue; + if(tail != 0){ + icalcomponent_add_component(tail,impl->root_component); } + tail = 0; - /* There is no point in continuing if we have not seen a - component yet */ - - if(pvl_data(pvl_tail(components)) == 0){ - continue; + /* Return the component if we are back to the 0th level */ + if (impl->level == 0){ + impl->state = ICALPARSER_SUCCESS; + return impl->root_component; + } else { + impl->state = ICALPARSER_END_COMP; + return 0; } + } + + + /* There is no point in continuing if we have not seen a + component yet */ + if(pvl_data(pvl_tail(impl->components)) == 0){ + impl->state = ICALPARSER_ERROR; + return 0; + } -/********************************************************************** - * Handle property names - **********************************************************************/ - /* At this point, the property name really is a property name, - (Not a component name) so make a new property and add it to - the component */ - prop = icalproperty_new_from_string(str); + /********************************************************************** + * Handle property names + **********************************************************************/ + /* At this point, the property name really is a property name, + (Not a component name) so make a new property and add it to + the component */ - if (prop != 0){ - tail = pvl_data(pvl_tail(components)); + prop = icalproperty_new_from_string(str); - icalcomponent_add_property(tail, prop); + if (prop != 0){ + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); - /* Set the value kind for the default for this type of - property. This may be re-set by a VALUE parameter */ - value_kind = - icalenum_property_kind_to_value_kind( - icalproperty_isa(prop)); - } else { - icalcomponent* tail = pvl_data(pvl_tail(components)); + icalcomponent_add_property(tail, prop); + + /* Set the value kind for the default for this type of + property. This may be re-set by a VALUE parameter */ + value_kind = + icalenum_property_kind_to_value_kind( + icalproperty_isa(prop)); - insert_error(tail,str,"Parse error in property name", - ICAL_XLICERRORTYPE_PROPERTYPARSEERROR); + } else { + icalcomponent* tail = pvl_data(pvl_tail(impl->components)); + + insert_error(tail,str,"Parse error in property name", + ICAL_XLICERRORTYPE_PROPERTYPARSEERROR); - tail = 0; - continue; - } + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } -/********************************************************************** - * Handle parameter values - **********************************************************************/ + /********************************************************************** + * Handle parameter values + **********************************************************************/ - /* Now, add any parameters to the last property */ + /* Now, add any parameters to the last property */ - p = 0; - while(1) { + p = 0; + while(1) { - if (*(end-1) == ':'){ - /* if the last seperator was a ":" and the value is a - URL, icalparser_get_next_parameter will find the - ':' in the URL, so better break now. */ - break; - } + if (*(end-1) == ':'){ + /* if the last seperator was a ":" and the value is a + URL, icalparser_get_next_parameter will find the + ':' in the URL, so better break now. */ + break; + } - str = icalparser_get_next_parameter(end,&end); + str = icalparser_get_next_parameter(end,&end); - if (str != 0){ - char* name; - char* pvalue; - icalparameter *param = 0; - icalparameter_kind kind; - - tail = pvl_data(pvl_tail(components)); + if (str != 0){ + char* name; + char* pvalue; + + icalparameter *param = 0; + icalparameter_kind kind; + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); - name = icalparser_get_param_name(str,&pvalue); + name = icalparser_get_param_name(str,&pvalue); - if (name == 0){ - insert_error(tail, str, "Can't parse parameter name", - ICAL_XLICERRORTYPE_PARAMETERPARSEERROR); - tail = 0; - break; - } + if (name == 0){ + /* 'tail' defined above */ + insert_error(tail, str, "Can't parse parameter name", + ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR); + tail = 0; + break; + } - kind = icalenum_string_to_parameter_kind(name); - if (kind != ICAL_NO_PARAMETER){ - param = icalparameter_new_from_string(kind,pvalue); - } else { + kind = icalenum_string_to_parameter_kind(name); - /* Error. Failed to parse the parameter*/ - insert_error(tail, str, "Can't parse parameter name", - ICAL_XLICERRORTYPE_PARAMETERPARSEERROR); - tail = 0; - continue; - } + if (kind != ICAL_NO_PARAMETER){ + param = icalparameter_new_from_string(kind,pvalue); + } else { + /* Error. Failed to parse the parameter*/ + /* 'tail' defined above */ + insert_error(tail, str, "Can't parse parameter name", + ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR); + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } - if (param == 0){ - insert_error(tail,str,"Can't parse parameter value", - ICAL_XLICERRORTYPE_PARAMETERPARSEERROR); + if (param == 0){ + /* 'tail' defined above */ + insert_error(tail,str,"Can't parse parameter value", + ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR); - tail = 0; - continue; - } + tail = 0; + impl->state = ICALPARSER_ERROR; + continue; + } - /* If it is a VALUE parameter, set the kind of value*/ - if (icalparameter_isa(param)==ICAL_VALUE_PARAMETER){ + /* If it is a VALUE parameter, set the kind of value*/ + if (icalparameter_isa(param)==ICAL_VALUE_PARAMETER){ - value_kind = (icalvalue_kind) - icalparameter_get_value(param); + value_kind = (icalvalue_kind) + icalparameter_get_value(param); - if (value_kind == ICAL_NO_VALUE){ + if (value_kind == ICAL_NO_VALUE){ - /* Ooops, could not parse the value of the - parameter ( it was not one of the defined - values ), so reset the value_kind */ + /* Ooops, could not parse the value of the + parameter ( it was not one of the defined + values ), so reset the value_kind */ - icalcomponent* tail - = pvl_data(pvl_tail(components)); + insert_error( + tail, str, + "Got a VALUE parameter with an unknown type", + ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR); + icalparameter_free(param); - insert_error( - tail, str, - "Got a VALUE parameter with an unknown type", - ICAL_XLICERRORTYPE_PARAMETERPARSEERROR); - icalparameter_free(param); + value_kind = + icalenum_property_kind_to_value_kind( + icalproperty_isa(prop)); - value_kind = - icalenum_property_kind_to_value_kind( - icalproperty_isa(prop)); - - icalparameter_free(param); - tail = 0; - continue; - } - } + icalparameter_free(param); + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } + } - /* Everything is OK, so add the parameter */ - icalproperty_add_parameter(prop,param); - tail = 0; + /* Everything is OK, so add the parameter */ + icalproperty_add_parameter(prop,param); + tail = 0; - } else { - /* If we did not get a param string, go on to looking - for a value */ - break; - } - } + } else { /* if ( str != 0) */ + /* If we did not get a param string, go on to looking + for a value */ + break; + } /* if ( str != 0) */ + + } /* while(1) */ -/********************************************************************** - * Handle values - **********************************************************************/ + /********************************************************************** + * Handle values + **********************************************************************/ - /* Look for values. If there are ',' characters in the values, - then there are multiple values, so clone the current - parameter and add one part of the value to each clone */ + /* Look for values. If there are ',' characters in the values, + then there are multiple values, so clone the current + parameter and add one part of the value to each clone */ - vcount=0; - while(1) { - str = icalparser_get_next_value(end,&end, value_kind); + vcount=0; + while(1) { + str = icalparser_get_next_value(end,&end, value_kind); - if (str != 0){ + if (str != 0){ - if (vcount > 0){ - /* Actually, only clone after the second value */ - icalproperty* clone = icalproperty_new_clone(prop); - tail = pvl_data(pvl_tail(components)); + if (vcount > 0){ + /* Actually, only clone after the second value */ + icalproperty* clone = icalproperty_new_clone(prop); + icalcomponent* tail = pvl_data(pvl_tail(impl->components)); - icalcomponent_add_property(tail, clone); - prop = clone; - tail = 0; - } + icalcomponent_add_property(tail, clone); + prop = clone; + tail = 0; + } - value = icalvalue_new_from_string(value_kind, str); + value = icalvalue_new_from_string(value_kind, str); - /* Don't add properties without value */ - if (value == 0){ - char temp[1024]; + /* Don't add properties without value */ + if (value == 0){ + char temp[200]; /* HACK */ - icalproperty_kind prop_kind = icalproperty_isa(prop); - tail = pvl_data(pvl_tail(components)); + icalproperty_kind prop_kind = icalproperty_isa(prop); + icalcomponent* tail = pvl_data(pvl_tail(impl->components)); - sprintf(temp,"Can't parse as %s value in %s property. Removing entire property", - icalenum_value_kind_to_string(value_kind), - icalenum_property_kind_to_string(prop_kind)); + sprintf(temp,"Can't parse as %s value in %s property. Removing entire property", + icalenum_value_kind_to_string(value_kind), + icalenum_property_kind_to_string(prop_kind)); - insert_error(tail, str, temp, - ICAL_XLICERRORTYPE_VALUEPARSEERROR); + insert_error(tail, str, temp, + ICAL_XLICERRORTYPE_VALUEPARSEERROR); - /* Remove the troublesome property */ - icalcomponent_remove_property(tail,prop); - icalproperty_free(prop); - prop = 0; - tail = 0; - break; + /* Remove the troublesome property */ + icalcomponent_remove_property(tail,prop); + icalproperty_free(prop); + prop = 0; + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; - } else { - vcount++; - icalproperty_set_value(prop, value); - } + } else { + vcount++; + icalproperty_set_value(prop, value); + } - } else { + } else { + if (vcount == 0){ + char temp[200]; /* HACK */ + icalproperty_kind prop_kind = icalproperty_isa(prop); + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); + + sprintf(temp,"No value for %s property. Removing entire property", + icalenum_property_kind_to_string(prop_kind)); + + insert_error(tail, str, temp, + ICAL_XLICERRORTYPE_VALUEPARSEERROR); + + /* Remove the troublesome property */ + icalcomponent_remove_property(tail,prop); + icalproperty_free(prop); + prop = 0; + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } else { + break; } } + } - } while( !feof(stdin) && line !=0 ); + /**************************************************************** + * End of component parsing. + *****************************************************************/ - - if (pvl_data(pvl_tail(components)) == 0){ - /* A nice, clean exit */ - pvl_free(components); - free(line); - return root_component; + if (pvl_data(pvl_tail(impl->components)) == 0 && + impl->level == 0){ + impl->state = ICALPARSER_SUCCESS; + return impl->root_component; + } else { + impl->state = ICALPARSER_IN_PROGRESS; + return 0; } - /* Clear off any component that may be left in the list */ - /* This will happen if some components did not have an "END" tag*/ +} + +icalparser_state icalparser_get_state(icalparser* parser) +{ + struct icalparser_impl* impl = (struct icalparser_impl*) parser; + return impl->state; + +} + +icalcomponent* icalparser_claim(icalparser* parser) +{ + struct icalparser_impl* impl = (struct icalparser_impl*) parser; + icalcomponent *c = impl->root_component; + + impl->root_component = 0; + + return c; + +} + + +icalcomponent* icalparser_clean(icalparser* parser) +{ + struct icalparser_impl* impl = (struct icalparser_impl*) parser; + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); - while((tail=pvl_data(pvl_tail(components))) != 0){ + icalerror_check_arg_rz((parser != 0 ),"parser"); + + /* We won't get a clean exit if some components did not have an + "END" tag. Clear off any component that may be left in the list */ + + + while((tail=pvl_data(pvl_tail(impl->components))) != 0){ insert_error(tail," ", "Missing END tag for this component. Closing component at end of input.", ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); - root_component = pvl_pop(components); - tail=pvl_data(pvl_tail(components)); + impl->root_component = pvl_pop(impl->components); + tail=pvl_data(pvl_tail(impl->components)); if(tail != 0){ - icalcomponent_add_component(tail,root_component); + icalcomponent_add_component(tail,impl->root_component); } } - free(line); - return root_component; + return impl->root_component; + } -char* string_line_generator_pos=0; -char* string_line_generator_str; +struct slg_data { + char* pos; + char* str; +}; + char* string_line_generator(char *out, size_t buf_size, void *d) { char *n; - - if(string_line_generator_pos==0){ - string_line_generator_pos=string_line_generator_str; + size_t size; + struct slg_data* data = (struct slg_data*)d; + + if(data->pos==0){ + data->pos=data->str; } /* If the pointer is at the end of the string, we are done */ - if (*string_line_generator_pos ==0){ + if (*(data->pos)==0){ return 0; } - n = strchr(string_line_generator_pos,'\n'); + n = strchr(data->pos,'\n'); - /* If no newline, take the rest of the string, and leave the - pointer at the \0 */ - - if (n == 0) { - n = string_line_generator_pos + strlen(string_line_generator_pos); + if (n == 0){ + size = strlen(data->pos); } else { - n++; + n++; /* include newline in output */ + size = (n-data->pos); } - strncpy(out,string_line_generator_pos,(n-string_line_generator_pos)); - - *(out+(n-string_line_generator_pos)) = '\0'; - - string_line_generator_pos = n; - - return out; + if (size > buf_size-1){ + size = buf_size-1; + } -} -void _test_string_line_generator(char* str) -{ - char *line; - int lineno=0; - string_line_generator_str = str; - string_line_generator_pos = 0; - - while((line = icalparser_get_line(string_line_generator,&lineno))){ - printf("#%d: %s\n",lineno,line); - } + strncpy(out,data->pos,size); + *(out+size) = '\0'; - string_line_generator_pos = 0; - string_line_generator_str = 0; -} - + data->pos += size; + return out; +} icalcomponent* icalparser_parse_string(char* str) { - icalcomponent *c; - - string_line_generator_str = str; - string_line_generator_pos = 0; - c = icalparser_parse(string_line_generator); - string_line_generator_pos = 0; - string_line_generator_str = 0; - + struct slg_data d; + icalparser *p; + + d.pos = 0; + d.str = str; + + p = icalparser_new(); + icalparser_set_gen_data(p,&d); + c = icalparser_parse(p,string_line_generator); + icalparser_free(p); + return c; } |