Index: design-data/parameters.csv =================================================================== --- design-data/parameters.csv (revision 976) +++ design-data/parameters.csv (working copy) @@ -1,34 +1,39 @@ -"#Name ","C Type","Enumeration Values" -"ALTREP","const char*", -"CHARSET","const char*", -"CN","const char*", -"CUTYPE","icalparameter_cutype","INDIVIDUAL;GROUP;RESOURCE;ROOM;UNKNOWN" -"DELEGATED-FROM","const char*", -"DELEGATED-TO","const char*", -"DIR","const char*", -"ENCODING","icalparameter_encoding","8BIT;BASE64" -"FBTYPE","icalparameter_fbtype","FREE;BUSY;BUSY-UNAVAILABLE;BUSY-TENTATIVE" -"FMTTYPE","const char*", -"LANGUAGE","const char*", -"MEMBER","const char*", -"PARTSTAT","icalparameter_partstat","NEEDS-ACTION;ACCEPTED;DECLINED;TENTATIVE;DELEGATED;COMPLETED;INPROCESS" -"RANGE","icalparameter_range","THISANDPRIOR;THISANDFUTURE" -"RELATED","icalparameter_related","START;END" -"RELTYPE","icalparameter_reltype","PARENT;CHILD;SIBLING" -"ROLE","icalparameter_role","CHAIR;REQ-PARTICIPANT;OPT-PARTICIPANT;NON-PARTICIPANT" -"RSVP","icalparameter_rsvp","TRUE;FALSE" -"SENT-BY","const char*", -"TZID","const char*", -"VALUE","icalparameter_value","BINARY;BOOLEAN;DATE;DURATION;FLOAT;INTEGER;PERIOD;RECUR;TEXT;URI;ERROR;DATE-TIME;UTC-OFFSET;CAL-ADDRESS" -"X","const char*", -"X-LIC-ERRORTYPE","icalparameter_xlicerrortype","COMPONENT-PARSE-ERROR;PROPERTY-PARSE-ERROR;PARAMETER-NAME-PARSE-ERROR;PARAMETER-VALUE-PARSE-ERROR;VALUE-PARSE-ERROR;INVALID-ITIP;UNKNOWN-VCAL-PROP-ERROR;MIME-PARSE-ERROR;VCAL-PROP-PARSE-ERROR" -"X-LIC-COMPARETYPE","icalparameter_xliccomparetype","EQUAL;NOTEQUAL;LESS;GREATER;LESSEQUAL;GREATEREQUAL;REGEX;ISNULL;ISNOTNULL" +"#Name ","C icalparameter_kind Enum","C Type","Enumeration Values" +"ALTREP","2","const char*", +"CHARSET","3","const char*", +"CN","4","const char*", +"CUTYPE","5","icalparameter_cutype","INDIVIDUAL;GROUP;RESOURCE;ROOM;UNKNOWN" +"DELEGATED-FROM","6","const char*", +"DELEGATED-TO","7","const char*", +"DIR","8","const char*", +"ENCODING","10","icalparameter_encoding","8BIT;BASE64" +"FBTYPE","11","icalparameter_fbtype","FREE;BUSY;BUSY-UNAVAILABLE;BUSY-TENTATIVE" +"FMTTYPE","12","const char*", +"LANGUAGE","14","const char*", +"MEMBER","18","const char*", +"PARTSTAT","20","icalparameter_partstat","NEEDS-ACTION;ACCEPTED;DECLINED;TENTATIVE;DELEGATED;COMPLETED;INPROCESS" +"RANGE","21","icalparameter_range","THISANDPRIOR;THISANDFUTURE" +"RELATED","22","icalparameter_related","START;END" +"RELTYPE","23","icalparameter_reltype","PARENT;CHILD;SIBLING" +"ROLE","24","icalparameter_role","CHAIR;REQ-PARTICIPANT;OPT-PARTICIPANT;NON-PARTICIPANT" +"RSVP","25","icalparameter_rsvp","TRUE;FALSE" +"SENT-BY","26","const char*", +"TZID","27","const char*", +"VALUE","28","icalparameter_value","BINARY;BOOLEAN;DATE;DURATION;FLOAT;INTEGER;PERIOD;RECUR;TEXT;URI;ERROR;DATE-TIME;UTC-OFFSET;CAL-ADDRESS" +"X","29","const char*", +"X-LIC-ERRORTYPE","31","icalparameter_xlicerrortype","COMPONENT-PARSE-ERROR;PROPERTY-PARSE-ERROR;PARAMETER-NAME-PARSE-ERROR;PARAMETER-VALUE-PARSE-ERROR;VALUE-PARSE-ERROR;INVALID-ITIP;UNKNOWN-VCAL-PROP-ERROR;MIME-PARSE-ERROR;VCAL-PROP-PARSE-ERROR" +"X-LIC-COMPARETYPE","30","icalparameter_xliccomparetype","EQUAL;NOTEQUAL;LESS;GREATER;LESSEQUAL;GREATEREQUAL;REGEX;ISNULL;ISNOTNULL" "#CAP Parameters","Draft 8", "#this parameter should really be called ACTION, but this conflicts with the ACTION property" -"ACTIONPARAM","icalparameter_action","ASK;ABORT" -"ID","const char*", -"ENABLE","icalparameter_enable","TRUE;FALSE" -"LATENCY","const char*", -"LOCAL","icalparameter_local","TRUE;FALSE" -"LOCALIZE","const char*", -"OPTIONS","const char*", +"ACTIONPARAM","1","icalparameter_action","ASK;ABORT" +"ID","13","const char*", +"ENABLE","9","icalparameter_enable","TRUE;FALSE" +"LATENCY","15","const char*", +"LOCAL","16","icalparameter_local","TRUE;FALSE" +"LOCALIZE","17","const char*", +"OPTIONS","19","const char*", +"NO","32",, +"#In practice any unknown paramater that is not an xparam is treated as an ianaparam" +"IANA","33","const char*", +"ANY","0",, +"#NOTE for updaters. Preserve the icalparameter_kind Enum values to aid forward compatibility" Index: scripts/readvaluesfile.pl =================================================================== --- scripts/readvaluesfile.pl (revision 976) +++ scripts/readvaluesfile.pl (working copy) @@ -110,8 +110,9 @@ my $parameter_name = $column[0]; - my $data_type = $column[1]; - my $enum_string = $column[2]; + my $enumConst = $column[1]; + my $data_type = $column[2]; + my $enum_string = $column[3]; my @enums; if($enum_string){ @@ -119,6 +120,7 @@ } $h{$parameter_name} = { C => $data_type, + kindEnum => $enumConst, enums => [@enums] }; } Index: scripts/mkderivedparameters.pl =================================================================== --- scripts/mkderivedparameters.pl (revision 976) +++ scripts/mkderivedparameters.pl (working copy) @@ -19,19 +19,25 @@ while(){ if (//){ + $autogenMsg = "of section of machine generated code (mkderivedparameters.pl). Do not edit."; + if($opt_p){ + $startComment = "#"; + $endComment = ""; + } else { + $startComment = "/*"; + $endComment = " */"; + } + print $startComment." START ".$autogenMsg.$endComment."\n\n"; + insert_code(); + + print $startComment." END ".$autogenMsg.$endComment."\n\n"; } else { print; } } - if($opt_p){ - print "# Everything below this line is machine generated. Do not edit. \n"; - } else { - print "/* Everything below this line is machine generated. Do not edit. */\n"; - } - } sub insert_code @@ -40,7 +46,9 @@ # Write parameter enumerations and datatypes if($opt_h){ - print "typedef enum icalparameter_kind {\n ICAL_ANY_PARAMETER = 0,\n"; + my $enumConst = $params{'ANY'}->{"kindEnum"}; + print "typedef enum icalparameter_kind {\n ICAL_ANY_PARAMETER = ".$enumConst.",\n"; + $enumVal = 1; foreach $param (sort keys %params) { next if !$param; @@ -49,12 +57,13 @@ my $uc = join("",map {uc($_);} split(/-/,$param)); - my @enums = @{$params{$param}->{'enums'}}; + $enumConst = $params{$param}->{"kindEnum"}; - print " ICAL_${uc}_PARAMETER, \n"; + print " ICAL_${uc}_PARAMETER = ".$enumConst.", \n"; } - print " ICAL_NO_PARAMETER\n} icalparameter_kind;\n\n"; + $enumConst = $params{'NO'}->{"kindEnum"}; + print " ICAL_NO_PARAMETER = ".$enumConst."\n} icalparameter_kind;\n\n"; # Now create enumerations for parameter values $idx = 20000; @@ -65,7 +74,7 @@ next if !$param; - next if $param eq 'NO' or $prop eq 'ANY'; + next if $param eq 'NO' or $param eq 'ANY'; my $type = $params{$param}->{"C"}; my $ucv = join("",map {uc(lc($_));} split(/-/,$param)); @@ -131,7 +140,7 @@ next if !$param; - next if $param eq 'NO' or $prop eq 'ANY'; + next if $param eq 'NO' or $param eq 'ANY'; my $lc = join("",map {lc($_);} split(/-/,$param)); my $uc = join("",map {uc(lc($_));} split(/-/,$param)); @@ -152,7 +161,7 @@ next if !$param; - next if $param eq 'NO' or $prop eq 'ANY'; + next if $param eq 'NO' or $param eq 'ANY'; my $type = $params{$param}->{"C"}; my $uc = join("",map {uc(lc($_));} split(/-/,$param)); @@ -178,8 +187,10 @@ } -foreach $param (keys %params){ +foreach $param (sort keys %params){ + next if $param eq 'NO' or $param eq 'ANY'; + my $type = $params{$param}->{'C'}; my $ucf = join("",map {ucfirst(lc($_));} split(/-/,$param)); Index: src/libical/icaltypes.h =================================================================== --- src/libical/icaltypes.h (revision 976) +++ src/libical/icaltypes.h (working copy) @@ -105,5 +105,18 @@ void icaltimezonetype_free(struct icaltimezonetype tzt); +/* ical_unknown_token_handling : + * How should the ICAL library handle components, properties and parameters with + * unknown names? + * FIXME: Currently only affects parameters. Extend to components and properties. + */ +typedef enum ical_unknown_token_handling { + ICAL_ASSUME_IANA_TOKEN = 1, + ICAL_DISCARD_TOKEN = 2, + ICAL_TREAT_AS_ERROR = 3 +} ical_unknown_token_handling; +ical_unknown_token_handling ical_get_unknown_token_handling_setting(void); +void ical_set_unknown_token_handling_setting(ical_unknown_token_handling newSetting); + #endif /* !ICALTYPES_H */ Index: src/libical/icalparameter.c =================================================================== --- src/libical/icalparameter.c (revision 976) +++ src/libical/icalparameter.c (working copy) @@ -184,6 +184,8 @@ if(kind == ICAL_X_PARAMETER){ icalparameter_set_xname(param,cpy); + } else if(kind == ICAL_IANA_PARAMETER) { + icalparameter_set_iana_name(param, cpy); } free(cpy); @@ -231,10 +233,11 @@ buf_ptr = buf; if(param->kind == ICAL_X_PARAMETER) { - - icalmemory_append_string(&buf, &buf_ptr, &buf_size, - icalparameter_get_xname(param)); - + icalmemory_append_string(&buf, &buf_ptr, &buf_size, + icalparameter_get_xname(param)); + } else if (param->kind == ICAL_IANA_PARAMETER) { + icalmemory_append_string(&buf, &buf_ptr, &buf_size, + icalparameter_get_iana_name(param)); } else { kind_string = icalparameter_kind_to_string(param->kind); @@ -365,6 +368,26 @@ return param->string; } +void icalparameter_set_iana_value (icalparameter* param, const char* v) +{ + icalparameter_set_xvalue(param, v); +} + +const char* icalparameter_get_iana_value(icalparameter* param) +{ + return icalparameter_get_xvalue(param); +} + +void icalparameter_set_iana_name (icalparameter* param, const char* v) +{ + icalparameter_set_xname(param, v); +} + +const char* icalparameter_get_iana_name (icalparameter* param) +{ + return icalparameter_get_xname(param); +} + void icalparameter_set_parent(icalparameter* param, icalproperty* property) { @@ -380,6 +403,36 @@ return param->parent; } +/* returns 1 if parameters have same name in ICAL, otherwise 0 */ +int icalparameter_has_same_name(icalparameter* param1, icalparameter* param2) +{ + icalparameter_kind kind1; + icalparameter_kind kind2; + const char *name1; + const char *name2; + icalerror_check_arg_rz( (param1!=0),"param1"); + icalerror_check_arg_rz( (param2!=0),"param2"); + + kind1 = icalparameter_isa(param1); + kind2 = icalparameter_isa(param2); + + if (kind1 != kind2) + return 0; + + if (kind1 == ICAL_X_PARAMETER) { + name1 = icalparameter_get_xname(param1); + name2 = icalparameter_get_xname(param2); + if (strcasecmp(name1, name2) != 0) + return 0; + } else if (kind1 == ICAL_IANA_PARAMETER) { + name1 = icalparameter_get_iana_name(param1); + name2 = icalparameter_get_iana_name(param2); + if (strcasecmp(name1, name2) != 0) + return 0; + } + return 1; +} + /* Everything below this line is machine generated. Do not edit. */ /* ALTREP */ Index: src/libical/icalparameter.h =================================================================== --- src/libical/icalparameter.h (revision 976) +++ src/libical/icalparameter.h (working copy) @@ -55,12 +55,21 @@ int icalparameter_isa_parameter(void* param); -/* Access the name of an X parameer */ +/* Access the name of an X parameter */ void icalparameter_set_xname (icalparameter* param, const char* v); const char* icalparameter_get_xname(icalparameter* param); void icalparameter_set_xvalue (icalparameter* param, const char* v); const char* icalparameter_get_xvalue(icalparameter* param); +/* Access the name of an IANA parameter */ +void icalparameter_set_iana_name (icalparameter* param, const char* v); +const char* icalparameter_get_iana_name(icalparameter* param); +void icalparameter_set_iana_value (icalparameter* param, const char* v); +const char* icalparameter_get_iana_value(icalparameter* param); + +/* returns 1 if parameters have same name in ICAL, otherwise 0 */ +int icalparameter_has_same_name(icalparameter* param1, icalparameter* param2); + /* Convert enumerations */ const char* icalparameter_kind_to_string(icalparameter_kind kind); Index: src/libical/icalparser.c =================================================================== --- src/libical/icalparser.c (revision 976) +++ src/libical/icalparser.c (working copy) @@ -898,13 +898,25 @@ 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; + 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_IANA_PARAMETER){ + ical_unknown_token_handling tokHandlingSetting = + ical_get_unknown_token_handling_setting(); + if (tokHandlingSetting == ICAL_DISCARD_TOKEN) + continue; + param = icalparameter_new(ICAL_IANA_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); Index: src/libical/icalproperty.c =================================================================== --- src/libical/icalproperty.c (revision 976) +++ src/libical/icalproperty.c (working copy) @@ -569,11 +569,15 @@ icalerror_check_arg_rv( (parameter!=0),"parameter"); kind = icalparameter_isa(parameter); - if (kind != ICAL_X_PARAMETER) - icalproperty_remove_parameter_by_kind(prop,kind); - else + if (kind == ICAL_X_PARAMETER) { icalproperty_remove_parameter_by_name(prop, icalparameter_get_xname(parameter)); + } else if (kind == ICAL_IANA_PARAMETER) { + icalproperty_remove_parameter_by_name(prop, + icalparameter_get_iana_name(parameter)); + } + else + icalproperty_remove_parameter_by_kind(prop,kind); icalproperty_add_parameter(prop,parameter); } @@ -603,8 +607,10 @@ return; } - if(kind == ICAL_X_PARAMETER){ - icalparameter_set_xname(param, name); + if (kind == ICAL_X_PARAMETER) { + icalparameter_set_xname(param, name); + } else if (kind == ICAL_IANA_PARAMETER) { + icalparameter_set_iana_name(param, name); } icalproperty_set_parameter(prop,param); @@ -644,13 +650,19 @@ for(param = icalproperty_get_first_parameter(prop,kind); param != 0; param = icalproperty_get_next_parameter(prop,kind)) { - if (kind != ICAL_X_PARAMETER) { + + if (kind == ICAL_X_PARAMETER) { + if (strcmp(icalparameter_get_xname(param),name)==0) { + break; + } + } else if (kind == ICAL_IANA_PARAMETER) { + if (strcmp(icalparameter_get_iana_name(param),name)==0) { + break; + } + } else { break; - } + } - if (strcmp(icalparameter_get_xname(param),name)==0) { - break; - } } if (param == 0){ @@ -763,6 +775,8 @@ if (icalparameter_isa(param) == ICAL_X_PARAMETER) kind_string = icalparameter_get_xname(param); + else if (icalparameter_isa(param) == ICAL_IANA_PARAMETER) + kind_string = icalparameter_get_iana_name(param); else kind_string = icalparameter_kind_to_string(icalparameter_isa(param)); @@ -797,21 +811,15 @@ icalerror_check_arg_rv((parameter!=0),"parameter"); kind = icalparameter_isa(parameter); - name = icalparameter_get_xname(parameter); - /* - * FIXME If it's an X- parameter, also compare the names. It would be nice - * to have a better abstraction like icalparameter_equals() - */ - for(p=pvl_head(prop->parameters);p != 0; p = pvl_next(p)){ - icalparameter* p_param = (icalparameter *)pvl_data (p); - if (icalparameter_isa(p_param) == kind && - (kind != ICAL_X_PARAMETER || - !strcmp(icalparameter_get_xname(p_param), name))) { + for (p=pvl_head(prop->parameters);p != 0; p = pvl_next(p)) { + icalparameter* p_param = (icalparameter *)pvl_data (p); + + if (icalparameter_has_same_name(parameter, p_param)) { pvl_remove (prop->parameters, p); icalparameter_free(p_param); break; - } + } } } Index: src/libical/icalderivedparameter.c.in =================================================================== --- src/libical/icalderivedparameter.c.in (revision 976) +++ src/libical/icalderivedparameter.c.in (working copy) @@ -38,6 +38,7 @@ #include "icalproperty.h" #include "icalerror.h" #include "icalmemory.h" +#include "icaltypes.h" #include /* for malloc() */ #include @@ -98,21 +99,25 @@ int i; if (string ==0 ) { - return ICAL_NO_PARAMETER; + return ICAL_NO_PARAMETER; } for (i=0; parameter_map[i].kind != ICAL_NO_PARAMETER; i++) { - if (strcasecmp(parameter_map[i].name, string) == 0) { - return parameter_map[i].kind; - } + if (strcasecmp(parameter_map[i].name, string) == 0) { + return parameter_map[i].kind; + } } if(strncmp(string,"X-",2)==0){ - return ICAL_X_PARAMETER; + return ICAL_X_PARAMETER; } - return ICAL_NO_PARAMETER; + if (ical_get_unknown_token_handling_setting() == ICAL_TREAT_AS_ERROR) { + return ICAL_NO_PARAMETER; + } else { + return ICAL_IANA_PARAMETER; + } } Index: src/libical/icaltypes.c =================================================================== --- src/libical/icaltypes.c (revision 976) +++ src/libical/icaltypes.c (working copy) @@ -43,7 +43,13 @@ #define TEMP_MAX 1024 +#ifdef HAVE_PTHREAD + #include + static pthread_mutex_t unk_token_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif +static ical_unknown_token_handling unknownTokenHandling = ICAL_TREAT_AS_ERROR; + int icaltriggertype_is_null_trigger(struct icaltriggertype tr) { if(icaltime_is_null_time(tr.time) && @@ -199,3 +205,35 @@ return temp; } + +ical_unknown_token_handling ical_get_unknown_token_handling_setting(void) +{ + ical_unknown_token_handling myHandling; + +#ifdef HAVE_PTHREAD + pthread_mutex_lock (&unk_token_mutex); +#endif + + myHandling = unknownTokenHandling; + +#ifdef HAVE_PTHREAD + pthread_mutex_unlock (&unk_token_mutex); +#endif + + return myHandling; +} + +void ical_set_unknown_token_handling_setting(ical_unknown_token_handling newSetting) +{ + +#ifdef HAVE_PTHREAD + pthread_mutex_lock (&unk_token_mutex); +#endif + + unknownTokenHandling = newSetting; + +#ifdef HAVE_PTHREAD + pthread_mutex_unlock (&unk_token_mutex); +#endif + +}