aboutsummaryrefslogtreecommitdiffstats
path: root/libical/src/libical
diff options
context:
space:
mode:
Diffstat (limited to 'libical/src/libical')
-rw-r--r--libical/src/libical/Makefile.am4
-rw-r--r--libical/src/libical/icalcomponent.c62
-rw-r--r--libical/src/libical/icalcomponent.h6
-rw-r--r--libical/src/libical/icalenums.c17
-rw-r--r--libical/src/libical/icalenums.h6
-rw-r--r--libical/src/libical/icalerror.c26
-rw-r--r--libical/src/libical/icalerror.h3
-rw-r--r--libical/src/libical/icallexer.l129
-rw-r--r--libical/src/libical/icalmemory.h1
-rw-r--r--libical/src/libical/icalparameter.c.in9
-rw-r--r--libical/src/libical/icalparser.c106
-rw-r--r--libical/src/libical/icalparser.h1
-rw-r--r--libical/src/libical/icalproperty.c.in4
-rw-r--r--libical/src/libical/icalrecur.c775
-rw-r--r--libical/src/libical/icalrestriction.h1
-rw-r--r--libical/src/libical/icaltime.c640
-rw-r--r--libical/src/libical/icaltime.h58
-rw-r--r--libical/src/libical/icaltypes.c37
-rw-r--r--libical/src/libical/icaltypes.h6
-rw-r--r--libical/src/libical/icalvalue.c.in265
-rw-r--r--libical/src/libical/icalyacc.y120
21 files changed, 1563 insertions, 713 deletions
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 <stdio.h> /* For fprintf */
#include <stdio.h> /* For stderr */
+#include <string.h> /* For strncmp */
#include <assert.h>
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]
%}
-<binary_value>{
-.* { ical_yylval.v_string= icalmemory_tmp_copy(yytext);
- return STRING;}
-{crlf} { return EOL;}
-
-}
-
-<boolean_value>{
-. { return CHARACTER; }
-{crlf} { return EOL;}
-
-}
-
-<uri_value>{
-.* { ical_yylval.v_string= icalmemory_tmp_copy(yytext);
- return STRING;}
-{crlf} { return EOL;}
-
-}
-
-
<time_value>{
-{digit}* { ical_yylval.v_string= icalmemory_tmp_copy(yytext);
- return DIGITS; }
-T { return TIME_CHAR; }
-Z { return UTC_CHAR; }
-{crlf} { return EOL;}
-. { return CHARACTER; }
-
-}
-
-<duration_value>{
-{digit}+ { ical_yylval.v_string =icalmemory_tmp_copy(yytext);
- return DIGITS; }
-T { return TIME_CHAR; }
-[\+\-PTWHMSD] { return yytext[0]; }
-{crlf} { return EOL;}
-
-}
-
-<number_value>{
-[\+\-\.0-9]+ { ical_yylval.v_int=atoi(yytext); return INTNUMBER; }
-{crlf} { return EOL;}
-. { return CHARACTER; }
-
-}
-
-<period_value>{
{digit}+ { ical_yylval.v_string =icalmemory_tmp_copy(yytext) ;
return DIGITS; }
T { return TIME_CHAR; }
@@ -151,46 +104,6 @@ Z { return UTC_CHAR; }
}
-<recur_value>{
-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;}
-}
-
<utcoffset_value>{
{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 <stdlib.h> /* for malloc */
#include <errno.h> /* for errno */
-#include <string.h> /* for strdup */
+#include <string.h> /* for strdup and strchr*/
#include <assert.h>
+#include <stddef.h> /* 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)<limit &&array[i+1]
+ != ICAL_RECURRENCE_ARRAY_MAX){
+ icalmemory_append_char(&str,&str_p,&buf_sz,',');
+ }
+ }
+ }
+ }
+
+ return str;
+}
+#endif
+
+
+
+/************************* occurrence iteration routiens ******************/
enum byrule {
NO_CONTRACTION = -1,
@@ -156,7 +528,7 @@ struct icalrecur_iterator_impl {
struct icaltimetype dtstart; /* Hack. Make into time_t */
struct icaltimetype last; /* last time return from _iterator_next*/
- int occurrence_no; /* number of step made on this iterator */
+ int occurrence_no; /* number of step made on t iterator */
struct icalrecurrencetype rule;
short days[366];
@@ -164,6 +536,7 @@ struct icalrecur_iterator_impl {
enum byrule byrule;
short by_indices[9];
+ short orig_data[9]; /* 1 if there was data in the byrule */
short *by_ptrs[9]; /* Pointers into the by_* array elements of the rule */
@@ -306,6 +679,11 @@ void setup_defaults(struct icalrecur_iterator_impl* impl,
int expand_year_days(struct icalrecur_iterator_impl* impl,short year);
+int has_by_data(struct icalrecur_iterator_impl* impl, enum byrule byrule){
+
+ return (impl->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,47 +30,223 @@
#endif
#include "icaltime.h"
-#include "icalvalue.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#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(&gtm);
+
+ 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;
memset(&stm,0,sizeof( struct tm));
@@ -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, <alves@hungry.com> */
-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)<limit &&array[i+1]
- != ICAL_RECURRENCE_ARRAY_MAX){
- icalmemory_append_char(&str,&str_p,&buf_sz,',');
- }
- }
- }
- }
-
- return str;
+ return icalrecurrencetype_as_string(recur);
}
char* icalvalue_text_as_ical_string(icalvalue* value) {
@@ -826,67 +775,17 @@ char* icalvalue_attach_as_ical_string(icalvalue* value) {
}
}
-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* icalvalue_duration_as_ical_string(icalvalue* value)
{
struct icaldurationtype data;
- char *buf, *output_line;
- size_t buf_size = 256;
- char* buf_ptr = 0;
icalerror_check_arg_rz( (value!=0),"value");
data = icalvalue_get_duration(value);
- buf = (char*)icalmemory_new_buffer(buf_size);
- buf_ptr = buf;
-
- if (data.is_neg)
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, "-");
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, "P");
-
-
- if (data.weeks != 0 ) {
- append_duration_segment(&buf, &buf_ptr, &buf_size, "W", data.weeks);
- }
-
- if (data.days != 0 ) {
- append_duration_segment(&buf, &buf_ptr, &buf_size, "D", data.days);
- }
-
- if (data.hours != 0 || data.minutes != 0 || data.seconds != 0) {
-
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T");
+ return icaldurationtype_as_ical_string(data);
- if (data.hours != 0 ) {
- append_duration_segment(&buf, &buf_ptr, &buf_size, "H", data.hours);
- }
- if (data.minutes != 0 ) {
- append_duration_segment(&buf, &buf_ptr, &buf_size, "M", data.minutes);
- }
- if (data.seconds != 0 ) {
- append_duration_segment(&buf, &buf_ptr, &buf_size, "S", data.seconds);
- }
-
- }
-
- output_line = icalmemory_tmp_copy(buf);
- icalmemory_free_buffer(buf);
-
- return output_line;
-
-
}
void print_time_to_string(char* str, struct icaltimetype *data)
@@ -1087,31 +986,20 @@ char* icalvalue_period_as_ical_string(icalvalue* value) {
char* icalvalue_trigger_as_ical_string(icalvalue* value)
{
- union icaltriggertype data;
+ struct icaltriggertype data;
char* str;
- icalvalue *e;
icalerror_check_arg_rz( (value!=0),"value");
data = icalvalue_get_trigger(value);
str = (char*)icalmemory_tmp_buffer(60);
- if (data.time.is_date != -1){
- /* use the absolute date */
- e = icalvalue_new_datetime(data.time);
-
- strcpy (str, icalvalue_datetime_as_ical_string(e));
-
+ if(!icaltime_is_null_time(data.time)){
+ return icaltime_as_ical_string(data.time);
} else {
- /* use the duration */
- e = icalvalue_new_duration(data.duration);
-
- strcpy (str, icalvalue_duration_as_ical_string(e));
-
- }
+ return icaldurationtype_as_ical_string(data.duration);
+ }
- icalvalue_free(e);
- return str;
}
const char*
@@ -1220,6 +1108,20 @@ icalvalue_isa_value (void* value)
}
+int icalvalue_is_time(icalvalue* a) {
+ icalvalue_kind kind = icalvalue_isa(a);
+
+ if(kind == ICAL_DATETIMEDATE_VALUE ||
+ kind == ICAL_DATETIME_VALUE ||
+ kind == ICAL_DATE_VALUE ||
+ kind == ICAL_TIME_VALUE ){
+ return 1;
+ }
+
+ return 0;
+
+}
+
icalparameter_xliccomparetype
icalvalue_compare(icalvalue* a, icalvalue *b)
{
@@ -1230,7 +1132,8 @@ icalvalue_compare(icalvalue* a, icalvalue *b)
icalerror_check_arg_rz( (b!=0), "b");
/* Not the same type; they can only be unequal */
- if (icalvalue_isa(a) != icalvalue_isa(b)){
+ if( ! (icalvalue_is_time(a) && icalvalue_is_time(b)) &&
+ icalvalue_isa(a) != icalvalue_isa(b)){
return ICAL_XLICCOMPARETYPE_NOTEQUAL;
}
@@ -1271,6 +1174,21 @@ icalvalue_compare(icalvalue* a, icalvalue *b)
}
}
+ case ICAL_DURATION_VALUE:
+ {
+ int a = icaldurationtype_as_int(impla->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;