From 4028f454b6c274fa093056180af8d11e5c7bfd1e Mon Sep 17 00:00:00 2001 From: JP Rosevear Date: Tue, 23 Jan 2001 20:22:40 +0000 Subject: Import clean up svn path=/trunk/; revision=7751 --- libical/src/libical/Makefile.am | 4 +- libical/src/libical/icalcomponent.c | 62 +- libical/src/libical/icalcomponent.h | 6 + libical/src/libical/icalenums.c | 17 +- libical/src/libical/icalenums.h | 6 +- libical/src/libical/icalerror.c | 26 +- libical/src/libical/icalerror.h | 3 + libical/src/libical/icallexer.l | 129 +-- libical/src/libical/icalmemory.h | 1 + libical/src/libical/icalparameter.c.in | 9 +- libical/src/libical/icalparser.c | 106 ++- libical/src/libical/icalparser.h | 1 - libical/src/libical/icalproperty.c.in | 4 +- libical/src/libical/icalrecur.c | 775 +++++++++++++++-- libical/src/libical/icalrestriction.h | 1 + libical/src/libical/icaltime.c | 640 +++++++++++--- libical/src/libical/icaltime.h | 58 +- libical/src/libical/icaltypes.c | 37 + libical/src/libical/icaltypes.h | 6 +- libical/src/libical/icalvalue.c.in | 265 ++---- libical/src/libical/icalyacc.y | 120 +-- libical/src/libicalss/Makefile.am | 6 +- libical/src/libicalss/icalcstp.h | 13 +- libical/src/test/Makefile.am | 10 +- libical/src/test/icaltestparser.c | 1 - libical/src/test/regression.c | 1497 ++++++++++++++++++++++++++------ libical/src/test/storage.c | 4 +- libical/src/test/stow.c | 1 - 28 files changed, 2797 insertions(+), 1011 deletions(-) (limited to 'libical/src') diff --git a/libical/src/libical/Makefile.am b/libical/src/libical/Makefile.am index 20859f4744..a3b61d5677 100644 --- a/libical/src/libical/Makefile.am +++ b/libical/src/libical/Makefile.am @@ -54,7 +54,8 @@ libical_la_SOURCES = \ pvl.c \ pvl.h \ sspm.c \ - sspm.h + sspm.h \ + vsnprintf.c libicalincludedir = $(includedir) @@ -187,3 +188,4 @@ EXTRA_DIST = \ $(BUILT_SOURCES) \ icallexer.c \ icalyacc.c + diff --git a/libical/src/libical/icalcomponent.c b/libical/src/libical/icalcomponent.c index e36faae8e7..3ac0ee0663 100644 --- a/libical/src/libical/icalcomponent.c +++ b/libical/src/libical/icalcomponent.c @@ -696,8 +696,8 @@ time_t icalcomponent_convert_time(icalproperty *p) tzp = icalproperty_get_first_parameter(p,ICAL_TZID_PARAMETER); if (sict.is_utc == 1 && tzp != 0){ - icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); icalerror_warn("icalcomponent_get_span: component has a UTC DTSTART with a timezone specified "); + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); return 0; } @@ -715,7 +715,7 @@ time_t icalcomponent_convert_time(icalproperty *p) /* _as_timet will use localtime() to do the conversion */ convt = icaltime_as_timet(sict); - offset = icaltime_local_utc_offset(); + offset = icaltime_utc_offset(sict,0); convt += offset; #ifdef TEST_CONVERT_TIME @@ -837,7 +837,7 @@ struct icaltime_span icalcomponent_get_span(icalcomponent* comp) dur = icalproperty_get_duration(duration); - durt = icaldurationtype_as_timet(dur); + durt = icaldurationtype_as_int(dur); span.end = span.start+durt; } @@ -1163,14 +1163,16 @@ struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp) } else if ( end_prop != 0) { return icalproperty_get_dtend(end_prop); } else if ( dur_prop != 0) { + struct icaltimetype start = icalcomponent_get_dtstart(inner); - time_t startt = icaltime_as_timet(start); struct icaldurationtype duration = icalproperty_get_duration(dur_prop); - time_t durt = icaldurationtype_as_timet(duration); - return icaltime_from_timet(startt+durt,start.is_date,start.is_utc); + struct icaltimetype end = icaltime_add(start,duration); + + return end; + } else { /* Error, both duration and dtend have been specified */ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); @@ -1200,14 +1202,12 @@ void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v) } else if ( dur_prop != 0) { struct icaltimetype start = icalcomponent_get_dtstart(inner); - time_t startt = icaltime_as_timet(start); struct icaltimetype end = icalcomponent_get_dtend(inner); - time_t endt = icaltime_as_timet(end); - + struct icaldurationtype dur - = icaldurationtype_from_timet(endt-startt); + = icaltime_subtract(end,start); icalproperty_set_duration(dur_prop,dur); @@ -1235,17 +1235,13 @@ void icalcomponent_set_duration(icalcomponent* comp, } else if ( end_prop != 0) { struct icaltimetype start = icalcomponent_get_dtstart(inner); - time_t startt = icaltime_as_timet(start); - time_t durt = icaldurationtype_as_timet(v); - - struct icaltimetype new_end - = icaltime_from_timet(startt+durt,start.is_date,start.is_utc); + struct icaltimetype new_end = icaltime_add(start,v); icalproperty_set_dtend(end_prop,new_end); } else if ( dur_prop != 0) { - icalproperty_set_duration(end_prop,v); + icalproperty_set_duration(dur_prop,v); } else { /* Error, both duration and dtend have been specified */ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); @@ -1277,7 +1273,7 @@ struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp) icalcomponent_get_dtend(inner); time_t endt = icaltime_as_timet(end); - return icaldurationtype_from_timet(endt-startt); + return icaldurationtype_from_int(endt-startt); } else if ( dur_prop != 0) { return icalproperty_get_duration(dur_prop); } else { @@ -1287,8 +1283,6 @@ struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp) } } - - void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method) { icalproperty *prop @@ -1348,8 +1342,34 @@ struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp) } -void icalcomponent_set_summary(icalcomponent* comp, const char* v); -const char* icalcomponent_get_summary(icalcomponent* comp); +void icalcomponent_set_summary(icalcomponent* comp, const char* v) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + icalproperty *prop + = icalcomponent_get_first_property(inner, ICAL_SUMMARY_PROPERTY); + + if (prop == 0){ + prop = icalproperty_new_summary(v); + icalcomponent_add_property(inner, prop); + } + + icalproperty_set_summary(prop,v); +} + + +const char* icalcomponent_get_summary(icalcomponent* comp) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + icalproperty *prop + = icalcomponent_get_first_property(inner,ICAL_SUMMARY_PROPERTY); + + if (prop == 0){ + return 0; + } + + return icalproperty_get_summary(prop); + +} void icalcomponent_set_comment(icalcomponent* comp, const char* v); const char* icalcomponent_get_comment(icalcomponent* comp); diff --git a/libical/src/libical/icalcomponent.h b/libical/src/libical/icalcomponent.h index b08d488db3..61f4bf0dbf 100644 --- a/libical/src/libical/icalcomponent.h +++ b/libical/src/libical/icalcomponent.h @@ -86,6 +86,12 @@ icalproperty** icalcomponent_get_properties(icalcomponent* component, */ +/* Return the first VEVENT, VTODO or VJOURNAL sub-component of cop, or + comp if it is one of those types */ + +icalcomponent* icalcomponent_get_inner(icalcomponent* comp); + + void icalcomponent_add_component(icalcomponent* parent, icalcomponent* child); diff --git a/libical/src/libical/icalenums.c b/libical/src/libical/icalenums.c index cd5ec43203..92811eef93 100644 --- a/libical/src/libical/icalenums.c +++ b/libical/src/libical/icalenums.c @@ -32,6 +32,7 @@ #include /* For fprintf */ #include /* For stderr */ +#include /* For strncmp */ #include struct icalproperty_kind_map { @@ -41,6 +42,7 @@ struct icalproperty_kind_map { static struct icalproperty_kind_map property_map[] = { + { ICAL_ANY_PROPERTY, "ANY"}, { ICAL_ACTION_PROPERTY, "ACTION"}, { ICAL_ATTACH_PROPERTY, "ATTACH"}, { ICAL_ATTENDEE_PROPERTY, "ATTENDEE"}, @@ -126,7 +128,7 @@ const char* icalenum_property_kind_to_string(icalproperty_kind kind) } -icalproperty_kind icalenum_string_to_property_kind(char* string) +icalproperty_kind icalenum_string_to_property_kind(const char* string) { int i; @@ -205,7 +207,7 @@ const char* icalenum_parameter_kind_to_string(icalparameter_kind kind) } -icalparameter_kind icalenum_string_to_parameter_kind(char* string) +icalparameter_kind icalenum_string_to_parameter_kind(const char* string) { int i; @@ -250,9 +252,10 @@ static struct icalvalue_kind_map value_map[] = { ICAL_METHOD_VALUE, "METHOD"}, /* Not an RFC2445 type */ { ICAL_STATUS_VALUE, "STATUS"}, /* Not an RFC2445 type */ { ICAL_GEO_VALUE, "FLOAT"}, /* Not an RFC2445 type */ - { ICAL_ATTACH_VALUE, "XATTACH"}, /* Not an RFC2445 type */ - { ICAL_DATETIMEDATE_VALUE, "XDATETIMEDATE"}, /* Not an RFC2445 type */ - { ICAL_DATETIMEPERIOD_VALUE, "XDATETIMEPERIOD"}, /* Not an RFC2445 type */ + { ICAL_ATTACH_VALUE, "ATTACH"}, /* Not an RFC2445 type */ + { ICAL_DATETIMEDATE_VALUE, "DATETIMEDATE"}, /* Not an RFC2445 type */ + { ICAL_DATETIMEPERIOD_VALUE, "DATETIMEPERIOD"}, /* Not an RFC2445 type */ + { ICAL_TRIGGER_VALUE, "TRIGGER"}, /* Not an RFC2445 type */ { ICAL_QUERY_VALUE, "QUERY"}, { ICAL_NO_VALUE, ""}, }; @@ -330,7 +333,7 @@ const char* icalenum_component_kind_to_string(icalcomponent_kind kind) } -icalcomponent_kind icalenum_string_to_component_kind(char* string) +icalcomponent_kind icalenum_string_to_component_kind(const char* string) { int i; @@ -400,7 +403,7 @@ static struct icalproperty_kind_value_map propval_map[] = { ICAL_RECURRENCEID_PROPERTY, ICAL_DATETIME_VALUE }, { ICAL_EXDATE_PROPERTY, ICAL_DATETIME_VALUE }, { ICAL_RDATE_PROPERTY, ICAL_DATETIME_VALUE }, - { ICAL_TRIGGER_PROPERTY, ICAL_DURATION_VALUE }, + { ICAL_TRIGGER_PROPERTY, ICAL_TRIGGER_VALUE }, { ICAL_DURATION_PROPERTY, ICAL_DURATION_VALUE }, /* CAP properties */ diff --git a/libical/src/libical/icalenums.h b/libical/src/libical/icalenums.h index ab25532cf6..d11547efad 100644 --- a/libical/src/libical/icalenums.h +++ b/libical/src/libical/icalenums.h @@ -421,16 +421,16 @@ icalrequeststatus icalenum_num_to_reqstat(short major, short minor); **********************************************************************/ const char* icalenum_property_kind_to_string(icalproperty_kind kind); -icalproperty_kind icalenum_string_to_property_kind(char* string); +icalproperty_kind icalenum_string_to_property_kind(const char* string); const char* icalenum_value_kind_to_string(icalvalue_kind kind); icalvalue_kind icalenum_value_kind_by_prop(icalproperty_kind kind); const char* icalenum_parameter_kind_to_string(icalparameter_kind kind); -icalparameter_kind icalenum_string_to_parameter_kind(char* string); +icalparameter_kind icalenum_string_to_parameter_kind(const char* string); const char* icalenum_component_kind_to_string(icalcomponent_kind kind); -icalcomponent_kind icalenum_string_to_component_kind(char* string); +icalcomponent_kind icalenum_string_to_component_kind(const char* string); icalvalue_kind icalenum_property_kind_to_value_kind(icalproperty_kind kind); diff --git a/libical/src/libical/icalerror.c b/libical/src/libical/icalerror.c index 76212afdae..e9641efc6a 100644 --- a/libical/src/libical/icalerror.c +++ b/libical/src/libical/icalerror.c @@ -53,15 +53,29 @@ void icalerror_clear_errno() { icalerrno = ICAL_NO_ERROR; } -void icalerror_set_errno(icalerrorenum e) { - #ifdef ICAL_ERRORS_ARE_FATAL - fprintf(stderr,"libical: icalerrno_set_error: %s",icalerror_strerror(e)); - icalerror_crash_here(); +int icalerror_errors_are_fatal = 1; +#else +int icalerror_errors_are_fatal = 0; #endif - icalerror_stop_here(); +void icalerror_set_errno(icalerrorenum e) { + + icalerrno = e; + icalerror_stop_here(); + + if(icalerror_errors_are_fatal == 1){ + + fprintf(stderr,"libical: icalerrno_set_error: %s\n",icalerror_strerror(e)); +#ifdef NDEBUG + icalerror_crash_here(); +#else + assert(0); +#endif + } + + } @@ -75,7 +89,7 @@ static struct icalerror_string_map string_map[] = {ICAL_BADARG_ERROR,"Bad argument to function"}, {ICAL_NEWFAILED_ERROR,"Failed to create a new object via a *_new() routine"}, {ICAL_MALFORMEDDATA_ERROR,"An input string was not correctly formed or a component has missing or extra properties"}, - {ICAL_PARSE_ERROR,"Failed to parse a part of an iCal componet"}, + {ICAL_PARSE_ERROR,"Failed to parse a part of an iCal component"}, {ICAL_INTERNAL_ERROR,"Random internal error. This indicates an error in the library code, not an error in use"}, {ICAL_FILE_ERROR,"An operation on a file failed. Check errno for more detail."}, {ICAL_ALLOCATION_ERROR,"Failed to allocate memory"}, diff --git a/libical/src/libical/icalerror.h b/libical/src/libical/icalerror.h index c5035149f9..85e054fd86 100644 --- a/libical/src/libical/icalerror.h +++ b/libical/src/libical/icalerror.h @@ -131,8 +131,11 @@ typedef enum icalerrorenum { } icalerrorenum; +/* The libical error enumeration, like errno*/ extern icalerrorenum icalerrno; +/* If true, libicl aborts after a call to icalerror_set_error*/ +extern int icalerror_errors_are_fatal; void icalerror_clear_errno(void); void icalerror_set_errno(icalerrorenum e); diff --git a/libical/src/libical/icallexer.l b/libical/src/libical/icallexer.l index 5a3616b8da..d76a7938e3 100644 --- a/libical/src/libical/icallexer.l +++ b/libical/src/libical/icallexer.l @@ -6,7 +6,7 @@ DESCRIPTION: - $Id: icallexer.l,v 1.7 2000/12/12 22:54:40 danw Exp $ + $Id: icallexer.l,v 1.8 2001/01/23 20:22:33 jpr Exp $ $Locker: $ (C) COPYRIGHT 1999 Eric Busboom @@ -94,54 +94,7 @@ digit [0-9] %} -{ -.* { ical_yylval.v_string= icalmemory_tmp_copy(yytext); - return STRING;} -{crlf} { return EOL;} - -} - -{ -. { return CHARACTER; } -{crlf} { return EOL;} - -} - -{ -.* { ical_yylval.v_string= icalmemory_tmp_copy(yytext); - return STRING;} -{crlf} { return EOL;} - -} - - { -{digit}* { ical_yylval.v_string= icalmemory_tmp_copy(yytext); - return DIGITS; } -T { return TIME_CHAR; } -Z { return UTC_CHAR; } -{crlf} { return EOL;} -. { return CHARACTER; } - -} - -{ -{digit}+ { ical_yylval.v_string =icalmemory_tmp_copy(yytext); - return DIGITS; } -T { return TIME_CHAR; } -[\+\-PTWHMSD] { return yytext[0]; } -{crlf} { return EOL;} - -} - -{ -[\+\-\.0-9]+ { ical_yylval.v_int=atoi(yytext); return INTNUMBER; } -{crlf} { return EOL;} -. { return CHARACTER; } - -} - -{ {digit}+ { ical_yylval.v_string =icalmemory_tmp_copy(yytext) ; return DIGITS; } T { return TIME_CHAR; } @@ -151,46 +104,6 @@ Z { return UTC_CHAR; } } -{ -INTERVAL { return INTERVAL; } -COUNT { return COUNT; } -UNTIL { return UNTIL; } -FREQ { return FREQ; } -BYDAY { return BYDAY; } -BYHOUR { return BYHOUR; } -BYMINUTE { return BYMINUTE; } -BYMONTH { return BYMONTH; } -BYMONTHDAY { return BYMONTHDAY; } -BYSECOND { return BYSECOND; } -BYSETPOS { return BYSETPOS; } -BYWEEKNO { return BYWEEKNO; } -BYYEARDAY { return BYYEARDAY; } -DAILY { return DAILY; } -SECONDLY { return SECONDLY; } -MINUTELY { return MINUTELY; } -HOURLY { return HOURLY; } -MONTHLY { return MONTHLY; } -WEEKLY { return WEEKLY; } -YEARLY { return YEARLY; } -WKST { return WKST; } -MO { return MO; } -SA { return SA; } -SU { return SU; } -TU { return TU; } -WE { return WE; } -TH { return TH; } -FR { return FR; } -= { return EQUALS; } -, { return COMMA; } -; { return SEMICOLON; } -- { return MINUS; } -[\+0-9]+ { ical_yylval.v_string= icalmemory_tmp_copy(yytext); - return DIGITS; } -T { return TIME_CHAR; } -Z { return UTC_CHAR; } -{crlf} { return EOL;} -} - { {crlf} { return EOL;} \-|\+ { return yytext[0]; } @@ -222,52 +135,14 @@ void set_parser_value_state(icalvalue_kind kind) switch (kind){ - case ICAL_ATTACH_VALUE: - case ICAL_BINARY_VALUE: - {BEGIN(binary_value);break;} - - case ICAL_BOOLEAN_VALUE: - case ICAL_INTEGER_VALUE: - case ICAL_FLOAT_VALUE: - {BEGIN(number_value);break;} - case ICAL_UTCOFFSET_VALUE: {BEGIN(utcoffset_value);break;} - case ICAL_TEXT_VALUE: - {BEGIN(text_value); - init_str_buf(); - break;} - - case ICAL_CALADDRESS_VALUE: - case ICAL_URI_VALUE: - {BEGIN(uri_value);break;} - - case ICAL_DATE_VALUE: - case ICAL_DATETIME_VALUE: - case ICAL_DATETIMEDATE_VALUE: case ICAL_DATETIMEPERIOD_VALUE: - case ICAL_TIME_VALUE: - {BEGIN(time_value);break;} - case ICAL_DURATION_VALUE: - {BEGIN(duration_value);break;} - case ICAL_PERIOD_VALUE: - {BEGIN(period_value);break;} - - case ICAL_GEO_VALUE: - case ICAL_QUERY_VALUE: - {BEGIN(text_value);break;} - - case ICAL_RECUR_VALUE: - {BEGIN(recur_value);break;} + {BEGIN(time_value);break;} - case ICAL_NO_VALUE: - { - /* The value is probably actually a component name */ - {BEGIN(component); break;} - } default: { assert(1==0); diff --git a/libical/src/libical/icalmemory.h b/libical/src/libical/icalmemory.h index 63ede3f3ac..3ae77024c4 100644 --- a/libical/src/libical/icalmemory.h +++ b/libical/src/libical/icalmemory.h @@ -5,6 +5,7 @@ $Id$ + $Locker$ This program is free software; you can redistribute it and/or modify diff --git a/libical/src/libical/icalparameter.c.in b/libical/src/libical/icalparameter.c.in index ad83927e87..00e9280c7d 100644 --- a/libical/src/libical/icalparameter.c.in +++ b/libical/src/libical/icalparameter.c.in @@ -3,7 +3,7 @@ FILE: icalderivedparameters.{c,h} CREATOR: eric 09 May 1999 - $Id: icalparameter.c.in,v 1.2 2000/12/14 02:13:54 federico Exp $ + $Id: icalparameter.c.in,v 1.3 2001/01/23 20:22:33 jpr Exp $ $Locker: $ @@ -233,7 +233,8 @@ void icalparameter_set_impl_data(icalparameter_kind kind, data->v_xlicerrortype=value; break; case ICAL_XLICCOMPARETYPE_PARAMETER: data->v_xliccomparetype=value; break; - default: + default: + break; } } @@ -750,7 +751,7 @@ icalparameter_as_ical_string (icalparameter* parameter) } - icalmemory_append_string(&buf, &buf_ptr, &buf_size, "="); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "="); switch (impl->kind) { case ICAL_CUTYPE_PARAMETER: @@ -1236,7 +1237,7 @@ icalproperty* icalparameter_get_parent(icalparameter* param) { struct icalparameter_impl *impl = (struct icalparameter_impl*)param; - icalerror_check_arg_rv( (param!=0),"param"); + icalerror_check_arg_rz( (param!=0),"param"); return impl->parent; } diff --git a/libical/src/libical/icalparser.c b/libical/src/libical/icalparser.c index 6359d42d27..462fd164af 100644 --- a/libical/src/libical/icalparser.c +++ b/libical/src/libical/icalparser.c @@ -70,7 +70,6 @@ struct icalparser_impl size_t tmp_buf_size; char temp[TMP_BUF_SIZE]; icalcomponent *root_component; - icalcomponent *tail; int version; int level; int lineno; @@ -203,7 +202,7 @@ void icalparser_clear_flex_input(void) input_buffer_p = input_buffer+strlen(input_buffer); } -/* Cal the flex parser to parse a complex value */ +/* Call the flex/bison parser to parse a complex value */ icalvalue* icalparser_parse_value(icalvalue_kind kind, const char* str, icalproperty** error) @@ -526,40 +525,52 @@ icalcomponent* icalparser_parse(icalparser *parser, char* line; icalcomponent *c=0; - icalcomponent *root_component=0; + icalcomponent *root=0; + struct icalparser_impl *impl = (struct icalparser_impl*)parser; 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); - } + + if(icalcomponent_get_parent(c) !=0){ + /* This is bad news... assert? */ + } + + assert(impl->root_component == 0); + assert(pvl_count(impl->components) ==0); + + if (root == 0){ + /* Just one component */ + root = c; + } else if(icalcomponent_isa(root) != ICAL_XROOT_COMPONENT) { + /*Got a second component, so move the two components under + an XROOT container */ + icalcomponent *tempc = icalcomponent_new(ICAL_XROOT_COMPONENT); + icalcomponent_add_component(tempc, root); + icalcomponent_add_component(tempc, c); + root = tempc; + } else if(icalcomponent_isa(root) == ICAL_XROOT_COMPONENT) { + /* Already have an XROOT container, so add the component + to it*/ + icalcomponent_add_component(root, c); + + } else { + /* Badness */ + assert(0); + } + + c = 0; + } if(line != 0){ free(line); } } while ( line != 0); - return root_component; + return root; } @@ -593,7 +604,7 @@ icalcomponent* icalparser_add_line(icalparser* parser, end = 0; str = icalparser_get_prop_name(line, &end); - if (str == 0){ + if (str == 0 || strlen(str) == 0 ){ /* Could not get a property name */ icalcomponent *tail = pvl_data(pvl_tail(impl->components)); @@ -638,20 +649,35 @@ icalcomponent* icalparser_add_line(icalparser* parser, impl->level--; str = icalparser_get_next_value(end,&end, value_kind); + /* Pop last component off of list and add it to the second-to-last*/ impl->root_component = pvl_pop(impl->components); tail = pvl_data(pvl_tail(impl->components)); if(tail != 0){ icalcomponent_add_component(tail,impl->root_component); - } + } tail = 0; /* Return the component if we are back to the 0th level */ if (impl->level == 0){ + icalcomponent *rtrn; + + if(pvl_count(impl->components) != 0){ + /* There are still components on the stack -- this means + that one of them did not have a proper "END" */ + pvl_push(impl->components,impl->root_component); + icalparser_clean(parser); /* may reset impl->root_component*/ + } + + assert(pvl_count(impl->components) == 0); + impl->state = ICALPARSER_SUCCESS; - return impl->root_component; + rtrn = impl->root_component; + impl->root_component = 0; + return rtrn; + } else { impl->state = ICALPARSER_END_COMP; return 0; @@ -893,10 +919,12 @@ icalcomponent* icalparser_add_line(icalparser* parser, /**************************************************************** * End of component parsing. *****************************************************************/ - + if (pvl_data(pvl_tail(impl->components)) == 0 && impl->level == 0){ + /* HACK. Does this clause ever get executed? */ impl->state = ICALPARSER_SUCCESS; + assert(0); return impl->root_component; } else { impl->state = ICALPARSER_IN_PROGRESS; @@ -912,29 +940,16 @@ icalparser_state icalparser_get_state(icalparser* parser) } -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)); + icalcomponent *tail; 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," ", @@ -946,8 +961,13 @@ icalcomponent* icalparser_clean(icalparser* parser) tail=pvl_data(pvl_tail(impl->components)); if(tail != 0){ - icalcomponent_add_component(tail,impl->root_component); + if(icalcomponent_get_parent(impl->root_component)!=0){ + icalerror_warn("icalparser_clean is trying to attach a component for the second time"); + } else { + icalcomponent_add_component(tail,impl->root_component); + } } + } return impl->root_component; diff --git a/libical/src/libical/icalparser.h b/libical/src/libical/icalparser.h index 673d514f65..efbe86eb21 100644 --- a/libical/src/libical/icalparser.h +++ b/libical/src/libical/icalparser.h @@ -54,7 +54,6 @@ typedef enum icalparser_state { icalparser* icalparser_new(void); icalcomponent* icalparser_add_line(icalparser* parser, char* str ); -icalcomponent* icalparser_claim(icalparser* parser); icalcomponent* icalparser_clean(icalparser* parser); icalparser_state icalparser_get_state(icalparser* parser); void icalparser_free(icalparser* parser); diff --git a/libical/src/libical/icalproperty.c.in b/libical/src/libical/icalproperty.c.in index 3b5cff835b..80fefd58ab 100644 --- a/libical/src/libical/icalproperty.c.in +++ b/libical/src/libical/icalproperty.c.in @@ -4,7 +4,7 @@ FILE: icalproperty.c CREATOR: eric 28 April 1999 - $Id: icalproperty.c.in,v 1.2 2000/12/14 02:13:54 federico Exp $ + $Id: icalproperty.c.in,v 1.3 2001/01/23 20:22:33 jpr Exp $ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org @@ -376,7 +376,7 @@ icalproperty_add_parameter (icalproperty* prop,icalparameter* parameter) void icalproperty_set_parameter (icalproperty* prop,icalparameter* parameter) { - icalproperty_kind kind; + icalparameter_kind kind; kind = icalparameter_isa(parameter); diff --git a/libical/src/libical/icalrecur.c b/libical/src/libical/icalrecur.c index 6a9bfcd011..cfd8e2b33b 100644 --- a/libical/src/libical/icalrecur.c +++ b/libical/src/libical/icalrecur.c @@ -4,6 +4,7 @@ CREATOR: eric 16 May 2000 $Id$ + $Locker$ @@ -111,6 +112,16 @@ Finally, icalrecur_iterator_next() does a few other checks on the time value, and if it passes, it returns the time. + A note about the end_of_data flag. This flag is usually set early in + a next_* routine and returned in the end. The way it is used allows + the next_* routine to set the last time back to the first element in + a BYxx rule, and then signal to the higer level routine to increment + the next higher level. For instance. WITH FREQ=MONTHLY;BYDAY=TU,FR, + After next_weekday_by_month runs though both TU and FR, it sets the + week day back to TU and sets end_of_data. This signals next_month to + increment the month. + + ======================================================================*/ #ifdef HAVE_CONFIG_H @@ -120,22 +131,383 @@ #include "icalrecur.h" #ifdef ICAL_NO_LIBICAL -#include "icalerror.h" -#else #define icalerror_set_errno(x) #define icalerror_check_arg_rv(x,y) +#else +#include "icalerror.h" +#include "icalmemory.h" #endif #include /* for malloc */ #include /* for errno */ -#include /* for strdup */ +#include /* for strdup and strchr*/ #include +#include /* For offsetof() macro */ #define TEMP_MAX 1024 +/*********************** Rule parsing routines ************************/ + +struct icalrecur_parser { + const char* rule; + char* copy; + char* this_clause; + char* next_clause; + + struct icalrecurrencetype rt; +}; + +const char* icalrecur_first_clause(struct icalrecur_parser *parser) +{ + char *idx; + parser->this_clause = parser->copy; + + idx = strchr(parser->this_clause,';'); + + if (idx == 0){ + parser->next_clause = 0; + return 0; + } + + *idx = 0; + idx++; + parser->next_clause = idx; + + return parser->this_clause; + +} + +const char* icalrecur_next_clause(struct icalrecur_parser *parser) +{ + char* idx; + + parser->this_clause = parser->next_clause; + + if(parser->this_clause == 0){ + return 0; + } + + idx = strchr(parser->this_clause,';'); + + if (idx == 0){ + parser->next_clause = 0; + } else { + + *idx = 0; + idx++; + parser->next_clause = idx; + } + + return parser->this_clause; + +} + +void icalrecur_clause_name_and_value(struct icalrecur_parser *parser, + char** name, char** value) +{ + char *idx; + + *name = parser->this_clause; + + idx = strchr(parser->this_clause,'='); + + if (idx == 0){ + *name = 0; + *value = 0; + return; + } + + *idx = 0; + idx++; + *value = idx; +} + +void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array, + int size, char* vals) +{ + char *t, *n; + int i=0; + int sign = 1; + short v; + + n = vals; + + while(n != 0){ + + if(i == size){ + return; + } + + t = n; + + n = strchr(t,','); + + if(n != 0){ + *n = 0; + n++; + } + + /* Get optional sign. HACK. sign is not allowed for all BYxxx + rule parts */ + if( *t == '-'){ + sign = 1; + t++; + } else if (*t == '+'){ + sign = -1; + t++; + } + + v = atoi(t) * sign ; + + + array[i++] = v; + array[i] = ICAL_RECURRENCE_ARRAY_MAX; + + } + +} + +void icalrecur_add_bydayrules(struct icalrecur_parser *parser, const char* vals) +{ + + char *t, *n; + int i=0; + int sign = 1; + int weekno = 0; + icalrecurrencetype_weekday wd; + short *array = parser->rt.by_day; + char* end; + + end = (char*)vals+strlen(vals); + n = vals; + + while(n != 0){ + + + t = n; + + n = strchr(t,','); + + if(n != 0){ + *n = 0; + n++; + } + + /* Get optional sign. */ + if( *t == '-'){ + sign = -1; + t++; + } else if (*t == '+'){ + sign = 1; + t++; + } else { + sign = 1; + } + + weekno = 0; + /* Get Optional weekno */ + if( sscanf(t,"%d",&weekno) != 0){ + if (n != 0){ + int weeknolen = (n-t)-3; /* 3 -> one for \0, 2 for day name */ + /* could use abs(log10(weekno))+1, but that needs libm */ + t += weeknolen; + } else { + t = end -2; + } + } + + wd = icalrecur_string_to_weekday(t); + + array[i++] = sign* ((int)wd + 8*weekno); + array[i] = ICAL_RECURRENCE_ARRAY_MAX; + + } + +} + + +struct icalrecurrencetype icalrecurrencetype_from_string(const char* str) +{ + struct icalrecur_parser parser; + + memset(&parser,0,sizeof(parser)); + icalrecurrencetype_clear(&parser.rt); + + icalerror_check_arg_re(str!=0,"str",parser.rt); + + + /* Set up the parser struct */ + parser.rule = str; + parser.copy = strdup(parser.rule); + parser.this_clause = parser.copy; + + if(parser.copy == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return parser.rt; + } + /* Loop through all of the clauses */ + for(icalrecur_first_clause(&parser); + parser.this_clause != 0; + icalrecur_next_clause(&parser)) + { + char *name, *value; + icalrecur_clause_name_and_value(&parser,&name,&value); + + if (strcmp(name,"FREQ") == 0){ + parser.rt.freq = icalrecur_string_to_recurrence(value); + } else if (strcmp(name,"COUNT") == 0){ + parser.rt.count = atoi(value); + } else if (strcmp(name,"UNTIL") == 0){ + parser.rt.until = icaltime_from_string(value); + } else if (strcmp(name,"INTERVAL") == 0){ + parser.rt.interval = atoi(value); + } else if (strcmp(name,"WKST") == 0){ + parser.rt.week_start = icalrecur_string_to_weekday(value); + } else if (strcmp(name,"BYSECOND") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_second, + ICAL_BY_SECOND_SIZE,value); + } else if (strcmp(name,"BYMINUTE") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_minute, + ICAL_BY_MINUTE_SIZE,value); + } else if (strcmp(name,"BYHOUR") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_hour, + ICAL_BY_HOUR_SIZE,value); + } else if (strcmp(name,"BYDAY") == 0){ + icalrecur_add_bydayrules(&parser,value); + } else if (strcmp(name,"BYMONTHDAY") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_month_day, + ICAL_BY_MONTHDAY_SIZE,value); + } else if (strcmp(name,"BYYEARDAY") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_year_day, + ICAL_BY_YEARDAY_SIZE,value); + } else if (strcmp(name,"BYWEEKNO") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_week_no, + ICAL_BY_WEEKNO_SIZE,value); + } else if (strcmp(name,"BYMONTH") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_month, + ICAL_BY_MONTH_SIZE,value); + } else if (strcmp(name,"BYSETPOS") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_set_pos, + ICAL_BY_SETPOS_SIZE,value); + } else { + /* error */ + } + + } + + free(parser.copy); + + return parser.rt; + +} + +#ifndef ICAL_NO_LIBICAL + +struct { char* str;size_t offset; short limit; } recurmap[] = +{ + {";BYSECOND=",offsetof(struct icalrecurrencetype,by_second),60}, + {";BYMINUTE=",offsetof(struct icalrecurrencetype,by_minute),60}, + {";BYHOUR=",offsetof(struct icalrecurrencetype,by_hour),24}, + {";BYDAY=",offsetof(struct icalrecurrencetype,by_day),7}, + {";BYMONTHDAY=",offsetof(struct icalrecurrencetype,by_month_day),31}, + {";BYYEARDAY=",offsetof(struct icalrecurrencetype,by_year_day),366}, + {";BYWEEKNO=",offsetof(struct icalrecurrencetype,by_week_no),52}, + {";BYMONTH=",offsetof(struct icalrecurrencetype,by_month),12}, + {";BYSETPOS=",offsetof(struct icalrecurrencetype,by_set_pos),366}, + {0,0,0}, +}; + +/* A private routine in icalvalue.c */ +void print_datetime_to_string(char* str, struct icaltimetype *data); + +char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur) +{ + char* str; + char *str_p; + size_t buf_sz = 200; + char temp[20]; + int i,j; + + if(recur->freq == ICAL_NO_RECURRENCE){ + return 0; + } + str = (char*)icalmemory_tmp_buffer(buf_sz); + str_p = str; + + icalmemory_append_string(&str,&str_p,&buf_sz,"FREQ="); + icalmemory_append_string(&str,&str_p,&buf_sz, + icalrecur_recurrence_to_string(recur->freq)); + + if(recur->until.year != 0){ + + temp[0] = 0; + print_datetime_to_string(temp,&(recur->until)); + + icalmemory_append_string(&str,&str_p,&buf_sz,";UNTIL="); + icalmemory_append_string(&str,&str_p,&buf_sz, temp); + } + + if(recur->count != 0){ + sprintf(temp,"%d",recur->count); + icalmemory_append_string(&str,&str_p,&buf_sz,";COUNT="); + icalmemory_append_string(&str,&str_p,&buf_sz, temp); + } + + if(recur->interval != 0){ + sprintf(temp,"%d",recur->interval); + icalmemory_append_string(&str,&str_p,&buf_sz,";INTERVAL="); + icalmemory_append_string(&str,&str_p,&buf_sz, temp); + } + + for(j =0; recurmap[j].str != 0; j++){ + short* array = (short*)(recurmap[j].offset+ (size_t)recur); + short limit = recurmap[j].limit; + + /* Skip unused arrays */ + if( array[0] != ICAL_RECURRENCE_ARRAY_MAX ) { + + icalmemory_append_string(&str,&str_p,&buf_sz,recurmap[j].str); + + for(i=0; + i< limit && array[i] != ICAL_RECURRENCE_ARRAY_MAX; + i++){ + if (j == 3) { /* BYDAY */ + short dow = icalrecurrencetype_day_day_of_week(array[i]); + const char *daystr = icalrecur_weekday_to_string(dow); + short pos; + + pos = icalrecurrencetype_day_position(array[i]); + + if (pos == 1) + icalmemory_append_string(&str,&str_p,&buf_sz,daystr); + else { + sprintf(temp,"%d%s",pos,daystr); + icalmemory_append_string(&str,&str_p,&buf_sz,temp); + } + + } else { + sprintf(temp,"%d",array[i]); + icalmemory_append_string(&str,&str_p,&buf_sz, temp); + } + + if( (i+1)orig_data[byrule] == 1); +} + icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, struct icaltimetype dtstart) @@ -341,6 +719,27 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, impl->by_ptrs[BY_SECOND]=impl->rule.by_second; impl->by_ptrs[BY_SET_POS]=impl->rule.by_set_pos; + memset(impl->orig_data,0,9); + + impl->orig_data[BY_MONTH] + = (impl->rule.by_month[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_WEEK_NO] + =(impl->rule.by_week_no[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_YEAR_DAY] + =(impl->rule.by_year_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_MONTH_DAY] + =(impl->rule.by_month_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_DAY] + = (impl->rule.by_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_HOUR] + = (impl->rule.by_hour[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_MINUTE] + = (impl->rule.by_minute[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_SECOND] + = (impl->rule.by_second[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_SET_POS] + = (impl->rule.by_set_pos[0]!=ICAL_RECURRENCE_ARRAY_MAX); + /* Check if the recurrence rule is legal */ @@ -400,7 +799,7 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, /* Rewrite some of the rules and set up defaults to make later - processing easier. Primarily, this involves copying an element + processing easier. Primarily, t involves copying an element from the start time into the coresponding BY_* array when the BY_* array is empty */ @@ -420,9 +819,37 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, setup_defaults(impl,BY_MONTH,ICAL_MONTHLY_RECURRENCE,impl->dtstart.month, &(impl->last.month)); - if(impl->rule.freq == ICAL_WEEKLY_RECURRENCE && - impl->by_ptrs[BY_DAY][0] == ICAL_RECURRENCE_ARRAY_MAX){ - impl->by_ptrs[BY_DAY][0] = icaltime_day_of_week(impl->dtstart); + if(impl->rule.freq == ICAL_WEEKLY_RECURRENCE ){ + + if(impl->by_ptrs[BY_DAY][0] == ICAL_RECURRENCE_ARRAY_MAX){ + + /* Weekly recurrences with no BY_DAY data should occur on the + same day of the week as the start time . */ + impl->by_ptrs[BY_DAY][0] = icaltime_day_of_week(impl->dtstart); + + } else { + /* If there is BY_DAY data, then we need to move the initial + time to the start of the BY_DAY data. That if if the + start time is on a Wednesday, and the rule has + BYDAY=MO,WE,FR, move the initial time back to + monday. Otherwise, jumping to the next week ( jumping 7 + days ahead ) will skip over some occurrences in the + second week. */ + + /* This is probably a HACK. There should be some more + general way to solve this problem */ + + short dow = impl->by_ptrs[BY_DAY][0]-icaltime_day_of_week(impl->last); + + if(dow < 0) { + /* initial time is after first day of BY_DAY data */ + + impl->last.day += dow; + impl->last = icaltime_normalize(impl->last); + } + } + + } @@ -430,6 +857,41 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, expand_year_days(impl,impl->dtstart.year); } + + /* If this is a monthly interval with by day data, then we need to + set the last value to the appropriate day of the month */ + + if(impl->rule.freq == ICAL_MONTHLY_RECURRENCE && + has_by_data(impl,BY_DAY)) { + + short dow = icalrecurrencetype_day_day_of_week( + impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]); + short pos = icalrecurrencetype_day_position( + impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]); + + short poscount = 0; + short days_in_month = + icaltime_days_in_month(impl->last.month, impl->last.year) ; + + for(impl->last.day = 1; + impl->last.day <= days_in_month; + impl->last.day++){ + + if(icaltime_day_of_week(impl->last) == dow){ + if(++poscount == pos){ + break; + } + } + } + + if(impl->last.day > days_in_month){ + icalerror_set_errno(ICAL_USAGE_ERROR); + return 0; + } + + } + + return impl; } @@ -540,8 +1002,7 @@ void increment_second(struct icalrecur_iterator_impl* impl, int inc) } } -#if 0 - +#if 0 #include "ical.h" void test_increment() { @@ -812,11 +1273,10 @@ int next_yearday(struct icalrecur_iterator_impl* impl) } -/* This routine is only called by next_week or next_month, so it does -not have a clause for this_frequency. In both cases, it is certain -that BY_DAY has data */ +/* This routine is only called by next_week. It is certain that BY_DAY +has data */ -int next_weekday(struct icalrecur_iterator_impl* impl) +int next_weekday_by_week(struct icalrecur_iterator_impl* impl) { short end_of_data = 0; @@ -829,42 +1289,121 @@ int next_weekday(struct icalrecur_iterator_impl* impl) assert( impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX); - impl->by_indices[BY_DAY]++; - - if (impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]] - ==ICAL_RECURRENCE_ARRAY_MAX){ - impl->by_indices[BY_DAY] = 0; + while(1) { + + impl->by_indices[BY_DAY]++; /* Look at next elem in BYDAY array */ - end_of_data = 1; - } + /* Are we at the end of the BYDAY array? */ + if (impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + + impl->by_indices[BY_DAY] = 0; /* Reset to 0 */ + end_of_data = 1; /* Signal that we're at the end */ + } + + /* Add the day of week offset to to the start of this week, and use + that to get the next day */ + dow = impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]; + start_of_week = icaltime_start_doy_of_week(impl->last); + + dow--; /*Sun is 1, not 0 */ - /* HACK. I don't think this handles the Nth day of week rules - correctly ( "BYDAY=2TU" ) */ - dow = impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]; - - start_of_week = icaltime_start_doy_of_week(impl->last); - next = icaltime_from_day_of_year(start_of_week + dow - 1,impl->last.year); + if(dow+start_of_week <1 && !end_of_data){ + /* The selected date is in the previous year. */ + continue; + } - impl->last.day = next.day; - impl->last.month = next.month; + next = icaltime_from_day_of_year(start_of_week + dow,impl->last.year); + + impl->last.day = next.day; + impl->last.month = next.month; + impl->last.year = next.year; - return end_of_data; + return end_of_data; + } } +int next_weekday_by_month(struct icalrecur_iterator_impl* impl) +{ + + short end_of_data = 0; + struct icaltimetype start_of_month; /* Start of month */ + short pos, poscount, dow, days_in_month; + + if (next_hour(impl) == 0){ + return 0; + } + + assert( impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX); + + while(1) { + impl->by_indices[BY_DAY]++; /* Look at next elem in BYDAY array */ + + /* Are we at the end of the BYDAY array? */ + if (impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + + impl->by_indices[BY_DAY] = 0; /* Reset to 0 */ + end_of_data = 1; /* Signal that we're at the end */ + } + + dow = icalrecurrencetype_day_day_of_week( + impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]); + pos = icalrecurrencetype_day_position( + impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]); + + start_of_month = impl->last; + + /* Find right day in month. HACK. Find an arithmetic way to do + this */ + + poscount = 0; + days_in_month = + icaltime_days_in_month(impl->last.month, impl->last.year) ; + + for(start_of_month.day = 1; + start_of_month.day <= days_in_month; + start_of_month.day++){ + + if(icaltime_day_of_week(start_of_month) == dow){ + if(++poscount == pos){ + break; + } + } + } + + if (!end_of_data == 1 && + ( + start_of_month.day > days_in_month || + icaltime_compare(start_of_month,impl->last) <= 0 + ) + ){ + continue; + } + + impl->last.day = start_of_month.day; + impl->last.month = start_of_month.month; + impl->last.year = start_of_month.year; + + return end_of_data; + } +} + int next_month(struct icalrecur_iterator_impl* impl) { - short has_by_data = (impl->by_ptrs[BY_MONTH][0]!=ICAL_RECURRENCE_ARRAY_MAX); short this_frequency = (impl->rule.freq == ICAL_MONTHLY_RECURRENCE); short end_of_data = 0; - assert(has_by_data || this_frequency); + assert( has_by_data(impl,BY_MONTH) || this_frequency); /* Week day data overrides monthday data */ - if(impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX){ - if (next_weekday(impl) == 0){ + if(has_by_data(impl,BY_DAY)){ + /* For this case, the weekdays are relative to the + month. BYDAY=FR -> First Friday in month, etc. */ + if (next_weekday_by_month(impl) == 0){ return 0; } } else { @@ -873,7 +1412,8 @@ int next_month(struct icalrecur_iterator_impl* impl) } } - if( has_by_data ){ + + if(has_by_data(impl,BY_MONTH) ){ /* Ignore the frequency and use the byrule data */ impl->by_indices[BY_MONTH]++; @@ -888,13 +1428,36 @@ int next_month(struct icalrecur_iterator_impl* impl) impl->last.month = impl->by_ptrs[BY_MONTH][impl->by_indices[BY_MONTH]]; - } else if( !has_by_data && this_frequency ){ - /* Compute the next value from the last time and the frequency interval*/ - increment_month(impl,impl->rule.interval); + } else if( !has_by_data(impl,BY_MONTH) && this_frequency ){ - } + if(has_by_data(impl,BY_DAY)){ - if(has_by_data && end_of_data && this_frequency ){ + short dayinc = 28; + + /* BY_DAY data specified a day of week, but incrementing the + month changes the day of the week -- Nov 2 is not the + same DOW as Oct 2. So, we need to fix the day of week by + incrementing in even weeks into the next month. . */ + + + if ( impl->last.day + dayinc + <= icaltime_days_in_month(impl->last.month, impl->last.year)){ + dayinc += 7; + } + + increment_monthday(impl,dayinc); + + } else { + + /* Compute the next value from the last time and the + frequency interval*/ + increment_month(impl,impl->rule.interval); + } + + } + + + if(has_by_data(impl,BY_MONTH) && end_of_data && this_frequency ){ increment_year(impl,1); } return end_of_data; @@ -908,16 +1471,14 @@ int next_week(struct icalrecur_iterator_impl* impl) short this_frequency = (impl->rule.freq == ICAL_WEEKLY_RECURRENCE); short end_of_data = 0; - int sec_in_week = 60*60*24*7; - if (next_weekday(impl) == 0){ + if (next_weekday_by_week(impl) == 0){ return 0; } if( impl->by_ptrs[BY_WEEK_NO][0]!=ICAL_RECURRENCE_ARRAY_MAX){ /* Use the Week Number byrule data */ int week_no; - time_t tt; struct icaltimetype t; impl->by_indices[BY_WEEK_NO]++; @@ -935,13 +1496,13 @@ int next_week(struct icalrecur_iterator_impl* impl) week_no = impl->by_ptrs[BY_WEEK_NO][impl->by_indices[BY_WEEK_NO]]; - tt = icaltime_as_timet(impl->last); - - tt+=sec_in_week*week_no; - - impl->last = icaltime_from_timet(tt,impl->last.is_date,impl->last.is_utc); + impl->last.day += week_no*7; + + impl->last = icaltime_normalize(impl->last); } else if( !has_by_data && this_frequency ){ + + increment_monthday(impl,7*impl->rule.interval); } @@ -953,10 +1514,6 @@ int next_week(struct icalrecur_iterator_impl* impl) } -int has_by_data(struct icalrecur_iterator_impl* impl, enum byrule byrule){ - - return (impl->by_ptrs[byrule][0] != ICAL_RECURRENCE_ARRAY_MAX); -} /* For INTERVAL=YEARLY, set up the days[] array in the iterator to @@ -970,10 +1527,13 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year) struct icaltimetype t; + t.is_date = 1; /* Needed to make day_of_year routines work property */ + memset(&t,0,sizeof(t)); memset(impl->days,ICAL_RECURRENCE_ARRAY_MAX_BYTE,sizeof(impl->days)); - if(has_by_data(impl,BY_MONTH) && !has_by_data(impl,BY_MONTH_DAY)){ + if(has_by_data(impl,BY_MONTH) && !has_by_data(impl,BY_MONTH_DAY) + && !has_by_data(impl,BY_DAY)){ for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){ struct icaltimetype t; @@ -983,6 +1543,7 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year) t = impl->dtstart; t.year = year; t.month = month; + t.is_date = 1; doy = icaltime_day_of_year(t); @@ -1003,7 +1564,8 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year) t.day = 1; t.year = year; t.month = month; - + t.is_date = 1; + for(t.day = 1; t.day <=days_in_month; t.day++){ short current_dow = icaltime_day_of_week(t); @@ -1034,6 +1596,7 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year) t.day = month_day; t.month = month; t.year = year; + t.is_date = 1; doy = icaltime_day_of_year(t); @@ -1049,18 +1612,30 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year) t.day = impl->dtstart.day; t.month = impl->dtstart.month; t.year = year; + t.is_date = 1; dow = icaltime_day_of_week(t); + /* HACK Not finished */ + } else if (has_by_data(impl,BY_WEEK_NO) && has_by_data(impl,BY_DAY)){ - + /* HACK Not finished */ } else if (has_by_data(impl,BY_YEAR_DAY)){ - + + for(j=0;impl->by_ptrs[BY_YEAR_DAY][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){ + short doy = impl->by_ptrs[BY_YEAR_DAY][j]; + impl->days[days_index++] = doy; + } + } else if (has_by_data(impl,BY_MONTH_DAY) ){ + /* HACK Not finished */ } else if (has_by_data(impl,BY_DAY)){ + /* HACK Not finished */ } else { + assert(0); + /* HACK Not finished */ } @@ -1124,7 +1699,6 @@ int check_restriction(struct icalrecur_iterator_impl* impl, int check_contracting_rules(struct icalrecur_iterator_impl* impl) { - enum byrule; int day_of_week=0; int week_no=0; @@ -1158,14 +1732,15 @@ struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr) return icaltime_null_time(); } - if(impl->occurrence_no == 0){ + if(impl->occurrence_no == 0 + && icaltime_compare(impl->last,impl->dtstart) >= 0){ + impl->occurrence_no++; return impl->last; } - do { - switch(impl->rule.freq){ + switch(impl->rule.freq){ case ICAL_SECONDLY_RECURRENCE: { next_second(impl); @@ -1199,19 +1774,19 @@ struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr) assert(0); /* HACK, need a better error */ } } - + if(impl->last.year >= 2038){ /* HACK */ return icaltime_null_time(); } - } while(!check_contracting_rules(impl) || icaltime_compare(impl->last,impl->dtstart) < 0); - - + + +/* Ignore null times and times that are after the until time */ if( !icaltime_is_null_time(impl->rule.until) && - icaltime_compare(impl->last,impl->rule.until) > 0) { + icaltime_compare(impl->last,impl->rule.until) > 0 ) { return icaltime_null_time(); } @@ -1252,7 +1827,17 @@ enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day) short icalrecurrencetype_day_position(short day) { - return (day-icalrecurrencetype_day_day_of_week(day))/8; + short wd, pos; + + wd = icalrecurrencetype_day_day_of_week(day); + + pos = (abs(day)-wd)/8 * ((day<0)?-1:1); + + if(pos == 0){ + pos = 1; + } + + return pos; } @@ -1283,6 +1868,20 @@ const char* icalrecur_weekday_to_string(icalrecurrencetype_weekday kind) return 0; } +icalrecurrencetype_weekday icalrecur_string_to_weekday(const char* str) +{ + int i; + + for (i=0; wd_map[i].wd != ICAL_NO_WEEKDAY; i++) { + if ( strcmp(str,wd_map[i].str) == 0){ + return wd_map[i].wd; + } + } + + return ICAL_NO_WEEKDAY; +} + + struct { icalrecurrencetype_frequency kind; @@ -1310,4 +1909,48 @@ const char* icalrecur_recurrence_to_string(icalrecurrencetype_frequency kind) return 0; } +icalrecurrencetype_frequency icalrecur_string_to_recurrence(const char* str) +{ + int i; + + for (i=0; freq_map[i].kind != ICAL_NO_RECURRENCE ; i++) { + if ( strcmp(str,freq_map[i].str) == 0){ + return freq_map[i].kind; + } + } + return ICAL_NO_RECURRENCE; +} + + +int icalrecur_expand_recurrence(char* rule, time_t start, + int count, time_t* array) +{ + struct icalrecurrencetype recur; + icalrecur_iterator* ritr; + time_t tt; + struct icaltimetype icstart, next; + int i = 0; + + memset(array, 0, count*sizeof(time_t)); + + icstart = icaltime_from_timet(start,0); + + recur = icalrecurrencetype_from_string(rule); + for(ritr = icalrecur_iterator_new(recur,icstart), + next = icalrecur_iterator_next(ritr); + !icaltime_is_null_time(next) && i < count; + next = icalrecur_iterator_next(ritr)){ + + tt = icaltime_as_timet(next); + + if (tt >= start ){ + array[i++] = tt; + } + + } + + icalrecur_iterator_free(ritr); + + return 1; +} diff --git a/libical/src/libical/icalrestriction.h b/libical/src/libical/icalrestriction.h index 409334cf28..6d414db4af 100644 --- a/libical/src/libical/icalrestriction.h +++ b/libical/src/libical/icalrestriction.h @@ -6,6 +6,7 @@ $Id$ + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org This program is free software; you can redistribute it and/or modify diff --git a/libical/src/libical/icaltime.c b/libical/src/libical/icaltime.c index 112ac7972b..8169161dee 100644 --- a/libical/src/libical/icaltime.c +++ b/libical/src/libical/icaltime.c @@ -30,45 +30,221 @@ #endif #include "icaltime.h" -#include "icalvalue.h" #include #include #include #include +#ifdef ICAL_NO_LIBICAL +#define icalerror_set_errno(x) +#define icalerror_check_arg_rv(x,y) +#define icalerror_check_arg_re(x,y,z) +#else +#include "icalerror.h" +#include "icalmemory.h" +#endif + + + +extern long int timezone; /* Global defined by libc */ struct icaltimetype -icaltime_from_timet(time_t tm, int is_date, int is_utc) +icaltime_from_timet(time_t tm, int is_date) { - struct icaltimetype tt; + struct icaltimetype tt = icaltime_null_time(); struct tm t; -#if 0 /* This is incorrect; a time_t *is* in UTC by definition. So we just ignore the flag. */ - if(is_utc == 0){ - tm += icaltime_local_utc_offset(); - } -#endif - t = *(gmtime(&tm)); + + if(is_date == 0){ + tt.second = t.tm_sec; + tt.minute = t.tm_min; + tt.hour = t.tm_hour; + } else { + tt.second = tt.minute =tt.hour = 0 ; + } - tt.second = t.tm_sec; - tt.minute = t.tm_min; - tt.hour = t.tm_hour; tt.day = t.tm_mday; tt.month = t.tm_mon + 1; tt.year = t.tm_year+ 1900; -#if 0 - tt.is_utc = is_utc; -#endif tt.is_utc = 1; tt.is_date = is_date; return tt; } -/* Always returns time in UTC */ +char* set_tz(const char* tzid) +{ + char *tzstr = 0; + char *tmp; + + /* Put the new time zone into the environment */ + if(getenv("TZ") != 0){ + tzstr = (char*)strdup(getenv("TZ")); + + if(tzstr == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + } + + tmp = (char*)malloc(1024); + + if(tmp == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + snprintf(tmp,1024,"TZ=%s",tzid); + + /* HACK. In some libc versions, putenv gives the string to the + system and in some it gives a copy, so the following might be a + memory leak. THe linux man page says that glibc2.1.2 take + ownership ( no leak) while BSD4.4 uses a copy ( A leak ) */ + putenv(tmp); + + return tzstr; /* This will be zero if the TZ env var was not set */ +} + +void unset_tz(char* tzstr) +{ + /* restore the original environment */ + + if(tzstr!=0){ + char temp[1024]; + snprintf(temp,1024,"TZ=%s",tzstr); + putenv(temp); + free(tzstr); + } else { + putenv("TZ"); /* Delete from environment */ + } +} + time_t icaltime_as_timet(struct icaltimetype tt) +{ + struct tm stm; + time_t t; + + memset(&stm,0,sizeof( struct tm)); + + if(icaltime_is_null_time(tt)) { + return 0; + } + + stm.tm_sec = tt.second; + stm.tm_min = tt.minute; + stm.tm_hour = tt.hour; + stm.tm_mday = tt.day; + stm.tm_mon = tt.month-1; + stm.tm_year = tt.year-1900; + stm.tm_isdst = -1; + + if(tt.is_utc == 1 || tt.is_date == 1){ + char* old_tz = set_tz("UTC"); + t = mktime(&stm); + unset_tz(old_tz); + } else { + t = mktime(&stm); + } + + return t; + +} + +char* icaltime_as_ical_string(struct icaltimetype tt) +{ + size_t size = 17; + char* buf = icalmemory_new_buffer(size); + + if(tt.is_date){ + snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day); + } else { + char* fmt; + if(tt.is_utc){ + fmt = "%04d%02d%02dT%02d%02d%02dZ"; + } else { + fmt = "%04d%02d%02dT%02d%02d%02d"; + } + snprintf(buf, size,fmt,tt.year,tt.month,tt.day, + tt.hour,tt.minute,tt.second); + } + + icalmemory_add_tmp_buffer(buf); + + return buf; + +} + + +/* convert tt, of timezone tzid, into a utc time */ +struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid) +{ + int tzid_offset; + + if(tt.is_utc == 1 || tt.is_date == 1){ + return tt; + } + + tzid_offset = icaltime_utc_offset(tt,tzid); + + tt.second -= tzid_offset; + + tt.is_utc = 1; + + return icaltime_normalize(tt); +} + +/* convert tt, a time in UTC, into a time in timezone tzid */ +struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid) +{ + int tzid_offset; + + tzid_offset = icaltime_utc_offset(tt,tzid); + + tt.second += tzid_offset; + + tt.is_utc = 0; + + return icaltime_normalize(tt); + +} + + +/* Return the offset of the named zone as seconds. tt is a time + indicating the date for which you want the offset */ +int icaltime_utc_offset(struct icaltimetype ictt, const char* tzid) +{ + + time_t tt = icaltime_as_timet(ictt); + time_t offset_tt; + struct tm gtm; + + char *tzstr = 0; + + if(tzid != 0){ + tzstr = set_tz(tzid); + } + + /* Mis-interpret a UTC broken out time as local time */ + gtm = *(gmtime(&tt)); + gtm.tm_isdst = localtime(&tt)->tm_isdst; + offset_tt = mktime(>m); + + if(tzid != 0){ + unset_tz(tzstr); + } + + return tt-offset_tt; +} + + + +/* Normalize by converting from localtime to utc and back to local + time. This uses localtime because localtime and mktime are inverses + of each other */ + +struct icaltimetype icaltime_normalize(struct icaltimetype tt) { struct tm stm; time_t tut; @@ -87,29 +263,71 @@ time_t icaltime_as_timet(struct icaltimetype tt) if(tt.is_utc) stm.tm_sec -= icaltime_local_utc_offset(); + tut = mktime(&stm); - return tut; + stm = *(localtime(&tut)); + + tt.second = stm.tm_sec; + tt.minute = stm.tm_min; + tt.hour = stm.tm_hour; + tt.day = stm.tm_mday; + tt.month = stm.tm_mon +1; + tt.year = stm.tm_year+1900; + + return tt; } +#ifndef ICAL_NO_LIBICAL +#include "icalvalue.h" struct icaltimetype icaltime_from_string(const char* str) { - struct icaltimetype tt; - icalvalue *v = icalvalue_new_from_string(ICAL_DATETIME_VALUE,str); - - if (v == 0){ + struct icaltimetype tt = icaltime_null_time(); + int size; + + icalerror_check_arg_re(str!=0,"str",icaltime_null_time()); + + size = strlen(str); + + if(size == 15) { /* floating time */ + tt.is_utc = 0; + tt.is_date = 0; + } else if (size == 16) { /* UTC time, ends in 'Z'*/ + tt.is_utc = 1; + tt.is_date = 0; + + if(str[15] != 'Z'){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return icaltime_null_time(); + } + + } else if (size == 8) { /* A DATE */ + tt.is_utc = 0; + tt.is_date = 1; + } else { /* error */ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); return icaltime_null_time(); } - tt = icalvalue_get_datetime(v); + if(tt.is_date == 1){ + sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day); + } else { + char tsep; + sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day, + &tsep,&tt.hour,&tt.minute,&tt.second); - icalvalue_free(v); + if(tsep != 'T'){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return icaltime_null_time(); + } - return tt; - + } + + return tt; } +#endif char ctime_str[20]; char* icaltime_as_ctime(struct icaltimetype t) @@ -128,6 +346,7 @@ short days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; short icaltime_days_in_month(short month,short year) { + int is_leap =0; int days = days_in_month[month]; @@ -152,7 +371,11 @@ short icaltime_day_of_week(struct icaltimetype t){ time_t tt = icaltime_as_timet(t); struct tm *tm; - tm = gmtime(&tt); + if(t.is_utc == 1){ + tm = gmtime(&tt); + } else { + tm = localtime(&tt); + } return tm->tm_wday+1; } @@ -161,26 +384,50 @@ short icaltime_start_doy_of_week(struct icaltimetype t){ time_t tt = icaltime_as_timet(t); time_t start_tt; struct tm *stm; + int syear; stm = gmtime(&tt); + syear = stm->tm_year; start_tt = tt - stm->tm_wday*(60*60*24); stm = gmtime(&start_tt); + + if(syear == stm->tm_year){ + return stm->tm_yday+1; + } else { + /* return negative to indicate that start of week is in + previous year. */ + int is_leap = 0; + int year = stm->tm_year; - return stm->tm_yday; + if( (year % 4 == 0 && year % 100 != 0) || + year % 400 == 0){ + is_leap =1; + } + + return (stm->tm_yday+1)-(365+is_leap); + } + } + + short icaltime_day_of_year(struct icaltimetype t){ time_t tt = icaltime_as_timet(t); struct tm *stm; - stm = gmtime(&tt); + if(t.is_utc==1){ + stm = gmtime(&tt); + } else { + stm = localtime(&tt); + } - return stm->tm_yday; + return stm->tm_yday+1; } +/* Jan 1 is day #1, not 0 */ struct icaltimetype icaltime_from_day_of_year(short doy, short year) { struct tm stm; @@ -195,9 +442,10 @@ struct icaltimetype icaltime_from_day_of_year(short doy, short year) /* Now add in the days */ + doy--; tt += doy *60*60*24; - return icaltime_from_timet(tt, 1, 1); + return icaltime_from_timet(tt, 1); } struct icaltimetype icaltime_null_time() @@ -255,102 +503,83 @@ icaltime_compare_date_only (struct icaltimetype a, struct icaltimetype b) } } -/* convert tt, of timezone tzid, into a utc time */ -struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid) +struct icalperiodtype icalperiodtype_from_string (const char* str) { - time_t offset, tm; - struct icaltimetype utc; + + struct icalperiodtype p, null_p; + char *s = strdup(str); + char *start, *end = s; + int old_ieaf = icalerror_errors_are_fatal; - offset = icaltime_utc_offset(tt,tzid); - tm = icaltime_as_timet(tt); + p.start = p.end = icaltime_null_time(); + p.duration = icaldurationtype_from_int(0); - tm += offset; + null_p = p; - utc = icaltime_from_timet(tm,0,0); + if(s == 0) goto error; - return utc; -} + start = s; + end = strchr(s, '/'); -/* convert tt, a time in UTC, into a time in timezone tzid */ -struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid) -{ - time_t offset, tm; - struct icaltimetype zone; + if(end == 0) goto error; - offset = icaltime_utc_offset(tt,tzid); - tm = icaltime_as_timet(tt); + *end = 0; + end++; - tm -= offset; - - zone = icaltime_from_timet(tm,0,0); + p.start = icaltime_from_string(start); - return zone; + if (icaltime_is_null_time(p.start)) goto error; + + icalerror_errors_are_fatal = 0; + p.end = icaltime_from_string(end); + icalerror_errors_are_fatal = old_ieaf; -} + if (icaltime_is_null_time(p.end)){ -/* Return the offset of the named zone as seconds. tt is a time - indicating the date for which you want the offset */ -time_t icaltime_utc_offset(struct icaltimetype tt, const char* tzid) -{ -#ifdef HAVE_TIMEZONE - extern long int timezone; -#endif - time_t now; - struct tm *stm; + p.duration = icaldurationtype_from_string(end); - char *tzstr = 0; - char *tmp; + if(icaldurationtype_as_int(p.duration) == 0) goto error; + } - /* Put the new time zone into the environment */ - if(getenv("TZ") != 0){ - tzstr = (char*)strdup(getenv("TZ")); - } + return p; - tmp = (char*)malloc(1024); - snprintf(tmp,1024,"TZ=%s",tzid); + error: + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return null_p; +} - putenv(tmp); - /* Get the offset */ +const char* icalperiodtype_as_ical_string(struct icalperiodtype p) +{ - now = icaltime_as_timet(tt); + const char* start; + const char* end; - stm = localtime(&now); /* This sets 'timezone'*/ + char *buf; + size_t buf_size = 40; + char* buf_ptr = 0; - /* restore the original environment */ + buf = (char*)icalmemory_new_buffer(buf_size); + buf_ptr = buf; + - if(tzstr!=0){ - putenv(tzstr); + start = icaltime_as_ical_string(p.start); + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, start); + + if(!icaltime_is_null_time(p.end)){ + end = icaltime_as_ical_string(p.end); } else { - putenv("TZ"); /* Delete from environment */ + end = icaldurationtype_as_ical_string(p.duration); } - -#ifdef HAVE_TIMEZONE - return timezone; -#else - return -stm->tm_gmtoff; -#endif -} -time_t icaltime_local_utc_offset() -{ - time_t now; - struct tm *stm; + icalmemory_append_char(&buf, &buf_ptr, &buf_size, '/'); - stm = localtime(&now); /* This sets 'timezone'*/ + icalmemory_append_string(&buf, &buf_ptr, &buf_size, end); -#ifdef HAVE_TIMEZONE - return timezone; -#else - return -stm->tm_gmtoff; -#endif + return buf; } - - - - - time_t icalperiodtype_duration (struct icalperiodtype period); @@ -360,20 +589,21 @@ icalperiodtype_end (struct icalperiodtype period); /* From Russel Steinthal */ -time_t icaldurationtype_as_timet(struct icaldurationtype dur) +int icaldurationtype_as_int(struct icaldurationtype dur) { - return (time_t) (dur.seconds + - (60 * dur.minutes) + - (60 * 60 * dur.hours) + - (60 * 60 * 24 * dur.days) + - (60 * 60 * 24 * 7 * dur.weeks)); + return (int)( (dur.seconds + + (60 * dur.minutes) + + (60 * 60 * dur.hours) + + (60 * 60 * 24 * dur.days) + + (60 * 60 * 24 * 7 * dur.weeks)) + * (dur.is_neg==1? -1 : 1) ) ; } /* From Seth Alves, */ -struct icaldurationtype icaldurationtype_from_timet(time_t t) +struct icaldurationtype icaldurationtype_from_int(int t) { struct icaldurationtype dur; - time_t used = 0; + int used = 0; dur.weeks = (t - used) / (60 * 60 * 24 * 7); used += dur.weeks * (60 * 60 * 24 * 7); @@ -385,33 +615,209 @@ struct icaldurationtype icaldurationtype_from_timet(time_t t) used += dur.minutes * (60); dur.seconds = (t - used); + dur.is_neg = t<0? 1 : 0; + return dur; } +#ifndef ICAL_NO_LIBICAL +#include "icalvalue.h" struct icaldurationtype icaldurationtype_from_string(const char* str) { - icalvalue *v = icalvalue_new_from_string(ICAL_DURATION_VALUE,str); + int i; + int begin_flag = 0; + int time_flag = 0; + int date_flag = 0; + int week_flag = 0; + int digits=-1; + int scan_size = -1; + int size = strlen(str); + char p; + struct icaldurationtype d; + + memset(&d, 0, sizeof(struct icaldurationtype)); + + for(i=0;i != size;i++){ + p = str[i]; + + switch(p) + { + case '-': { + if(i != 0 || begin_flag == 1) goto error; + + d.is_neg = 1; + break; + } + + case 'P': { + if (i != 0 && i !=1 ) goto error; + begin_flag = 1; + break; + } + + case 'T': { + time_flag = 1; + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + + /* HACK. Skip any more digits if the l;ast one + read has not been assigned */ + if(digits != -1){ + break; + } + + if (begin_flag == 0) goto error; + /* Get all of the digits, not one at a time */ + scan_size = sscanf((char*)(str+i),"%d",&digits); + if(scan_size == 0) goto error; + break; + } + + case 'H': { + if (time_flag == 0||week_flag == 1||d.hours !=0||digits ==-1) + goto error; + d.hours = digits; digits = -1; + break; + } + case 'M': { + if (time_flag == 0||week_flag==1||d.minutes != 0||digits ==-1) + goto error; + d.minutes = digits; digits = -1; + break; + } + case 'S': { + if (time_flag == 0||week_flag==1||d.seconds!=0||digits ==-1) + goto error; + d.seconds = digits; digits = -1; + break; + } + case 'W': { + if (time_flag==1||date_flag==1||d.weeks!=0||digits ==-1) + goto error; + week_flag = 1; + d.weeks = digits; digits = -1; + break; + } + case 'D': { + if (time_flag==1||week_flag==1||d.days!=0||digits ==-1) + goto error; + date_flag = 1; + d.days = digits; digits = -1; + break; + } + default: { + goto error; + } + + } + } + + return d; + + + error: + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + memset(&d, 0, sizeof(struct icaldurationtype)); + return d; + +} + +#define TMP_BUF_SIZE 1024 +void append_duration_segment(char** buf, char** buf_ptr, size_t* buf_size, + char* sep, unsigned int value) { + + char temp[TMP_BUF_SIZE]; + + sprintf(temp,"%d",value); + + icalmemory_append_string(buf, buf_ptr, buf_size, temp); + icalmemory_append_string(buf, buf_ptr, buf_size, sep); + +} + +char* icaldurationtype_as_ical_string(struct icaldurationtype d) +{ - if( v !=0){ - return icalvalue_get_duration(v); + char *buf, *output_line; + size_t buf_size = 256; + char* buf_ptr = 0; + int seconds; + + buf = (char*)icalmemory_new_buffer(buf_size); + buf_ptr = buf; + + + seconds = icaldurationtype_as_int(d); + + if(seconds !=0){ + + if(d.is_neg == 1){ + icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-'); + } + + icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P'); + + if (d.weeks != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks); + } + + if (d.days != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days); + } + + if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) { + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T"); + + if (d.hours != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours); + } + if (d.minutes != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "M", + d.minutes); + } + if (d.seconds != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "S", + d.seconds); + } + + } } else { - struct icaldurationtype dur; - memset(&dur,0,sizeof(struct icaldurationtype)); - return dur; + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PTS0"); } + output_line = icalmemory_tmp_copy(buf); + icalmemory_free_buffer(buf); + + return output_line; + } +#endif struct icaltimetype icaltime_add(struct icaltimetype t, struct icaldurationtype d) { - time_t tt = icaltime_as_timet(t); - time_t dt = icaldurationtype_as_timet(d); + int dt = icaldurationtype_as_int(d); + + t.second += dt; - return icaltime_from_timet(tt + dt, t.is_date, t.is_utc); + t = icaltime_normalize(t); + return t; } struct icaldurationtype icaltime_subtract(struct icaltimetype t1, @@ -421,7 +827,7 @@ struct icaldurationtype icaltime_subtract(struct icaltimetype t1, time_t t1t = icaltime_as_timet(t1); time_t t2t = icaltime_as_timet(t2); - return icaldurationtype_from_timet(t1t-t2t); + return icaldurationtype_from_int(t1t-t2t); } diff --git a/libical/src/libical/icaltime.h b/libical/src/libical/icaltime.h index 64617e578d..d624041c29 100644 --- a/libical/src/libical/icaltime.h +++ b/libical/src/libical/icaltime.h @@ -5,6 +5,7 @@ $Id$ + $Locker$ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org @@ -50,8 +51,38 @@ struct icaltimetype int is_utc; /* 1-> time is in UTC timezone */ int is_date; /* 1 -> interpret this as date. */ + + const char* zone; /*Ptr to Olsen placename. Libical does not own mem*/ }; +/* Convert seconds past UNIX epoch to a timetype*/ +struct icaltimetype icaltime_from_timet(time_t v, int is_date); +time_t icaltime_as_timet(struct icaltimetype); +char* icaltime_as_ical_string(struct icaltimetype tt); + +/* Like icaltime_from_timet(), except that the input may be in seconds + past the epoch in floating time */ +struct icaltimetype icaltime_from_int(int v, int is_date, int is_utc); +int icaltime_as_int(struct icaltimetype); + +/* create a time from an ISO format string */ +struct icaltimetype icaltime_from_string(const char* str); + +/* Routines for handling timezones */ +/* Return the offset of the named zone as seconds. tt is a time + indicating the date for which you want the offset */ +int icaltime_utc_offset(struct icaltimetype tt, const char* tzid); + +/* convert tt, of timezone tzid, into a utc time. Does nothing if the + time is already UTC. */ +struct icaltimetype icaltime_as_utc(struct icaltimetype tt, + const char* tzid); + +/* convert tt, a time in UTC, into a time in timezone tzid */ +struct icaltimetype icaltime_as_zone(struct icaltimetype tt, + const char* tzid); + + struct icaltimetype icaltime_null_time(void); int icaltime_is_null_time(struct icaltimetype t); @@ -64,9 +95,6 @@ struct icaltimetype icaltime_from_day_of_year(short doy, short year); short icaltime_day_of_week(struct icaltimetype t); short icaltime_start_doy_of_week(struct icaltimetype t); -struct icaltimetype icaltime_from_timet(time_t v, int is_date, int is_utc); -struct icaltimetype icaltime_from_string(const char* str); -time_t icaltime_as_timet(struct icaltimetype); char* icaltime_as_ctime(struct icaltimetype); short icaltime_week_number(short day_of_month, short month, short year); @@ -80,22 +108,6 @@ int icaltime_compare_date_only(struct icaltimetype a, struct icaltimetype b); short icaltime_days_in_month(short month,short year); -/* Routines for handling timezones */ - -/* Return the offset of the named zone as seconds. tt is a time - indicating the date for which you want the offset */ -time_t icaltime_utc_offset(struct icaltimetype tt, const char* tzid); - -time_t icaltime_local_utc_offset(); - - -/* convert tt, of timezone tzid, into a utc time */ -struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid); - -/* convert tt, a time in UTC, into a time in timezone tzid */ -struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid); - - struct icaldurationtype { @@ -107,9 +119,10 @@ struct icaldurationtype unsigned int seconds; }; -struct icaldurationtype icaldurationtype_from_timet(time_t t); +struct icaldurationtype icaldurationtype_from_int(int t); struct icaldurationtype icaldurationtype_from_string(const char*); -time_t icaldurationtype_as_timet(struct icaldurationtype duration); +int icaldurationtype_as_int(struct icaldurationtype duration); +char* icaldurationtype_as_ical_string(struct icaldurationtype d); struct icalperiodtype @@ -119,6 +132,9 @@ struct icalperiodtype struct icaldurationtype duration; }; +struct icalperiodtype icalperiodtype_from_string (const char* str); +const char* icalperiodtype_as_ical_string(struct icalperiodtype p); + time_t icalperiodtype_duration(struct icalperiodtype period); time_t icalperiodtype_end(struct icalperiodtype period); diff --git a/libical/src/libical/icaltypes.c b/libical/src/libical/icaltypes.c index e726904fcf..4afc8916bb 100644 --- a/libical/src/libical/icaltypes.c +++ b/libical/src/libical/icaltypes.c @@ -4,6 +4,7 @@ CREATOR: eric 16 May 1999 $Id$ + $Locker$ @@ -149,6 +150,42 @@ void* icalattachtype_get_binary(struct icalattachtype* v) } +struct icaltriggertype icaltriggertype_from_string(const char* str) +{ + + + struct icaltriggertype tr, null_tr; + int old_ieaf = icalerror_errors_are_fatal; + + tr.time= icaltime_null_time(); + tr.duration = icaldurationtype_from_int(0); + + null_tr = tr; + + if(str == 0) goto error; + + + icalerror_errors_are_fatal = 0; + + tr.time = icaltime_from_string(str); + + icalerror_errors_are_fatal = old_ieaf; + + if (icaltime_is_null_time(tr.time)){ + + tr.duration = icaldurationtype_from_string(str); + + if(icaldurationtype_as_int(tr.duration) == 0) goto error; + } + + return tr; + + error: + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return null_tr; + +} + struct icalreqstattype icalreqstattype_from_string(char* str) { diff --git a/libical/src/libical/icaltypes.h b/libical/src/libical/icaltypes.h index d2a106883b..ef4f874064 100644 --- a/libical/src/libical/icaltypes.h +++ b/libical/src/libical/icaltypes.h @@ -67,15 +67,13 @@ struct icalgeotype float lon; }; - - -union icaltriggertype +struct icaltriggertype { struct icaltimetype time; struct icaldurationtype duration; }; - +struct icaltriggertype icaltriggertype_from_string(const char* str); /* struct icalreqstattype. This struct contains two string pointers, but don't try to free either of them. The "desc" string is a pointer diff --git a/libical/src/libical/icalvalue.c.in b/libical/src/libical/icalvalue.c.in index ae48207f42..cdcd12ba83 100644 --- a/libical/src/libical/icalvalue.c.in +++ b/libical/src/libical/icalvalue.c.in @@ -3,7 +3,7 @@ FILE: icalvalue.c CREATOR: eric 02 May 1999 - $Id: icalvalue.c.in,v 1.2 2001/01/19 14:55:26 jpr Exp $ + $Id: icalvalue.c.in,v 1.3 2001/01/23 20:22:33 jpr Exp $ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org @@ -91,7 +91,7 @@ struct icalvalue_impl { a reference*/ struct icalrecurrencetype *v_recur; - union icaltriggertype v_trigger; + struct icaltriggertype v_trigger; icalproperty_method v_method; icalproperty_status v_status; @@ -197,7 +197,7 @@ icalvalue* icalvalue_new_clone(icalvalue* value){ char* icalmemory_strdup_and_dequote(const char* str) { - char* p; + const char* p; char* out = (char*)malloc(sizeof(char) * strlen(str) +1); char* pout; @@ -215,8 +215,9 @@ char* icalmemory_strdup_and_dequote(const char* str) switch(*p){ case 0: { - break; *pout = '\0'; + break; + } case 'n': { @@ -417,18 +418,56 @@ icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind,const char* } case ICAL_RECUR_VALUE: + { + struct icalrecurrencetype rt; + rt = icalrecurrencetype_from_string(str); + value = icalvalue_new_recur(rt); + break; + } + + case ICAL_TIME_VALUE: + { + struct icaltimetype tt; + tt = icaltime_from_string(str); + value = icalvalue_new_time(tt); + break; + } case ICAL_DATE_VALUE: + { + struct icaltimetype tt; + tt = icaltime_from_string(str); + value = icalvalue_new_date(tt); + break; + } case ICAL_DATETIME_VALUE: + { + struct icaltimetype tt; + tt = icaltime_from_string(str); + value = icalvalue_new_datetime(tt); + break; + } case ICAL_DATETIMEDATE_VALUE: + { + struct icaltimetype tt; + tt = icaltime_from_string(str); + value = icalvalue_new_datetimedate(tt); + break; + } + case ICAL_DATETIMEPERIOD_VALUE: - case ICAL_TIME_VALUE: - case ICAL_DURATION_VALUE: - case ICAL_PERIOD_VALUE: - case ICAL_TRIGGER_VALUE: + case ICAL_DURATION_VALUE: + case ICAL_PERIOD_VALUE: { value = icalparser_parse_value(kind,str,error); break; } + + case ICAL_TRIGGER_VALUE: + { + struct icaltriggertype tr = icaltriggertype_from_string(str); + value = icalvalue_new_trigger(tr); + break; + } default: { @@ -556,14 +595,15 @@ char* icalvalue_binary_as_ical_string(icalvalue* value) { } +#define MAX_INT_DIGITS 12 /* Enough for 2^32 + sign*/ char* icalvalue_int_as_ical_string(icalvalue* value) { int data; - char* str = (char*)icalmemory_tmp_buffer(2); + char* str = (char*)icalmemory_tmp_buffer(MAX_INT_DIGITS); icalerror_check_arg_rz( (value!=0),"value"); data = icalvalue_get_integer(value); - sprintf(str,"%d",data); + snprintf(str,MAX_INT_DIGITS,"%d",data); return str; } @@ -608,101 +648,10 @@ char* icalvalue_string_as_ical_string(icalvalue* value) { char* icalvalue_recur_as_ical_string(icalvalue* value) { - char* str; - char *str_p; - size_t buf_sz = 200; - char temp[20]; - int i,j; struct icalvalue_impl *impl = (struct icalvalue_impl*)value; struct icalrecurrencetype *recur = impl->data.v_recur; - struct { char* str;size_t offset; short limit; } recurmap[] = - { - {";BYSECOND=",offsetof(struct icalrecurrencetype,by_second),60}, - {";BYMINUTE=",offsetof(struct icalrecurrencetype,by_minute),60}, - {";BYHOUR=",offsetof(struct icalrecurrencetype,by_hour),24}, - {";BYDAY=",offsetof(struct icalrecurrencetype,by_day),7}, - {";BYMONTHDAY=",offsetof(struct icalrecurrencetype,by_month_day),31}, - {";BYYEARDAY=",offsetof(struct icalrecurrencetype,by_year_day),366}, - {";BYWEEKNO=",offsetof(struct icalrecurrencetype,by_week_no),52}, - {";BYMONTH=",offsetof(struct icalrecurrencetype,by_month),12}, - {";BYSETPOS=",offsetof(struct icalrecurrencetype,by_set_pos),366}, - {0,0,0}, - }; - - - - icalerror_check_arg_rz((value != 0),"value"); - - if(recur->freq == ICAL_NO_RECURRENCE){ - return 0; - } - - str = (char*)icalmemory_tmp_buffer(buf_sz); - str_p = str; - - icalmemory_append_string(&str,&str_p,&buf_sz,"FREQ="); - icalmemory_append_string(&str,&str_p,&buf_sz, - icalrecur_recurrence_to_string(recur->freq)); - - if(recur->until.year != 0){ - - temp[0] = 0; - print_datetime_to_string(temp,&(recur->until)); - - icalmemory_append_string(&str,&str_p,&buf_sz,";UNTIL="); - icalmemory_append_string(&str,&str_p,&buf_sz, temp); - } - - if(recur->count != 0){ - sprintf(temp,"%d",recur->count); - icalmemory_append_string(&str,&str_p,&buf_sz,";COUNT="); - icalmemory_append_string(&str,&str_p,&buf_sz, temp); - } - - if(recur->interval != 0){ - sprintf(temp,"%d",recur->interval); - icalmemory_append_string(&str,&str_p,&buf_sz,";INTERVAL="); - icalmemory_append_string(&str,&str_p,&buf_sz, temp); - } - - for(j =0; recurmap[j].str != 0; j++){ - short* array = (short*)(recurmap[j].offset+ (size_t)recur); - short limit = recurmap[j].limit; - - /* Skip unused arrays */ - if( array[0] != ICAL_RECURRENCE_ARRAY_MAX ) { - - icalmemory_append_string(&str,&str_p,&buf_sz,recurmap[j].str); - - for(i=0; i< limit && array[i] != ICAL_RECURRENCE_ARRAY_MAX; - i++){ - if (j == 3) { /* BYDAY */ - short dow = icalrecurrencetype_day_day_of_week(array[i]); - const char *daystr = icalrecur_weekday_to_string(dow); - short pos = icalrecurrencetype_day_position(array[i]); - - if (pos == 0) - icalmemory_append_string(&str,&str_p,&buf_sz,daystr); - else { - sprintf(temp,"%d%s",pos,daystr); - icalmemory_append_string(&str,&str_p,&buf_sz,temp); - } - - } else { - sprintf(temp,"%d",array[i]); - icalmemory_append_string(&str,&str_p,&buf_sz, temp); - } - - if( (i+1)data.v_duration); + int b = icaldurationtype_as_int(implb->data.v_duration); + + if (a > b){ + return ICAL_XLICCOMPARETYPE_GREATER; + } else if (a < b){ + return ICAL_XLICCOMPARETYPE_LESS; + } else { + return ICAL_XLICCOMPARETYPE_EQUAL; + } + } + + case ICAL_TEXT_VALUE: case ICAL_URI_VALUE: case ICAL_CALADDRESS_VALUE: @@ -1278,7 +1196,6 @@ icalvalue_compare(icalvalue* a, icalvalue *b) case ICAL_DATE_VALUE: case ICAL_DATETIME_VALUE: case ICAL_DATETIMEDATE_VALUE: - case ICAL_DURATION_VALUE: /* HACK. Not correct for DURATION */ case ICAL_TIME_VALUE: case ICAL_DATETIMEPERIOD_VALUE: { @@ -1292,7 +1209,7 @@ icalvalue_compare(icalvalue* a, icalvalue *b) } else if (r < 0){ return ICAL_XLICCOMPARETYPE_LESS; } else { - return 0; + return ICAL_XLICCOMPARETYPE_EQUAL; } @@ -1350,9 +1267,7 @@ icalproperty* icalvalue_get_parent(icalvalue* value) -/* Recur is a special case, so it is not auto generated. Well, - actually, it is auto-generated, but you will have to manually - remove the auto-generated version after each generation. */ +/* Recur is a special case, so it is not auto generated. */ icalvalue* icalvalue_new_recur (struct icalrecurrencetype v) { diff --git a/libical/src/libical/icalyacc.y b/libical/src/libical/icalyacc.y index 0512d6b585..982682d331 100644 --- a/libical/src/libical/icalyacc.y +++ b/libical/src/libical/icalyacc.y @@ -6,7 +6,7 @@ DESCRIPTION: - $Id: icalyacc.y,v 1.10 2000/12/12 00:27:40 federico Exp $ + $Id: icalyacc.y,v 1.11 2001/01/23 20:22:33 jpr Exp $ $Locker: $ (C) COPYRIGHT 1999 Eric Busboom @@ -48,14 +48,10 @@ int utcsign; /* Globals for DURATION values */ struct icaldurationtype duration; -/* Globals for RECUR values */ -struct icalrecurrencetype recur; -short skiplist[367]; -short skippos; -int dow_pos; +/* Globals for TRIGGER values */ +struct icaltriggertype trigger; void copy_list(short* array, size_t size); -void clear_recur(); void add_prop(icalproperty_kind); void icalparser_fill_date(struct tm* t, char* dstr); void icalparser_fill_time(struct tm* t, char* tstr); @@ -179,13 +175,10 @@ int yylex(void); /* Or this. */ %% value: - binary_value - | boolean_value - | date_value + date_value | datetime_value | duration_value | period_value - | recur_value | utcoffset_value | error { icalparser_yy_value = 0; @@ -193,13 +186,6 @@ value: yyclearin; } -binary_value: "unimplemented2" - -boolean_value: - TRUE - { icalparser_yy_value = icalvalue_new_boolean(1); } - | FALSE - { icalparser_yy_value = icalvalue_new_boolean(0); } date_value: DIGITS { @@ -369,87 +355,9 @@ period_value: DIGITS TIME_CHAR DIGITS utc_char '/' DIGITS TIME_CHAR DIGITS utc } - -/* Recur */ - -recur_start: - FREQ EQUALS SECONDLY {clear_recur();recur.freq = ICAL_SECONDLY_RECURRENCE;} - | FREQ EQUALS MINUTELY {clear_recur();recur.freq = ICAL_MINUTELY_RECURRENCE;} - | FREQ EQUALS HOURLY {clear_recur();recur.freq = ICAL_HOURLY_RECURRENCE;} - | FREQ EQUALS DAILY {clear_recur();recur.freq = ICAL_DAILY_RECURRENCE;} - | FREQ EQUALS WEEKLY {clear_recur();recur.freq = ICAL_WEEKLY_RECURRENCE;} - | FREQ EQUALS MONTHLY {clear_recur();recur.freq = ICAL_MONTHLY_RECURRENCE;} - | FREQ EQUALS YEARLY {clear_recur();recur.freq = ICAL_YEARLY_RECURRENCE;} - ; - - -weekday: - SU { skiplist[skippos]=ICAL_SUNDAY_WEEKDAY; } - | MO { skiplist[skippos]=ICAL_MONDAY_WEEKDAY; } - | TU { skiplist[skippos]=ICAL_TUESDAY_WEEKDAY; } - | WE { skiplist[skippos]=ICAL_WEDNESDAY_WEEKDAY; } - | TH { skiplist[skippos]=ICAL_THURSDAY_WEEKDAY; } - | FR { skiplist[skippos]=ICAL_FRIDAY_WEEKDAY; } - | SA { skiplist[skippos]=ICAL_SATURDAY_WEEKDAY; } - ; - -/* HACK. The skippos has only 8 positions, but the spec permits any number */ - -weekday_list: - weekday {if( skippos<8) skippos++;} - | DIGITS weekday { dow_pos = atoi($1); - skiplist[skippos] += 8*dow_pos; if( skippos<8) skippos++; } - | MINUS DIGITS weekday { dow_pos = atoi($2); - skiplist[skippos] -= 8*dow_pos; if( skippos<8) skippos++; } - | weekday_list COMMA weekday {if( skippos<8) skippos++;}; - | weekday_list COMMA DIGITS weekday { dow_pos = atoi($3); - skiplist[skippos] += 8*dow_pos;if( skippos<8) skippos++;} - | weekday_list COMMA MINUS DIGITS weekday { dow_pos = atoi($4); - skiplist[skippos] -= 8*dow_pos;if( skippos<8) skippos++;} +trigger: -recur_list: - DIGITS { skiplist[skippos] = atoi($1); skippos++;} - | recur_list COMMA DIGITS { skiplist[skippos] = atoi($3); if (skippos<367) skippos++;} - ; - -recur_skip: - INTERVAL EQUALS DIGITS {recur.interval = atoi($3);} - | WKST EQUALS SU {recur.week_start = ICAL_SUNDAY_WEEKDAY;} - | WKST EQUALS MO {recur.week_start = ICAL_MONDAY_WEEKDAY;} - | WKST EQUALS TU {recur.week_start = ICAL_TUESDAY_WEEKDAY;} - | WKST EQUALS WE {recur.week_start = ICAL_WEDNESDAY_WEEKDAY;} - | WKST EQUALS TH {recur.week_start = ICAL_THURSDAY_WEEKDAY;} - | WKST EQUALS FR {recur.week_start = ICAL_FRIDAY_WEEKDAY;} - | WKST EQUALS SA {recur.week_start = ICAL_SATURDAY_WEEKDAY;} - | BYSECOND EQUALS recur_list{copy_list(recur.by_second,60);} - | BYMINUTE EQUALS recur_list{copy_list(recur.by_minute,60);} - | BYHOUR EQUALS recur_list{copy_list(recur.by_hour,24);} - | BYDAY EQUALS weekday_list{copy_list(recur.by_day,7);} - | BYMONTH EQUALS recur_list{copy_list(recur.by_month,12);} - | BYMONTHDAY EQUALS recur_list{copy_list(recur.by_month_day,31);} - | BYYEARDAY EQUALS recur_list{copy_list(recur.by_year_day,366);} - | BYWEEKNO EQUALS recur_list{copy_list(recur.by_week_no,53);} - | BYSETPOS EQUALS recur_list{copy_list(recur.by_set_pos,366);} - | UNTIL EQUALS datetime_value - { recur.until = icalvalue_get_datetime(icalparser_yy_value); - icalvalue_free(icalparser_yy_value); icalparser_yy_value=0;} - | UNTIL EQUALS date_value - { recur.until = icalvalue_get_date(icalparser_yy_value); - icalvalue_free(icalparser_yy_value); icalparser_yy_value=0;} - | COUNT EQUALS DIGITS - { recur.count = atoi($3); } - ; - -recur_skip_list: - /* empty */ - | recur_skip_list SEMICOLON recur_skip - -recur_value: - recur_start recur_skip_list - { icalparser_yy_value = icalvalue_new_recur(recur); } - - /* UTC Offset */ @@ -467,26 +375,8 @@ utcoffset_value: icalparser_yy_value = icalvalue_new_utcoffset(utcsign * ($2*3600) + ($3*60) +($4)); } - - %% - -void clear_recur() -{ - memset(&skiplist, ICAL_RECURRENCE_ARRAY_MAX_BYTE, sizeof(skiplist)); - skippos = 0; - - icalrecurrencetype_clear(&recur); -} - -void copy_list(short* array, size_t size) -{ - memcpy(array, skiplist, size*sizeof(short)); - memset(&skiplist,ICAL_RECURRENCE_ARRAY_MAX_BYTE, sizeof(skiplist)); - skippos = 0; -} - struct icaltimetype fill_datetime(char* datestr, char* timestr) { struct icaltimetype stm; diff --git a/libical/src/libicalss/Makefile.am b/libical/src/libicalss/Makefile.am index 0cbecbedea..732d970738 100644 --- a/libical/src/libicalss/Makefile.am +++ b/libical/src/libicalss/Makefile.am @@ -17,12 +17,12 @@ libicalss_la_LDFLAGS = -version-info 0:0:0 libicalss_la_SOURCES = \ icalclassify.c \ + icalgauge.c \ + icalgaugeimpl.h \ icaldirset.c \ icaldirsetimpl.h \ icalfileset.c \ icalfilesetimpl.h \ - icalgauge.c \ - icalgaugeimpl.h \ icalset.c \ icalsslexer.l \ icalssutil.c \ @@ -35,11 +35,11 @@ libicalss_la_SOURCES = \ libicalssincludedir = $(includedir) COMBINEDHEADERS = \ + icalgauge.h \ icalset.h \ icalfileset.h \ icaldirset.h \ icalcalendar.h \ - icalgauge.h \ icalssutil.h \ icalclassify.h \ icalspanlist.h \ diff --git a/libical/src/libicalss/icalcstp.h b/libical/src/libicalss/icalcstp.h index 63f5af913f..2ebccd622a 100644 --- a/libical/src/libicalss/icalcstp.h +++ b/libical/src/libicalss/icalcstp.h @@ -52,9 +52,10 @@ 1) Construct a new icalcstps, bound to your code via stubs 2) Repeat forever: - 2a) Get string from client & give to icalcstps_next_input() - 2b) Call icalcstps_next_output. Send string to client. - + 2a) Get string from client & give to icalcstps_next_input() + 2b) Repeat until icalcstp_next_output returns 0: + 2b1) Call icalcstps_next_output. + 2b2) Send string to client. */ @@ -101,11 +102,11 @@ int icalcstps_next_input(icalcstps* cstp); /* How to use: 1) Construct a new icalcstpc - 2) Issue a command + 2) Issue a command by calling one of the command routines. 3) Repeat until both call icalcstpc_next_output and icalcstpc_next_input return 0: - 3a) Call icalcstpc_next_output. Send string to server. - 3b) Get string from server, & give to icalcstp_next_input() + 3a) Call icalcstpc_next_output. Send string to server. + 3b) Get string from server, & give to icalcstp_next_input() 4) Iterate with icalcstpc_first_response & icalcstp_next_response to get the servers responses 5) Repeat at #2 diff --git a/libical/src/test/Makefile.am b/libical/src/test/Makefile.am index a2ebea7610..2830afdaa0 100644 --- a/libical/src/test/Makefile.am +++ b/libical/src/test/Makefile.am @@ -4,14 +4,14 @@ noinst_PROGRAMS = copycluster regression parser storage stow recur testmime test LDADD = ../libicalss/libicalss.la ../libicalvcal/libicalvcal.la ../libical/libical.la INCLUDES = \ - -I . \ + -I. \ -I../libicalvcal \ - -I $(srcdir)/../libicalvcal \ - -I $(srcdir) \ + -I$(srcdir)/../libicalvcal \ + -I$(srcdir) \ -I../libical \ - -I $(srcdir)/../libical \ + -I$(srcdir)/../libical \ -I../libicalss \ - -I $(srcdir)/../libicalss + -I$(srcdir)/../libicalss copycluster_SOURCES = copycluster.c regression_SOURCES = regression.c diff --git a/libical/src/test/icaltestparser.c b/libical/src/test/icaltestparser.c index 71f91b641f..e5973e0d4a 100644 --- a/libical/src/test/icaltestparser.c +++ b/libical/src/test/icaltestparser.c @@ -112,7 +112,6 @@ int main(int argc, char* argv[]) if (c != 0){ /*icalcomponent_convert_errors(c);*/ printf("%s",icalcomponent_as_ical_string(c)); - icalparser_claim(parser); printf("\n---------------\n"); icalcomponent_free(c); } diff --git a/libical/src/test/regression.c b/libical/src/test/regression.c index b14e8aa6f8..66307bb405 100644 --- a/libical/src/test/regression.c +++ b/libical/src/test/regression.c @@ -35,6 +35,10 @@ #include /* for malloc */ #include /* for printf */ #include /* for time() */ +#include /* for unlink, fork */ +#include /* For waitpid */ +#include /* For wait pid */ +#include /* for select */ /* This example creates and minipulates the ical object that appears @@ -89,8 +93,8 @@ icalcomponent* create_simple_component() icalcomponent* calendar; struct icalperiodtype rtime; - rtime.start = icaltime_from_timet( time(0),0,0); - rtime.end = icaltime_from_timet( time(0),0,0); + rtime.start = icaltime_from_timet( time(0),0); + rtime.end = icaltime_from_timet( time(0),0); rtime.end.hour++; @@ -119,12 +123,12 @@ icalcomponent* create_new_component() icalcomponent* timezone; icalcomponent* tzc; icalcomponent* event; - struct icaltimetype atime = icaltime_from_timet( time(0),0,0); + struct icaltimetype atime = icaltime_from_timet( time(0),0); struct icalperiodtype rtime; icalproperty* property; - rtime.start = icaltime_from_timet( time(0),0,0); - rtime.end = icaltime_from_timet( time(0),0,0); + rtime.start = icaltime_from_timet( time(0),0); + rtime.end = icaltime_from_timet( time(0),0); rtime.end.hour++; @@ -328,11 +332,11 @@ icalcomponent* create_new_component_with_va_args() { icalcomponent* calendar; - struct icaltimetype atime = icaltime_from_timet( time(0),0,0); + struct icaltimetype atime = icaltime_from_timet( time(0),0); struct icalperiodtype rtime; - rtime.start = icaltime_from_timet( time(0),0,0); - rtime.end = icaltime_from_timet( time(0),0,0); + rtime.start = icaltime_from_timet( time(0),0); + rtime.end = icaltime_from_timet( time(0),0); rtime.end.hour++; @@ -521,9 +525,9 @@ void test_values() icalvalue_free(copy); - v = icalvalue_new_date(icaltime_from_timet( time(0),0,0)); + v = icalvalue_new_date(icaltime_from_timet( time(0),0)); printf("date 1: %s\n",icalvalue_as_ical_string(v)); - icalvalue_set_date(v,icaltime_from_timet( time(0)+3600,0,0)); + icalvalue_set_date(v,icaltime_from_timet( time(0)+3600,0)); printf("date 2: %s\n",icalvalue_as_ical_string(v)); copy = icalvalue_new_clone(v); @@ -803,7 +807,7 @@ int test_store() icaldirset *s = icaldirset_new("store"); int i; - rtime.start = icaltime_from_timet( time(0),0,0); + rtime.start = icaltime_from_timet( time(0),0); cluster = icalfileset_new("clusterin.vcd"); @@ -946,7 +950,6 @@ int test_store() int test_compare() { icalvalue *v1, *v2; - icalcomponent *c, *gauge; v1 = icalvalue_new_caladdress("cap://value/1"); v2 = icalvalue_new_clone(v1); @@ -978,43 +981,19 @@ int test_compare() printf("%d\n",icalvalue_compare(v1,v2)); - - gauge = - icalcomponent_vanew( - ICAL_VCALENDAR_COMPONENT, - icalcomponent_vanew( - ICAL_VEVENT_COMPONENT, - icalproperty_vanew_comment( - "Comment", - icalparameter_new_xliccomparetype(ICAL_XLICCOMPARETYPE_EQUAL), - 0), - 0), - 0); - - c = icalcomponent_vanew( - ICAL_VEVENT_COMPONENT, - icalproperty_vanew_comment( - "Comment", - 0), - 0); - - printf("%s",icalcomponent_as_ical_string(gauge)); - - printf("%d\n",icalgauge_test(c,gauge)); - return 0; } void test_restriction() { icalcomponent *comp; - struct icaltimetype atime = icaltime_from_timet( time(0),0,0); + struct icaltimetype atime = icaltime_from_timet( time(0),0); int valid; struct icalperiodtype rtime; - rtime.start = icaltime_from_timet( time(0),0,0); - rtime.end = icaltime_from_timet( time(0),0,0); + rtime.start = icaltime_from_timet( time(0),0); + rtime.end = icaltime_from_timet( time(0),0); rtime.end.hour++; @@ -1098,7 +1077,7 @@ void test_calendar() icaldirset *s; icalcalendar* calendar = icalcalendar_new("calendar"); icalerrorenum error; - struct icaltimetype atime = icaltime_from_timet( time(0),0,0); + struct icaltimetype atime = icaltime_from_timet( time(0),0); comp = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, @@ -1139,36 +1118,56 @@ void test_calendar() void test_increment(void); -void test_recur() +void print_occur(struct icalrecurrencetype recur, struct icaltimetype start) { - icalvalue *v; - - v = icalvalue_new_from_string(ICAL_RECUR_VALUE, - "FREQ=DAILY;COUNT=5;BYDAY=MO,TU,WE,TH,FR"); + struct icaltimetype next; + icalrecur_iterator* ritr; + + time_t tt = icaltime_as_timet(start); - printf("%s\n",icalvalue_as_ical_string(v)); + printf("#### %s\n",icalrecurrencetype_as_string(&recur)); + printf("#### %s\n",ctime(&tt )); + + for(ritr = icalrecur_iterator_new(recur,start), + next = icalrecur_iterator_next(ritr); + !icaltime_is_null_time(next); + next = icalrecur_iterator_next(ritr)){ + + tt = icaltime_as_timet(next); + + printf(" %s",ctime(&tt )); + + } - v = icalvalue_new_from_string(ICAL_RECUR_VALUE, - "FREQ=YEARLY;UNTIL=123456T123456;BYSETPOS=-1,2"); + icalrecur_iterator_free(ritr); +} - printf("%s\n",icalvalue_as_ical_string(v)); +void test_recur() +{ + struct icalrecurrencetype rt; + struct icaltimetype start; + time_t array[25]; + int i; - v = icalvalue_new_from_string(ICAL_RECUR_VALUE, - "FREQ=YEARLY;UNTIL=123456T123456;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30"); + rt = icalrecurrencetype_from_string("FREQ=MONTHLY;UNTIL=19971224T000000Z;INTERVAL=1;BYDAY=TU,2FR,3SA"); + start = icaltime_from_string("19970905T090000Z"); - printf("%s\n",icalvalue_as_ical_string(v)); + print_occur(rt,start); - v = icalvalue_new_from_string(ICAL_RECUR_VALUE, - "FREQ=MONTHLY;BYDAY=-1MO,TU,WE,TH,FR"); + printf("\n Using icalrecur_expand_recurrence\n"); - printf("%s\n",icalvalue_as_ical_string(v)); + icalrecur_expand_recurrence("FREQ=MONTHLY;UNTIL=19971224T000000Z;INTERVAL=1;BYDAY=TU,2FR,3SA", + icaltime_as_timet(start), + 25, + array); - v = icalvalue_new_from_string(ICAL_RECUR_VALUE, - "FREQ=WEEKLY;INTERVAL=20;WKST=SU;BYDAY=TU"); + for(i =0; array[i] != 0 && i < 25 ; i++){ + + printf(" %s",ctime(&(array[i]))); + } - printf("%s\n",icalvalue_as_ical_string(v)); - - test_increment(); + +/* test_increment();*/ } @@ -1210,7 +1209,7 @@ void icalrecurrencetype_test() "FREQ=YEARLY;UNTIL=20060101T000000;INTERVAL=2;BYDAY=SU,WE;BYSECOND=15,30; BYMONTH=1,6,11"); struct icalrecurrencetype r = icalvalue_get_recur(v); - struct icaltimetype t = icaltime_from_timet( time(0), 0, 0); + struct icaltimetype t = icaltime_from_timet( time(0), 0); struct icaltimetype next; time_t tt; @@ -1228,129 +1227,124 @@ void icalrecurrencetype_test() } -void test_recur_expansion() -{ - - icalvalue *v; - - v = icalvalue_new_from_string(ICAL_RECUR_VALUE, - "FREQ=YEARLY;UNTIL=123456T123456;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30"); - - printf("%s\n",icalvalue_as_ical_string(v)); +/* From Federico Mena Quintero */ +void test_recur_parameter_bug(){ - icalrecurrencetype_test(); -} - -static const char test_icalcomp_str[] = +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + static const char test_icalcomp_str[] = "BEGIN:VEVENT\r\n" -"UID\r\n" -" :20001121T203327-22955-2183-22933-0@guanabana.helixcode.com\r\n" -"DTSTAMP\r\n" -" :20001121T203327\r\n" -"DTSTART\r\n" -" :20001121T170000\r\n" -"DTEND\r\n" -" :20001121T180000\r\n" -"SUMMARY\r\n" -" :recur on the second Friday every month\\, forever\r\n" -"SEQUENCE\r\n" -" :3\r\n" -"CLASS\r\n" -" :PRIVATE\r\n" "RRULE\r\n" -" :FREQ=MONTHLY;INTERVAL=1;BYDAY=-2WE,2FR,3SA,-2WE\n" +" ;X-EVOLUTION-ENDDATE=20030209T081500\r\n" +" :FREQ=DAILY;COUNT=10;INTERVAL=6\r\n" "END:VEVENT\r\n"; + + icalcomponent *icalcomp; + icalproperty *prop; + struct icalrecurrencetype recur; + int n_errors; + + icalcomp = icalparser_parse_string ((char *) test_icalcomp_str); + if (!icalcomp) { + fprintf (stderr, "main(): could not parse the component\n"); + exit (EXIT_FAILURE); + } + + printf("%s\n\n",icalcomponent_as_ical_string(icalcomp)); -void test_recur_bug() -{ - icalcomponent *icalcomp; - char *str; - icalproperty *prop; - struct icalrecurrencetype r; - - /* Print the original stuff */ - - puts ("The original component is:\n\n"); - puts (test_icalcomp_str); - - /* Parse the component */ + n_errors = icalcomponent_count_errors (icalcomp); + if (n_errors) { + icalproperty *p; - icalcomp = icalparser_parse_string ((char *) test_icalcomp_str); - - if (!icalcomp) { - fprintf (stderr, "main(): Could not parse the stuff\n"); - exit (EXIT_FAILURE); - } - - if (icalcomponent_isa (icalcomp) != ICAL_VEVENT_COMPONENT) { - fprintf (stderr, "main(): This is not the test data I want\n"); - exit (EXIT_FAILURE); - } - - /* Watch the property */ - - prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY); - if (!prop) { - fprintf (stderr, "main(): This is not the test data I want\n"); - exit (EXIT_FAILURE); + for (p = icalcomponent_get_first_property (icalcomp, + ICAL_XLICERROR_PROPERTY); + p; + p = icalcomponent_get_next_property (icalcomp, + ICAL_XLICERROR_PROPERTY)) { + char *str; + + str = icalproperty_as_ical_string (p); + fprintf (stderr, "error: %s\n", str); } + } + + prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY); + if (!prop) { + fprintf (stderr, "main(): could not get the RRULE property"); + exit (EXIT_FAILURE); + } + + recur = icalproperty_get_rrule (prop); + + printf("%s\n",icalrecurrencetype_as_string(&recur)); - r = icalproperty_get_rrule (prop); - printf ("\nThe first BYDAY element is %d\n", r.by_day[0]); +} - printf ("Position is %d, weekday is %d\n", - icalrecurrencetype_day_position (r.by_day[0]), - (int) icalrecurrencetype_day_day_of_week (r.by_day[0])); - /* Re-stringify */ +void test_duration() +{ - puts ("\nThe component looks like this after re-stringification:\n\n"); - str = icalcomponent_as_ical_string (icalcomp); - if (!str) { - fprintf (stderr, "main(): Could not stringify the component\n"); - exit (EXIT_FAILURE); - } + struct icaldurationtype d; - puts (str); - puts ("\n"); + d = icaldurationtype_from_string("PT8H30M"); + printf("%s\n",icaldurationtype_as_ical_string(d)); + assert(icaldurationtype_as_int(d) == 30600); + + d = icaldurationtype_from_string("-PT8H30M"); + printf("%s\n",icaldurationtype_as_ical_string(d)); + assert(icaldurationtype_as_int(d) == -30600); -} + d = icaldurationtype_from_string("PT10H10M10S"); + printf("%s\n",icaldurationtype_as_ical_string(d)); + assert(icaldurationtype_as_int(d) == 36610); + d = icaldurationtype_from_string("P7W"); + printf("%s\n",icaldurationtype_as_ical_string(d)); + assert(icaldurationtype_as_int(d) == 4233600); -void test_duration() -{ + d = icaldurationtype_from_string("P2DT8H30M"); + printf("%s\n",icaldurationtype_as_ical_string(d)); + assert(icaldurationtype_as_int(d) == 203400); - icalvalue *v; + icalerror_errors_are_fatal = 0; - v = icalvalue_new_from_string(ICAL_DURATION_VALUE, - "PT8H30M"); + d = icaldurationtype_from_string("P-2DT8H30M"); + printf("%s\n",icaldurationtype_as_ical_string(d)); + assert(icaldurationtype_as_int(d) == 0); - printf("%s\n",icalvalue_as_ical_string(v)); + d = icaldurationtype_from_string("P7W8H"); + printf("%s\n",icaldurationtype_as_ical_string(d)); + assert(icaldurationtype_as_int(d) == 0); + d = icaldurationtype_from_string("T10H"); + printf("%s\n",icaldurationtype_as_ical_string(d)); + assert(icaldurationtype_as_int(d) == 0); - v = icalvalue_new_from_string(ICAL_DURATION_VALUE, - "-PT8H30M"); - printf("%s\n",icalvalue_as_ical_string(v)); + icalerror_errors_are_fatal = 1; - icalvalue_free(v); - v = icalvalue_new_from_string(ICAL_PERIOD_VALUE, - "19971015T050000Z/PT8H30M"); +} - printf("%s\n",icalvalue_as_ical_string(v)); +void test_period() +{ - icalvalue_free(v); - v = icalvalue_new_from_string(ICAL_PERIOD_VALUE, - "19971015T050000Z/19971015T060000Z"); + struct icalperiodtype p; - printf("%s\n",icalvalue_as_ical_string(v)); - icalvalue_free(v); + p = icalperiodtype_from_string("19971015T050000Z/PT8H30M"); + printf("%s\n",icalperiodtype_as_ical_string(p)); + p = icalperiodtype_from_string("19971015T050000Z/19971015T060000Z"); + printf("%s\n",icalperiodtype_as_ical_string(p)); } - void test_strings(){ icalvalue *v; @@ -1423,62 +1417,117 @@ void test_requeststat() st2 = icalreqstattype_from_string("2.1"); printf("%s\n",icalreqstattype_as_string(st2)); +#ifndef ICAL_ERRORS_ARE_FATAL st2 = icalreqstattype_from_string("16.4"); assert(st2.code == ICAL_UNKNOWN_STATUS); st2 = icalreqstattype_from_string("1."); assert(st2.code == ICAL_UNKNOWN_STATUS); - +#endif } char ictt_str[1024]; char* ictt_as_string(struct icaltimetype t) { - sprintf(ictt_str,"%02d-%02d-%02d %02d:%02d:%02d %c",t.year,t.month,t.day, - t.hour,t.minute,t.second,t.is_utc?'Z':' '); + sprintf(ictt_str,"%02d-%02d-%02d %02d:%02d:%02d%s",t.year,t.month,t.day, + t.hour,t.minute,t.second,t.is_utc?" Z":""); return ictt_str; } -void test_time() + +char* ical_timet_string(time_t t) +{ + struct tm stm = *(gmtime(&t)); + + sprintf(ictt_str,"%02d-%02d-%02d %02d:%02d:%02d Z",stm.tm_year+1900, + stm.tm_mon+1,stm.tm_mday,stm.tm_hour,stm.tm_min,stm.tm_sec); + + return ictt_str; + +} + +void do_test_time(char* zone) { - struct icaltimetype ictt, icttutc, icttny,icttphoenix; - time_t tt,tt2; + struct icaltimetype ictt, icttutc, icttutczone, icttdayl, + icttla, icttny,icttphoenix, icttlocal, icttnorm; + time_t tt,tt2, tt_p200; + int offset_la, offset_tz; icalvalue *v; short day_of_week,start_day_of_week, day_of_year; + icalerror_errors_are_fatal = 0; - tt = 973276230; /* Fri Nov 3 10:30:30 PST 2000 in UTC */ + ictt = icaltime_from_string("20001103T183030Z"); - printf("\n Convert to and from lib c \n"); + tt = icaltime_as_timet(ictt); + + assert(tt==973276230); /* Fri Nov 3 10:30:30 PST 2000 in PST + Fri Nov 3 18:30:30 PST 2000 in UTC */ + + offset_la = icaltime_utc_offset(ictt,"America/Los_Angeles"); + offset_tz = icaltime_utc_offset(ictt, zone); + + printf(" Normalize \n"); + printf("Orig (ical) : %s\n", ictt_as_string(ictt)); + icttnorm = ictt; + icttnorm.second -= 60 * 60 * 24 * 5; + icttnorm = icaltime_normalize(ictt); + printf("-5d in sec : %s\n", ictt_as_string(icttnorm)); + icttnorm.day += 60; + icttnorm = icaltime_normalize(ictt); + printf("+60 d : %s\n", ictt_as_string(icttnorm)); + + + printf("\n As time_t \n"); + + tt2 = icaltime_as_timet(ictt); + printf("20001103T183030Z (timet): %s\n",ical_timet_string(tt2)); + printf("20001103T183030Z : %s\n",ictt_as_string(ictt)); + assert(tt2 == tt); + + icttlocal = icaltime_from_string("20001103T183030"); + tt2 = icaltime_as_timet(icttlocal); + printf("20001103T183030 (timet): %s\n",ical_timet_string(tt2)); + printf("20001103T183030 : %s\n",ictt_as_string(icttlocal)); + assert(tt-tt2 == offset_tz); + + printf("\n From time_t \n"); - printf("System time is: %s",ctime(&tt)); + printf("Orig : %s\n",ical_timet_string(tt)); + printf("As utc : %s\n", ictt_as_string(ictt)); - ictt = icaltime_from_timet(tt,0,0); + icttlocal = icaltime_as_zone(ictt,zone); + printf("As local : %s\n", ictt_as_string(icttlocal)); + + + printf("\n Convert to and from lib c \n"); + + printf("System time is: %s\n",ical_timet_string(tt)); v = icalvalue_new_datetime(ictt); printf("System time from libical: %s\n",icalvalue_as_ical_string(v)); tt2 = icaltime_as_timet(ictt); - printf("Converted back to libc: %s",ctime(&tt2)); + printf("Converted back to libc: %s\n",ical_timet_string(tt2)); printf("\n Incrementing time \n"); - ictt.year++; - tt2 = icaltime_as_timet(ictt); - printf("Add a year: %s\n",ctime(&tt2)); + icttnorm = ictt; - ictt.month+=13; - tt2 = icaltime_as_timet(ictt); - printf("Add 13 months: %s",ctime(&tt2)); + icttnorm.year++; + tt2 = icaltime_as_timet(icttnorm); + printf("Add a year: %s\n",ical_timet_string(tt2)); - ictt.second+=90; - tt2 = icaltime_as_timet(ictt); - printf("Add 90 seconds: %s",ctime(&tt2)); + icttnorm.month+=13; + tt2 = icaltime_as_timet(icttnorm); + printf("Add 13 months: %s\n",ical_timet_string(tt2)); - ictt = icaltime_from_timet(tt,0,0); + icttnorm.second+=90; + tt2 = icaltime_as_timet(icttnorm); + printf("Add 90 seconds: %s\n",ical_timet_string(tt2)); printf("\n Day Of week \n"); @@ -1486,34 +1535,76 @@ void test_time() start_day_of_week = icaltime_start_doy_of_week(ictt); day_of_year = icaltime_day_of_year(ictt); + printf("Today is day of week %d, day of year %d\n",day_of_week,day_of_year); printf("Week started n doy of %d\n",start_day_of_week); + assert(day_of_week == 6); + assert(day_of_year == 308); + assert(start_day_of_week == 303 ); - printf("\n To and From UTC\n"); + printf("\n TimeZone Conversions \n"); - ictt = icaltime_from_timet(tt,0,1); - printf("As utc : %s\n", ictt_as_string(ictt)); - ictt = icaltime_from_timet(tt,0,0); - printf("As local : %s\n", ictt_as_string(ictt)); - + icttla = icaltime_as_zone(ictt,"America/Los_Angeles"); + assert(icttla.hour == 10); + icttutc = icaltime_as_utc(icttla,"America/Los_Angeles"); + assert(icaltime_compare(icttla, + icaltime_from_string("20001103T103030"))==0); - printf("\n TimeZone Conversions \n"); + icttutczone = icaltime_as_zone(ictt,"Etc/GMT0"); + icttutczone.is_utc = 1; + assert(icaltime_compare(icttutc, icttutczone) == 0); + assert(icaltime_compare(icttutc, ictt) == 0); + + icttny = icaltime_as_zone(ictt,"America/New_York"); + + icttphoenix = icaltime_as_zone(ictt,"America/Phoenix"); + + printf("Orig (ctime): %s\n", ical_timet_string(tt) ); + printf("Orig (ical) : %s\n", ictt_as_string(ictt)); + printf("UTC : %s\n", ictt_as_string(icttutc)); + printf("Los Angeles : %s\n", ictt_as_string(icttla)); + printf("Phoenix : %s\n", ictt_as_string(icttphoenix)); + printf("New York : %s\n", ictt_as_string(icttny)); + + + /* Daylight savings test for New York */ + printf("\n Daylight Savings \n"); - ictt = icaltime_from_timet(tt,0,1); + printf("Orig (ctime): %s\n", ical_timet_string(tt) ); + printf("Orig (ical) : %s\n", ictt_as_string(ictt)); + printf("NY : %s\n", ictt_as_string(icttny)); + + assert(strcmp(ictt_as_string(icttny),"2000-11-03 13:30:30")==0); + + tt_p200 = tt + 200 * 24 * 60 * 60 ; /* Add 200 days */ + + icttdayl = icaltime_from_timet(tt_p200,0); + icttny = icaltime_as_zone(icttdayl,"America/New_York"); - icttutc = icaltime_as_utc(ictt,"America/Los_Angeles"); + printf("Orig +200d : %s\n", ical_timet_string(tt_p200) ); + printf("NY+200D : %s\n", ictt_as_string(icttny)); + + assert(strcmp(ictt_as_string(icttny),"2001-05-22 14:30:30")==0); - icttny = icaltime_as_zone(icttutc,"America/New_York"); + /* Daylight savings test for Los Angeles */ - icttphoenix = icaltime_as_zone(icttutc,"America/Phoenix"); + icttla = icaltime_as_zone(ictt,"America/Los_Angeles"); + + printf("\nOrig (ctime): %s\n", ical_timet_string(tt) ); + printf("Orig (ical) : %s\n", ictt_as_string(ictt)); + printf("LA : %s\n", ictt_as_string(icttla)); + + assert(strcmp(ictt_as_string(icttla),"2000-11-03 10:30:30")==0); + + icttla = icaltime_as_zone(icttdayl,"America/Los_Angeles"); + + printf("Orig +200d : %s\n", ical_timet_string(tt_p200) ); + printf("LA+200D : %s\n", ictt_as_string(icttla)); - printf("Orig : %s", ctime(&tt) ); - printf("UTC : %s\n", ictt_as_string(icttutc)); - printf("Los Angeles: %s\n", ictt_as_string(ictt)); - printf("Phoenix : %s\n", ictt_as_string(icttphoenix)); - printf("New York : %s\n", ictt_as_string(icttny)); + assert(strcmp(ictt_as_string(icttla),"2001-05-22 11:30:30")==0); + icalerror_errors_are_fatal = 1; } void test_iterators() @@ -1655,6 +1746,91 @@ void test_iterators() } + +char* test_set_tz(const char* tzid) +{ + char *tzstr = 0; + char *tmp; + + /* Put the new time zone into the environment */ + if(getenv("TZ") != 0){ + tzstr = (char*)strdup(getenv("TZ")); + + if(tzstr == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + } + + tmp = (char*)malloc(1024); + + if(tmp == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + snprintf(tmp,1024,"TZ=%s",tzid); + + /* HACK. In some libc versions, putenv gives the string to the + system and in some it gives a copy, so the following might be a + memory leak. THe linux man page says that glibc2.1.2 take + ownership ( no leak) while BSD4.4 uses a copy ( A leak ) */ + putenv(tmp); + + return tzstr; /* This will be zero if the TZ env var was not set */ +} + +void test_unset_tz(char* tzstr) +{ + /* restore the original environment */ + + if(tzstr!=0){ + char temp[1024]; + snprintf(temp,1024,"TZ=%s",tzstr); + putenv(temp); + free(tzstr); + } else { + putenv("TZ"); /* Delete from environment */ + } +} + + +void test_time() +{ + char zones[6][40] = { "America/Los_Angeles","America/New_York","Europe/London","Asia/Shanghai", ""}; + int i; + char* old_tz; + int orig_month; + time_t tt; + struct tm stm; + + tt = time(0); + + stm = *(localtime(&tt)); + + orig_month = stm.tm_mon; + + do_test_time(0); + + old_tz = test_set_tz(zones[0]); + + for(i = 0; zones[i][0] != 0; i++){ + + if(zones[i][0] != 0){ + test_set_tz(zones[i]); + } + + printf(" ######### Timezone: %s ############\n",zones[i]); + + do_test_time(zones[i]); + + } + + test_unset_tz(old_tz); + +} + + void test_icalset() { icalcomponent *c; @@ -1698,9 +1874,13 @@ void test_classify() void print_span(int c, struct icaltime_span span ){ - printf("#%02d start: %s",c,ctime(&span.start)); - printf(" end : %s",ctime(&span.end)); + printf("#%02d start: %s\n",c,ical_timet_string(span.start)); + printf(" end : %s\n",ical_timet_string(span.end)); + +} +struct icaltimetype icaltime_as_local(struct icaltimetype tt) { + return icaltime_as_zone(tt,0); } void test_span() @@ -1724,9 +1904,11 @@ void test_span() c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0,0), + icalproperty_vanew_dtstart( + icaltime_as_local(icaltime_from_timet(tm1,0)), icalparameter_new_tzid("US/Pacific"),0), - icalproperty_vanew_dtend(icaltime_from_timet(tm2,0,0), + icalproperty_vanew_dtend( + icaltime_as_local(icaltime_from_timet(tm2,0)), icalparameter_new_tzid("US/Pacific"),0), 0 ); @@ -1737,12 +1919,14 @@ void test_span() print_span(1,span); + icalcomponent_free(c); + /* Use machine's local timezone. Same as above if run in US/Pacific */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0,0),0), - icalproperty_vanew_dtend(icaltime_from_timet(tm2,0,0),0), + icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0),0), + icalproperty_vanew_dtend(icaltime_from_timet(tm2,0),0), 0 ); @@ -1750,38 +1934,49 @@ void test_span() print_span(2,span); + icalcomponent_free(c); + /* Specify different timezone */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0,0), + icalproperty_vanew_dtstart( + icaltime_as_local(icaltime_from_timet(tm1,0)), icalparameter_new_tzid("US/Eastern"),0), - icalproperty_vanew_dtend(icaltime_from_timet(tm2,0,0), + icalproperty_vanew_dtend( + icaltime_as_local(icaltime_from_timet(tm2,0)), icalparameter_new_tzid("US/Eastern"),0), 0 ); span = icalcomponent_get_span(c); print_span(3,span); + icalcomponent_free(c); + + /* Specify different timezone for start and end*/ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0,0), + icalproperty_vanew_dtstart( + icaltime_as_local(icaltime_from_timet(tm1,0)), icalparameter_new_tzid("US/Eastern"),0), - icalproperty_vanew_dtend(icaltime_from_timet(tm2,0,0), + icalproperty_vanew_dtend( + icaltime_as_local(icaltime_from_timet(tm2,0)), icalparameter_new_tzid("US/Pacific"),0), 0 ); span = icalcomponent_get_span(c); print_span(4,span); + icalcomponent_free(c); /* Use Duration */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0,0), + icalproperty_vanew_dtstart( + icaltime_as_local(icaltime_from_timet(tm1,0)), icalparameter_new_tzid("US/Pacific"),0), icalproperty_new_duration(dur), @@ -1790,21 +1985,27 @@ void test_span() span = icalcomponent_get_span(c); print_span(5,span); + icalcomponent_free(c); + + #ifndef ICAL_ERRORS_ARE_FATAL /* Both UTC and Timezone -- an error */ icalerror_clear_errno(); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0,1), + icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0), icalparameter_new_tzid("US/Eastern"),0), - icalproperty_vanew_dtend(icaltime_from_timet(tm2,0,1), + icalproperty_vanew_dtend(icaltime_from_timet(tm2,0), icalparameter_new_tzid("US/Eastern"),0), 0 ); span = icalcomponent_get_span(c); assert(icalerrno != ICAL_NO_ERROR); + + icalcomponent_free(c); + #endif /*ICAL_ERRORS_ARE_FATAL*/ } @@ -1813,6 +2014,8 @@ icalcomponent* icalclassify_find_overlaps(icalset* set, icalcomponent* comp); void test_overlaps() { + +#if 0 /* Hack, not working right now */ icalcomponent *cset,*c; icalset *set; time_t tm1 = 973378800; /*Sat Nov 4 23:00:00 UTC 2000, @@ -1827,8 +2030,8 @@ void test_overlaps() printf("-- 1 -- \n"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1-hh,0,1),0), - icalproperty_vanew_dtend(icaltime_from_timet(tm2-hh,0,1),0), + icalproperty_vanew_dtstart(icaltime_from_timet(tm1-hh,0),0), + icalproperty_vanew_dtend(icaltime_from_timet(tm2-hh,0),0), 0 ); @@ -1839,8 +2042,8 @@ void test_overlaps() printf("-- 2 -- \n"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1-hh,0,1),0), - icalproperty_vanew_dtend(icaltime_from_timet(tm2,0,1),0), + icalproperty_vanew_dtstart(icaltime_from_timet(tm1-hh,0),0), + icalproperty_vanew_dtend(icaltime_from_timet(tm2,0),0), 0 ); @@ -1851,8 +2054,8 @@ void test_overlaps() printf("-- 3 -- \n"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_vanew_dtstart(icaltime_from_timet(tm1+5*hh,0,1),0), - icalproperty_vanew_dtend(icaltime_from_timet(tm2+5*hh,0,1),0), + icalproperty_vanew_dtstart(icaltime_from_timet(tm1+5*hh,0),0), + icalproperty_vanew_dtend(icaltime_from_timet(tm2+5*hh,0),0), 0 ); @@ -1860,6 +2063,8 @@ void test_overlaps() printf("%s\n",icalcomponent_as_ical_string(cset)); +#endif + } void test_fblist() @@ -1869,14 +2074,14 @@ void test_fblist() struct icalperiodtype period; sl = icalspanlist_new(set, - icaltime_from_string("19970324T1200Z"), + icaltime_from_string("19970324T120000Z"), icaltime_from_string("19990424T020000Z")); printf("Restricted spanlist\n"); icalspanlist_dump(sl); period= icalspanlist_next_free_time(sl, - icaltime_from_string("19970801T1200Z")); + icaltime_from_string("19970801T120000Z")); printf("Next Free time: %s\n",icaltime_as_ctime(period.start)); @@ -1888,7 +2093,7 @@ void test_fblist() printf("Unrestricted spanlist\n"); sl = icalspanlist_new(set, - icaltime_from_string("19970324T1200Z"), + icaltime_from_string("19970324T120000Z"), icaltime_null_time()); printf("Restricted spanlist\n"); @@ -1896,7 +2101,7 @@ void test_fblist() icalspanlist_dump(sl); period= icalspanlist_next_free_time(sl, - icaltime_from_string("19970801T1200Z")); + icaltime_from_string("19970801T120000Z")); printf("Next Free time: %s\n",icaltime_as_ctime(period.start)); @@ -1917,8 +2122,8 @@ void test_convenience(){ ICAL_VCALENDAR_COMPONENT, icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_new_dtstart(icaltime_from_string("19970801T1200")), - icalproperty_new_dtend(icaltime_from_string("19970801T1300")), + icalproperty_new_dtstart(icaltime_from_string("19970801T120000")), + icalproperty_new_dtend(icaltime_from_string("19970801T130000")), 0 ), 0); @@ -1926,7 +2131,7 @@ void test_convenience(){ printf("** 1 DTSTART and DTEND **\n%s\n\n", icalcomponent_as_ical_string(c)); - duration = icaldurationtype_as_timet(icalcomponent_get_duration(c))/60; + duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60; printf("Start: %s\n",ictt_as_string(icalcomponent_get_dtstart(c))); printf("End: %s\n",ictt_as_string(icalcomponent_get_dtend(c))); @@ -1938,7 +2143,7 @@ void test_convenience(){ ICAL_VCALENDAR_COMPONENT, icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_new_dtstart(icaltime_from_string("19970801T1200Z")), + icalproperty_new_dtstart(icaltime_from_string("19970801T120000Z")), icalproperty_new_duration(icaldurationtype_from_string("PT1H30M")), 0 ), @@ -1947,7 +2152,7 @@ void test_convenience(){ printf("\n** 2 DTSTART and DURATION **\n%s\n\n", icalcomponent_as_ical_string(c)); - duration = icaldurationtype_as_timet(icalcomponent_get_duration(c))/60; + duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60; printf("Start: %s\n",ictt_as_string(icalcomponent_get_dtstart(c))); printf("End: %s\n",ictt_as_string(icalcomponent_get_dtend(c))); @@ -1959,8 +2164,8 @@ void test_convenience(){ ICAL_VCALENDAR_COMPONENT, icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_new_dtstart(icaltime_from_string("19970801T1200")), - icalproperty_new_dtend(icaltime_from_string("19970801T1300")), + icalproperty_new_dtstart(icaltime_from_string("19970801T120000")), + icalproperty_new_dtend(icaltime_from_string("19970801T130000")), 0 ), 0); @@ -1970,7 +2175,7 @@ void test_convenience(){ printf("** 3 DTSTART and DTEND, Set DURATION **\n%s\n\n", icalcomponent_as_ical_string(c)); - duration = icaldurationtype_as_timet(icalcomponent_get_duration(c))/60; + duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60; printf("Start: %s\n",ictt_as_string(icalcomponent_get_dtstart(c))); printf("End: %s\n",ictt_as_string(icalcomponent_get_dtend(c))); @@ -1982,18 +2187,18 @@ void test_convenience(){ ICAL_VCALENDAR_COMPONENT, icalcomponent_vanew( ICAL_VEVENT_COMPONENT, - icalproperty_new_dtstart(icaltime_from_string("19970801T1200Z")), + icalproperty_new_dtstart(icaltime_from_string("19970801T120000Z")), icalproperty_new_duration(icaldurationtype_from_string("PT1H30M")), 0 ), 0); - icalcomponent_set_dtend(c,icaltime_from_string("19970801T1330Z")); + icalcomponent_set_dtend(c,icaltime_from_string("19970801T133000Z")); printf("\n** 4 DTSTART and DURATION, set DTEND **\n%s\n\n", icalcomponent_as_ical_string(c)); - duration = icaldurationtype_as_timet(icalcomponent_get_duration(c))/60; + duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60; printf("Start: %s\n",ictt_as_string(icalcomponent_get_dtstart(c))); printf("End: %s\n",ictt_as_string(icalcomponent_get_dtend(c))); @@ -2009,14 +2214,14 @@ void test_convenience(){ ), 0); - icalcomponent_set_dtstart(c,icaltime_from_string("19970801T1200Z")); - icalcomponent_set_dtend(c,icaltime_from_string("19970801T1330Z")); + icalcomponent_set_dtstart(c,icaltime_from_string("19970801T120000Z")); + icalcomponent_set_dtend(c,icaltime_from_string("19970801T133000Z")); printf("\n** 5 Set DTSTART and DTEND **\n%s\n\n", icalcomponent_as_ical_string(c)); - duration = icaldurationtype_as_timet(icalcomponent_get_duration(c))/60; + duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60; printf("Start: %s\n",ictt_as_string(icalcomponent_get_dtstart(c))); printf("End: %s\n",ictt_as_string(icalcomponent_get_dtend(c))); @@ -2033,14 +2238,14 @@ void test_convenience(){ 0); - icalcomponent_set_dtstart(c,icaltime_from_string("19970801T1200Z")); + icalcomponent_set_dtstart(c,icaltime_from_string("19970801T120000Z")); icalcomponent_set_duration(c,icaldurationtype_from_string("PT1H30M")); printf("\n** 6 Set DTSTART and DURATION **\n%s\n\n", icalcomponent_as_ical_string(c)); - duration = icaldurationtype_as_timet(icalcomponent_get_duration(c))/60; + duration = icaldurationtype_as_int(icalcomponent_get_duration(c))/60; printf("Start: %s\n",ictt_as_string(icalcomponent_get_dtstart(c))); printf("End: %s\n",ictt_as_string(icalcomponent_get_dtend(c))); @@ -2050,92 +2255,824 @@ void test_convenience(){ } -int main(int argc, char *argv[]) +void test_time_parser() { + struct icaltimetype tt; - printf("\n------------Test recur bug ----------\n"); - test_recur_bug(); + icalerror_errors_are_fatal = 0; - exit(0); + tt = icaltime_from_string("19970101T1000"); + assert(icaltime_is_null_time(tt)); - printf("\n------------Test recur---------------\n"); - test_recur(); + tt = icaltime_from_string("19970101X100000"); + assert(icaltime_is_null_time(tt)); - printf("\n------------Test FBlist------------\n"); - test_fblist(); + tt = icaltime_from_string("19970101T100000"); + assert(!icaltime_is_null_time(tt)); + printf("%s\n",icaltime_as_ctime(tt)); - printf("\n------------Test time----------------\n"); - test_time(); + tt = icaltime_from_string("19970101T100000Z"); + assert(!icaltime_is_null_time(tt)); + printf("%s\n",icaltime_as_ctime(tt)); + tt = icaltime_from_string("19970101"); + assert(!icaltime_is_null_time(tt)); + printf("%s\n",icaltime_as_ctime(tt)); - printf("\n------------Test Overlaps------------\n"); - test_overlaps(); + icalerror_errors_are_fatal = 1; +} - printf("\n------------Test Span----------------\n"); - test_span(); +void test_recur_parser() +{ + struct icalrecurrencetype rt; + printf("FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1,2,3,4,8;BYYEARDAY=34,65,76,78;BYDAY=-1TU,3WE,-4FR,SU,SA\n"); - printf("\n------------Test duration---------------\n"); - test_duration(); + rt = icalrecurrencetype_from_string("FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1,2,3,4,8;BYYEARDAY=34,65,76,78;BYDAY=-1TU,3WE,-4FR,SU,SA"); - exit(0); + printf("%s\n\n",icalrecurrencetype_as_string(&rt)); - + printf("FREQ=DAILY;COUNT=3;BYMONTH=1,2,3,4,8;BYYEARDAY=34,65,76,78;BYDAY=-1TU,3WE,-4FR,SU,S\n"); - printf("\n------------Test Convenience ------------\n"); - test_convenience(); - + rt = icalrecurrencetype_from_string("FREQ=DAILY;COUNT=3;BYMONTH=1,2,3,4,8;BYYEARDAY=34,65,76,78;BYDAY=-1TU,3WE,-4FR,SU,SA"); + + printf("%s\n",icalrecurrencetype_as_string(&rt)); + +} +void test_doy() +{ + struct icaltimetype tt1, tt2; + short doy; - printf("\n------------Test classify ---------------\n"); - test_classify(); + tt1 = icaltime_from_string("19950301"); + doy = icaltime_day_of_year(tt1); + tt2 = icaltime_from_day_of_year(doy,1995); + printf("%d %s %s\n",doy, icaltime_as_ctime(tt1),icaltime_as_ctime(tt2)); - printf("\n------------Test Memory---------------\n"); - test_memory(); + tt1 = icaltime_from_string("19960301"); + doy = icaltime_day_of_year(tt1); + tt2 = icaltime_from_day_of_year(doy,1996); + printf("%d %s %s\n",doy, icaltime_as_ctime(tt1),icaltime_as_ctime(tt2)); + tt1 = icaltime_from_string("19970301"); + doy = icaltime_day_of_year(tt1); + tt2 = icaltime_from_day_of_year(doy,1997); + printf("%d %s %s\n",doy, icaltime_as_ctime(tt1),icaltime_as_ctime(tt2)); - printf("\n------------Test Iterators-----------\n"); - test_iterators(); - printf("\n------------Test Restriction---------------\n"); - test_restriction(); +} - printf("\n------------Test request status-------\n"); - test_requeststat(); - printf("\n------------Test strings---------------\n"); - test_strings(); +void test_x(){ - printf("\n------------Test Compare---------------\n"); - test_compare(); +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + static const char test_icalcomp_str[] = +"BEGIN:VEVENT\r\n" +"RRULE\r\n" +" ;X-EVOLUTION-ENDDATE=20030209T081500\r\n" +" :FREQ=DAILY;COUNT=10;INTERVAL=6\r\n" +"X-COMMENT;X-FOO=BAR: Booga\r\n" +"END:VEVENT\r\n"; + + icalcomponent *icalcomp; + icalproperty *prop; + struct icalrecurrencetype recur; + int n_errors; + + icalcomp = icalparser_parse_string ((char *) test_icalcomp_str); + if (!icalcomp) { + fprintf (stderr, "main(): could not parse the component\n"); + exit (EXIT_FAILURE); + } + + printf("%s\n\n",icalcomponent_as_ical_string(icalcomp)); - printf("\n------------Test Values---------------\n"); - test_values(); + n_errors = icalcomponent_count_errors (icalcomp); + if (n_errors) { + icalproperty *p; + + for (p = icalcomponent_get_first_property (icalcomp, + ICAL_XLICERROR_PROPERTY); + p; + p = icalcomponent_get_next_property (icalcomp, + ICAL_XLICERROR_PROPERTY)) { + char *str; + + str = icalproperty_as_ical_string (p); + fprintf (stderr, "error: %s\n", str); + } + } + + prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY); + if (!prop) { + fprintf (stderr, "main(): could not get the RRULE property"); + exit (EXIT_FAILURE); + } - printf("\n------------Test Parameters-----------\n"); - test_parameters(); + recur = icalproperty_get_rrule (prop); + + printf("%s\n",icalrecurrencetype_as_string(&recur)); - printf("\n------------Test Properties-----------\n"); - test_properties(); +} - printf("\n------------Test Components ----------\n"); - test_components(); +void test_gauge_sql() { - printf("\n------------Create Components --------\n"); - create_new_component(); - printf("\n----- Create Components with vaargs ---\n"); - create_new_component_with_va_args(); + icalgauge *g; + + printf("\nSELECT DTSTART,DTEND,COMMENT FROM VEVENT,VTODO WHERE VEVENT.SUMMARY = 'Bongoa' AND SEQUENCE < 5\n"); + g = icalgauge_new_from_sql("SELECT DTSTART,DTEND,COMMENT FROM VEVENT,VTODO WHERE VEVENT.SUMMARY = 'Bongoa' AND SEQUENCE < 5"); - return 0; + icalgauge_dump(g); - printf("\n------------Test icalset ---------------\n"); - test_icalset(); + icalgauge_free(g); + + printf("\nSELECT * FROM VEVENT,VTODO WHERE VEVENT.SUMMARY = 'Bongoa' AND SEQUENCE < 5 OR METHOD != 'CREATE'\n"); + + g = icalgauge_new_from_sql("SELECT * FROM VEVENT,VTODO WHERE VEVENT.SUMMARY = 'Bongoa' AND SEQUENCE < 5 OR METHOD != 'CREATE'"); + icalgauge_dump(g); + + icalgauge_free(g); + +} + +void test_gauge_compare() { + + icalgauge *g; + icalcomponent *c; + + /* Equality */ + + c = icalcomponent_vanew(ICAL_VCALENDAR_COMPONENT, + icalcomponent_vanew(ICAL_VEVENT_COMPONENT, + icalproperty_new_dtstart( + icaltime_from_string("20000101T000002")),0),0); + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART = '20000101T000002'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART = '20000101T000002'\n"); + assert(c!=0); + assert(g!=0); + + assert(icalgauge_compare(g,c) == 1); + + icalgauge_free(g); + + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART = '20000101T000001'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART = '20000101T000001'\n"); + + assert(g!=0); + assert(icalgauge_compare(g,c) == 0); + + icalgauge_free(g); + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART != '20000101T000003'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART != '20000101T000003'\n"); + + + assert(g!=0); + assert(icalgauge_compare(g,c) == 1); + + icalgauge_free(g); + /* Less than */ + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART < '20000101T000003'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART < '20000101T000003'\n"); + + assert(icalgauge_compare(g,c) == 1); + + assert(g!=0); + icalgauge_free(g); + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART < '20000101T000002'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART < '20000101T000002'\n"); + + + assert(g!=0); + assert(icalgauge_compare(g,c) == 0); + + icalgauge_free(g); + + /* Greater than */ + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART > '20000101T000001'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART > '20000101T000001'\n"); + + + assert(g!=0); + assert(icalgauge_compare(g,c) == 1); + + icalgauge_free(g); + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART > '20000101T000002'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART > '20000101T000002'\n"); + + + assert(g!=0); + assert(icalgauge_compare(g,c) == 0); + + icalgauge_free(g); + + + /* Greater than or Equal to */ + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART >= '20000101T000002'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART >= '20000101T000002'\n"); + + + assert(g!=0); + assert(icalgauge_compare(g,c) == 1); + + icalgauge_free(g); + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART >= '20000101T000003'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART >= '20000101T000003'\n"); + + + assert(g!=0); + assert(icalgauge_compare(g,c) == 0); + + icalgauge_free(g); + + /* Less than or Equal to */ + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART <= '20000101T000002'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART <= '20000101T000002'\n"); + + + assert(g!=0); + assert(icalgauge_compare(g,c) == 1); + + icalgauge_free(g); + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART <= '20000101T000001'"); + + printf("SELECT * FROM VEVENT WHERE DTSTART <= '20000101T000001'\n"); + + + assert(g!=0); + assert(icalgauge_compare(g,c) == 0); + + icalgauge_free(g); + + icalcomponent_free(c); + + + /* Complex comparisions */ + + c = icalcomponent_vanew( + ICAL_VCALENDAR_COMPONENT, + icalproperty_new_method(ICAL_METHOD_REQUEST), + icalcomponent_vanew( + ICAL_VEVENT_COMPONENT, + icalproperty_new_dtstart( + icaltime_from_string("20000101T000002")), + icalproperty_new_comment("foo"), + icalcomponent_vanew( + ICAL_VALARM_COMPONENT, + icalproperty_new_dtstart( + icaltime_from_string("20000101T120000")), + + 0), + 0), + 0); + + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE VALARM.DTSTART = '20000101T120000'"); + + printf("SELECT * FROM VEVENT WHERE VALARM.DTSTART = '20000101T120000'\n"); + + assert(icalgauge_compare(g,c) == 1); + + icalgauge_free(g); + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE COMMENT = 'foo'"); + + printf("SELECT * FROM VEVENT WHERE COMMENT = 'foo'\n"); + + assert(icalgauge_compare(g,c) == 1); + + icalgauge_free(g); + + + g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE COMMENT = 'foo' AND VALARM.DTSTART = '20000101T120000'"); + + printf("SELECT * FROM VEVENT WHERE COMMENT = 'foo' AND VALARM.DTSTART = '20000101T120000'\n"); + + assert(icalgauge_compare(g,c) == 1); + + icalgauge_free(g); + + icalcomponent_free(c); + +} + +icalcomponent* make_component(int i){ + + icalcomponent *c; + + struct icaltimetype t = icaltime_from_string("20000101T120000Z"); + + t.day += i; + + icaltime_normalize(t); + + c = icalcomponent_vanew( + ICAL_VCALENDAR_COMPONENT, + icalproperty_new_method(ICAL_METHOD_REQUEST), + icalcomponent_vanew( + ICAL_VEVENT_COMPONENT, + icalproperty_new_dtstart(t), + 0), + 0); + + assert(c != 0); + + return c; + +} +void test_fileset() +{ + icalfileset *fs; + icalcomponent *c; + int i; + char *path = "test_fileset.ics"; + icalgauge *g = icalgauge_new_from_sql( + "SELECT * FROM VEVENT WHERE DTSTART > '20000103T120000Z' AND DTSTART <= '20000106T120000Z'"); + + + unlink(path); + + fs = icalfileset_new(path); + + assert(fs != 0); + + for (i = 0; i!= 10; i++){ + c = make_component(i); + icalfileset_add_component(fs,c); + } + + icalfileset_commit(fs); + + icalfileset_free(fs); + fs = icalfileset_new(path); + + + printf("== No Selections \n"); + + for (c = icalfileset_get_first_component(fs); + c != 0; + c = icalfileset_get_next_component(fs)){ + struct icaltimetype t = icalcomponent_get_dtstart(c); + + printf("%s\n",icaltime_as_ctime(t)); + } + + icalfileset_select(fs,g); + + printf("\n== DTSTART > '20000103T120000Z' AND DTSTART <= '20000106T120000Z' \n"); + + for (c = icalfileset_get_first_component(fs); + c != 0; + c = icalfileset_get_next_component(fs)){ + struct icaltimetype t = icalcomponent_get_dtstart(c); + + printf("%s\n",icaltime_as_ctime(t)); + } + + icalfileset_free(fs); + +} + +void microsleep(int us) +{ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = us; + + select(0,0,0,0,&tv); + +} + + +void test_file_locks() +{ + pid_t pid; + char *path = "test_fileset_locktest.ics"; + icalfileset *fs; + icalcomponent *c, *c2; + struct icaldurationtype d; + int i; + int final,sec; + + icalfileset_safe_saves = 1; + + icalerror_clear_errno(); + + unlink(path); + + fs = icalfileset_new(path); + + if(icalfileset_get_first_component(fs)==0){ + c = make_component(0); + + d = icaldurationtype_from_int(1); + + icalcomponent_set_duration(c,d); + + icalfileset_add_component(fs,c); + + c2 = icalcomponent_new_clone(c); + + icalfileset_add_component(fs,c2); + + icalfileset_commit(fs); + } + + icalfileset_free(fs); + + assert(icalerrno == ICAL_NO_ERROR); + + pid = fork(); + + assert(pid >= 0); + + if(pid == 0){ + /*child*/ + int i; + + microsleep(rand()/(RAND_MAX/100)); + + for(i = 0; i< 50; i++){ + fs = icalfileset_new(path); + + + assert(fs != 0); + + c = icalfileset_get_first_component(fs); + + assert(c!=0); + + d = icalcomponent_get_duration(c); + d = icaldurationtype_from_int(icaldurationtype_as_int(d)+1); + + icalcomponent_set_duration(c,d); + icalcomponent_set_summary(c,"Child"); + + c2 = icalcomponent_new_clone(c); + icalcomponent_set_summary(c2,"Child"); + icalfileset_add_component(fs,c2); + + icalfileset_mark(fs); + icalfileset_commit(fs); + + icalfileset_free(fs); + + microsleep(rand()/(RAND_MAX/20)); + + + } + + exit(0); + + } else { + /* parent */ + int i; + + for(i = 0; i< 50; i++){ + fs = icalfileset_new(path); + + assert(fs != 0); + + c = icalfileset_get_first_component(fs); + + assert(c!=0); + + d = icalcomponent_get_duration(c); + d = icaldurationtype_from_int(icaldurationtype_as_int(d)+1); + + icalcomponent_set_duration(c,d); + icalcomponent_set_summary(c,"Parent"); + + c2 = icalcomponent_new_clone(c); + icalcomponent_set_summary(c2,"Parent"); + icalfileset_add_component(fs,c2); + + icalfileset_mark(fs); + icalfileset_commit(fs); + icalfileset_free(fs); + + putc('.',stdout); + fflush(stdout); + + } + } + + assert(waitpid(pid,0,0)==pid); + + + fs = icalfileset_new(path); + + i=1; + + c = icalfileset_get_first_component(fs); + final = icaldurationtype_as_int(icalcomponent_get_duration(c)); + for (c = icalfileset_get_next_component(fs); + c != 0; + c = icalfileset_get_next_component(fs)){ + struct icaldurationtype d = icalcomponent_get_duration(c); + sec = icaldurationtype_as_int(d); + + /*printf("%d,%d ",i,sec);*/ + assert(i == sec); + i++; + } + + printf("\nFinal: %d\n",final); + + + assert(sec == final); +} + + +void test_trigger() +{ + + static const char test_icalcomp_str[] = +"BEGIN:VEVENT\n" +"TRIGGER;VALUE=DATE-TIME:19980403T120000\n" +"TRIGGER:-PT15M\n" +"TRIGGER:19980403T120000\n" +"END:VEVENT\r\n"; + + icalcomponent *c; + icalproperty *p; + struct icaltriggertype tr; + + + c = icalparser_parse_string ((char *) test_icalcomp_str); + if (!c) { + fprintf (stderr, "main(): could not parse the component\n"); + exit (EXIT_FAILURE); + } + + printf("%s\n\n",icalcomponent_as_ical_string(c)); + + for(p = icalcomponent_get_first_property(c,ICAL_TRIGGER_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(c,ICAL_TRIGGER_PROPERTY)){ + tr = icalproperty_get_trigger(p); + + if(!icaltime_is_null_time(tr.time)){ + printf("value=DATE-TIME:%s\n", icaltime_as_ical_string(tr.time)); + } else { + printf("value=DURATION:%s\n", icaldurationtype_as_ical_string(tr.duration)); + } + } +} + +int main(int argc, char *argv[]) +{ + int c; + extern char *optarg; + extern int optind, optopt; + int errflg=0; + char* program_name = strrchr(argv[0],'/'); + int ttime=0, trecur=0,tspan=0, tmisc=0, tgauge = 0, tfile = 0; + + if(argc==1) { + ttime = trecur = tspan = tmisc = tgauge = tfile = 1; + } + + while ((c = getopt(argc, argv, "t:s:r:m:g:f:")) != -1) { + switch (c) { + + case 't': { + ttime = atoi(optarg); + break; + } + + case 's': { + tspan = atoi(optarg); + break; + } + + case 'r': { + trecur = atoi(optarg); + break; + } + + + case 'm': { + tmisc = atoi(optarg); + break; + } + + + case 'g': { + tgauge = atoi(optarg); + break; + } + + case 'f': { + tfile = atoi(optarg); + break; + } + + case ':': {/* Option given without an operand */ + fprintf(stderr, + "%s: Option -%c requires an operand\n", + program_name,optopt); + errflg++; + break; + } + case '?': { + errflg++; + } + + } + + } + + + if(ttime==1 || ttime==2){ + printf("\n------------Test time parser ----------\n"); + test_time_parser(); + + } + + if(ttime==1 || ttime==3){ + printf("\n------------Test time----------------\n"); + test_time(); + } + + if(ttime==1 || ttime==4){ + printf("\n------------Test day of year---------\n"); + test_doy(); + } + + if(ttime==1 || ttime==5){ + printf("\n------------Test duration---------------\n"); + test_duration(); + } + + if(ttime==1 || ttime==6){ + printf("\n------------Test period ----------------\n"); + test_period(); + } + + + + if(trecur==1 || trecur==2){ + printf("\n------------Test recur parser ----------\n"); + test_recur_parser(); + } + + if(trecur==1 || trecur==3){ + printf("\n------------Test recur---------------\n"); + test_recur(); + } + + if(trecur==1 || trecur==4){ + printf("\n------------Test parameter bug---------\n"); + test_recur_parameter_bug(); + } + + + if(tspan==1 || tspan==2){ + printf("\n------------Test FBlist------------\n"); + test_fblist(); + } + + if(tspan==1 || tspan==3){ + printf("\n------------Test Overlaps------------\n"); + test_overlaps(); + } + + if(tspan==1 || tspan==4){ + printf("\n------------Test Span----------------\n"); + test_span(); + } + + if(tgauge == 1 || tgauge == 2){ + printf("\n------------Test Gauge SQL----------------\n"); + test_gauge_sql(); + } + + if(tgauge == 1 || tgauge == 3){ + printf("\n------------Test Gauge Compare--------------\n"); + test_gauge_compare(); + } + + if(tfile ==1 || tfile == 2){ + printf("\n------------Test File Set--------------\n"); + test_fileset(); + } + + if(tfile ==1 || tfile == 3){ + printf("\n------------Test File Locks--------------\n"); + test_file_locks(); + } + + + + if(tmisc == 1 || tmisc == 2){ + printf("\n------------Test X Props and Params--------\n"); + test_x(); + } + + if(tmisc == 1 || tmisc == 3){ + printf("\n------------Test Trigger ------------------\n"); + test_trigger(); + } + + + if(tmisc == 1){ + + printf("\n------------Test Convenience ------------\n"); + test_convenience(); + + + printf("\n------------Test classify ---------------\n"); + test_classify(); + + + printf("\n------------Test Iterators-----------\n"); + test_iterators(); + + printf("\n------------Test Restriction---------------\n"); + test_restriction(); + + printf("\n-----------Test request status-------\n"); + test_requeststat(); + + printf("\n------------Test strings---------------\n"); + test_strings(); + + printf("\n------------Test Compare---------------\n"); + test_compare(); + + printf("\n------------Test Values---------------\n"); + test_values(); + + printf("\n------------Test Parameters-----------\n"); + test_parameters(); + + printf("\n------------Test Properties-----------\n"); + test_properties(); + + printf("\n------------Test Components ----------\n"); + test_components(); + + printf("\n------------Create Components --------\n"); + create_new_component(); + + printf("\n----- Create Components with vaargs ---\n"); + create_new_component_with_va_args(); + + printf("\n------------Test Memory---------------\n"); + test_memory(); + } + + return 0; } diff --git a/libical/src/test/storage.c b/libical/src/test/storage.c index 8251babefe..2d8bc586f4 100644 --- a/libical/src/test/storage.c +++ b/libical/src/test/storage.c @@ -113,7 +113,7 @@ void test_fileset() struct icaltimetype start, end; icalcomponent *c,*clone, *itr; - start = icaltime_from_timet( time(0),0,0); + start = icaltime_from_timet( time(0),0); end = start; end.hour++; @@ -244,7 +244,7 @@ int test_dirset() assert(s != 0); - rtime.start = icaltime_from_timet( time(0),0,0); + rtime.start = icaltime_from_timet( time(0),0); cluster = icalfileset_new(OUTPUT_FILE); diff --git a/libical/src/test/stow.c b/libical/src/test/stow.c index a305d161fe..2570e3ad0c 100644 --- a/libical/src/test/stow.c +++ b/libical/src/test/stow.c @@ -745,7 +745,6 @@ icalcomponent* read_nonmime_component(struct options_struct *opt) comp = icalparser_add_line(parser,line); if (comp != 0){ - icalparser_claim(parser); return comp; } -- cgit