diff options
Diffstat (limited to 'libical')
-rw-r--r-- | libical/examples/access_components.c | 58 | ||||
-rw-r--r-- | libical/examples/errors.c | 2 | ||||
-rw-r--r-- | libical/examples/main.c | 7 | ||||
-rw-r--r-- | libical/examples/parse_text.c | 3 | ||||
-rw-r--r-- | libical/src/libical/icalmime.c | 86 | ||||
-rw-r--r-- | libical/src/libical/icalmime.h | 14 | ||||
-rw-r--r-- | libical/src/libical/icalrecur.c | 249 | ||||
-rw-r--r-- | libical/src/libical/icalrecur.h | 108 | ||||
-rw-r--r-- | libical/src/libical/sspm.c | 482 | ||||
-rw-r--r-- | libical/src/libical/sspm.h | 27 | ||||
-rw-r--r-- | libical/src/libicalss/icaldirset.c | 125 | ||||
-rw-r--r-- | libical/src/libicalss/icaldirset.h | 20 | ||||
-rw-r--r-- | libical/src/libicalss/icalfileset.c | 183 | ||||
-rw-r--r-- | libical/src/libicalss/icalfileset.h | 21 | ||||
-rw-r--r-- | libical/src/libicalss/icalfilesetimpl.h | 4 | ||||
-rw-r--r-- | libical/src/libicalss/icalgauge.c | 55 | ||||
-rw-r--r-- | libical/src/libicalss/icalgauge.h | 10 | ||||
-rw-r--r-- | libical/src/libicalss/icalset.c | 337 | ||||
-rw-r--r-- | libical/src/libicalss/icalset.h | 17 | ||||
-rw-r--r-- | libical/src/libicalvcal/icalvcal.c | 27 | ||||
-rw-r--r-- | libical/src/test/recur.c | 6 | ||||
-rw-r--r-- | libical/src/test/testmime.c | 5 |
22 files changed, 1548 insertions, 298 deletions
diff --git a/libical/examples/access_components.c b/libical/examples/access_components.c index 6b655b42f7..18fc6a6144 100644 --- a/libical/examples/access_components.c +++ b/libical/examples/access_components.c @@ -9,6 +9,8 @@ #include <time.h> /* for time() */ #include "icalmemory.h" +void do_something(icalcomponent *c); + /* Creating iCal Components There are two ways to create new component in libical. You can @@ -59,14 +61,9 @@ icalcomponent* create_new_component() icalcomponent_add_property( calendar, - icalproperty_new_version(strdup("2.0")) + icalproperty_new_version("2.0") ); - /* Note the use of strdup() in the previous and next call. All - properties constructors for properties with value types of - TEXT will take control of the string you pass into them. Since - the string '2.0' is a static string, we need to duplicate it in - new memory before giving it to the property */ /* Here is the short version of the memory rules: @@ -88,7 +85,7 @@ icalcomponent* create_new_component() icalcomponent_add_property( calendar, - icalproperty_new_prodid(strdup("-//RDU Software//NONSGML HandCal//EN")) + icalproperty_new_prodid("-//RDU Software//NONSGML HandCal//EN") ); /* Add an event */ @@ -105,11 +102,11 @@ icalcomponent* create_new_component() icalcomponent_add_property( event, - icalproperty_new_uid(strdup("guid-1.host1.com")) + icalproperty_new_uid("guid-1.host1.com") ); /* add a property that has parameters */ - property = icalproperty_new_organizer(strdup("mailto:mrbig@host.com")); + property = icalproperty_new_organizer("mailto:mrbig@host.com"); icalproperty_add_parameter( property, @@ -123,7 +120,7 @@ icalcomponent* create_new_component() operation is the same as adding a property to a component */ /* add another property that has parameters */ - property = icalproperty_new_attendee(strdup("mailto:employee-A@host.com")); + property = icalproperty_new_attendee("mailto:employee-A@host.com"); icalproperty_add_parameter( property, @@ -147,17 +144,17 @@ icalcomponent* create_new_component() icalcomponent_add_property( event, - icalproperty_new_description(strdup("Project XYZ Review Meeting")) + icalproperty_new_description("Project XYZ Review Meeting") ); icalcomponent_add_property( event, - icalproperty_new_categories(strdup("MEETING")) + icalproperty_new_categories("MEETING") ); icalcomponent_add_property( event, - icalproperty_new_class(strdup("PUBLIC")) + icalproperty_new_class("PUBLIC") ); icalcomponent_add_property( @@ -167,14 +164,14 @@ icalcomponent* create_new_component() icalcomponent_add_property( event, - icalproperty_new_summary(strdup("XYZ Project Review")) + icalproperty_new_summary("XYZ Project Review") ); property = icalproperty_new_dtstart(atime); icalproperty_add_parameter( property, - icalparameter_new_tzid(strdup("US-Eastern")) + icalparameter_new_tzid("US-Eastern") ); icalcomponent_add_property(event,property); @@ -184,14 +181,14 @@ icalcomponent* create_new_component() icalproperty_add_parameter( property, - icalparameter_new_tzid(strdup("US-Eastern")) + icalparameter_new_tzid("US-Eastern") ); icalcomponent_add_property(event,property); icalcomponent_add_property( event, - icalproperty_new_location(strdup("1CP Conference Room 4350")) + icalproperty_new_location("1CP Conference Room 4350") ); icalcomponent_add_component(calendar,event); @@ -224,44 +221,41 @@ icalcomponent* create_new_component_with_va_args() calendar = icalcomponent_vanew( ICAL_VCALENDAR_COMPONENT, - icalproperty_new_version(strdup("2.0")), - icalproperty_new_prodid(strdup("-//RDU Software//NONSGML HandCal//EN")), + icalproperty_new_version("2.0"), + icalproperty_new_prodid("-//RDU Software//NONSGML HandCal//EN"), icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstamp(atime), - icalproperty_new_uid(strdup("guid-1.host1.com")), + icalproperty_new_uid("guid-1.host1.com"), icalproperty_vanew_organizer( - strdup("mailto:mrbig@host.com"), + "mailto:mrbig@host.com", icalparameter_new_role(ICAL_ROLE_CHAIR), 0 ), icalproperty_vanew_attendee( - strdup("mailto:employee-A@host.com"), + "mailto:employee-A@host.com", icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT), icalparameter_new_rsvp(1), icalparameter_new_cutype(ICAL_CUTYPE_GROUP), 0 ), - icalproperty_new_description(strdup("Project XYZ Review Meeting")), - - /* Again, note the use of strdup to give libical - ownership of a static string. */ + icalproperty_new_description("Project XYZ Review Meeting"), - icalproperty_new_categories(strdup("MEETING")), - icalproperty_new_class(strdup("PUBLIC")), + icalproperty_new_categories("MEETING"), + icalproperty_new_class("PUBLIC"), icalproperty_new_created(atime), - icalproperty_new_summary(strdup("XYZ Project Review")), + icalproperty_new_summary("XYZ Project Review"), icalproperty_vanew_dtstart( atime, - icalparameter_new_tzid(strdup("US-Eastern")), + icalparameter_new_tzid("US-Eastern"), 0 ), icalproperty_vanew_dtend( atime, - icalparameter_new_tzid(strdup("US-Eastern")), + icalparameter_new_tzid("US-Eastern"), 0 ), - icalproperty_new_location(strdup("1CP Conference Room 4350")), + icalproperty_new_location("1CP Conference Room 4350"), 0 ), 0 diff --git a/libical/examples/errors.c b/libical/examples/errors.c index 071a2de816..86d963bd75 100644 --- a/libical/examples/errors.c +++ b/libical/examples/errors.c @@ -32,7 +32,7 @@ void component_errors(icalcomponent *comp) errors = icalcomponent_count_errors(comp); - printf("This component has %d parsing errors\n"); + printf("This component has %d parsing errors\n", errors); /* Print out all of the parsing errors. This is not strictly correct, because it does not descend into any sub-components, diff --git a/libical/examples/main.c b/libical/examples/main.c index 88d6621365..1be2de5c9e 100644 --- a/libical/examples/main.c +++ b/libical/examples/main.c @@ -1,9 +1,12 @@ /* This is just to make the code in the example directory link properly. */ +#include "ical.h" -main() +int main() { + + return 1; } -int do_something(){ +void do_something(icalcomponent* comp){ } diff --git a/libical/examples/parse_text.c b/libical/examples/parse_text.c index 2761e6f951..6de3e76dd5 100644 --- a/libical/examples/parse_text.c +++ b/libical/examples/parse_text.c @@ -25,10 +25,9 @@ char* read_stream(char *s, size_t size, void *d) } -int parse_text(int argc, char* argv[]) +void parse_text(int argc, char* argv[]) { - int lineno = 0; char* line; FILE* stream; icalcomponent *c; diff --git a/libical/src/libical/icalmime.c b/libical/src/libical/icalmime.c index a3fb7deaef..1aaf9c9aa9 100644 --- a/libical/src/libical/icalmime.c +++ b/libical/src/libical/icalmime.c @@ -27,8 +27,11 @@ ======================================================================*/ #include "icalmime.h" +#include "icalerror.h" +#include "icalmemory.h" #include "sspm.h" #include "stdlib.h" +#include <string.h> /* For strdup */ #ifdef DMALLOC #include "dmalloc.h" @@ -99,6 +102,7 @@ void* icalmime_text_end_part(void* part) void icalmime_text_free_part(void *part) { + part = part; } @@ -111,6 +115,10 @@ void* icalmime_attachment_new_part() void icalmime_attachment_add_line(void *part, struct sspm_header *header, char* line, size_t size) { + part = part; + header = header; + line = line; + size = size; } void* icalmime_attachment_end_part(void* part) @@ -129,6 +137,7 @@ struct sspm_action_map icalmime_local_action_map[] = { {SSPM_TEXT_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_textcalendar_end_part,icalmime_text_free_part}, {SSPM_TEXT_MAJOR_TYPE,SSPM_ANY_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part}, + {SSPM_TEXT_MAJOR_TYPE,SSPM_PLAIN_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part}, {SSPM_APPLICATION_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, {SSPM_AUDIO_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, @@ -136,14 +145,22 @@ struct sspm_action_map icalmime_local_action_map[] = {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,0,0,0,0} }; +#define NUM_PARTS 100 /* HACK. Hard Limit */ + + + +struct sspm_part* icalmime_make_part(icalcomponent* comp) +{ + comp = comp; + return 0; +} + +char* icalmime_as_mime_string(char* icalcomponent); icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size, void *d), void *data) { - -#define NUM_PARTS 100 /* HACK. Hard Limit */ - struct sspm_part *parts; int i, last_level=0; icalcomponent *root=0, *parent=0, *comp=0, *last = 0; @@ -179,8 +196,6 @@ icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size, sprintf(mimetype,"%s/%s",major,minor); - printf("%d: %-10s %p\n",parts[i].level,mimetype,data); - comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT); if(comp == 0){ @@ -205,8 +220,8 @@ icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size, } if(parts[i].header.error==SSPM_NO_HEADER_ERROR){ - str = "Did not get a header for the part. Is there a blank -line between the header and the previous boundary?"; + str = "Did not get a header for the part. Is there a blank\ +line between the header and the previous boundary\?"; } @@ -226,15 +241,21 @@ line between the header and the previous boundary?"; 0)); } -#if 0 - icalcomponent_add_property(comp, - icalproperty_new_xlicmimecontenttype((char*)icalmemory_strdup(mimetype))); + if(parts[i].header.major != SSPM_NO_MAJOR_TYPE && + parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){ + + icalcomponent_add_property(comp, + icalproperty_new_xlicmimecontenttype((char*) + icalmemory_strdup(mimetype))); + + } + + if (parts[i].header.encoding != SSPM_NO_ENCODING){ - if (parts[i].header.encoding != 0){ icalcomponent_add_property(comp, - icalproperty_new_xlicmimeencoding(parts[i].header.encoding)); + icalproperty_new_xlicmimeencoding( + sspm_encoding_string(parts[i].header.encoding))); } -#endif if (parts[i].header.filename != 0){ icalcomponent_add_property(comp, @@ -323,3 +344,42 @@ line between the header and the previous boundary?"; +int icalmime_test(char* (*get_string)(char *s, size_t size, void *d), + void *data) +{ + char *out; + struct sspm_part *parts; + int i; + + if ( (parts = (struct sspm_part *) + malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memset(parts,0,sizeof(parts)); + + sspm_parse_mime(parts, + NUM_PARTS, /* Max parts */ + icalmime_local_action_map, /* Actions */ + get_string, + data, /* data for get_string*/ + 0 /* First header */); + + for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; + i++){ + if(parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE){ + parts[i].data = strdup( + icalcomponent_as_ical_string((icalcomponent*)parts[i].data)); + } + } + + sspm_write_mime(parts,NUM_PARTS,&out,"To: bob@bob.org"); + + printf("%s\n",out); + + return 0; + +} + + diff --git a/libical/src/libical/icalmime.h b/libical/src/libical/icalmime.h index d301debf7b..b22288842d 100644 --- a/libical/src/libical/icalmime.h +++ b/libical/src/libical/icalmime.h @@ -1,4 +1,4 @@ -// -*- Mode: C -*- +/* -*- Mode: C -*- */ /*====================================================================== FILE: icalmime.h CREATOR: eric 26 July 2000 @@ -20,21 +20,23 @@ The Mozilla Public License Version 1.0. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - The Original Code is eric. The Initial Developer of the Original - Code is Eric Busboom - - ======================================================================*/ #ifndef ICALMIME_H #define ICALMIME_H -#include "ical.h" +#include "icalcomponent.h" +#include "icalparser.h" icalcomponent* icalmime_parse( char* (*line_gen_func)(char *s, size_t size, void *d), void *data); +/* The inverse of icalmime_parse, not implemented yet. Use sspm.h directly. */ +char* icalmime_as_mime_string(char* component); + + + #endif /* !ICALMIME_H */ diff --git a/libical/src/libical/icalrecur.c b/libical/src/libical/icalrecur.c index a4b51e60d5..9ec1b699c0 100644 --- a/libical/src/libical/icalrecur.c +++ b/libical/src/libical/icalrecur.c @@ -25,7 +25,7 @@ Processing starts when the caller generates a new recurrence iterator via icalrecur_iterator_new(). This routine copies the - recurrence rule into the iterator, extracts things like start and + recurrence rule into the iterator and extracts things like start and end dates. Then, it checks if the rule is legal, using some logic from RFC2445 and some logic that probably should be in RFC2445. @@ -118,18 +118,25 @@ #endif #include "icalrecur.h" + +#ifdef ICAL_NO_LIBICAL #include "icalerror.h" -#include "icalmemory.h" +#else +#define icalerror_set_errno(x) +#define icalerror_check_arg_rv(x,y) +#endif + #include <stdlib.h> /* for malloc */ #include <errno.h> /* for errno */ -#include <string.h> /* for icalmemory_strdup */ +#include <string.h> /* for strdup */ #include <assert.h> -#include <limits.h> /* for SHRT_MAX */ #define TEMP_MAX 1024 + + enum byrule { NO_CONTRACTION = -1, BY_SECOND = 0, @@ -147,7 +154,7 @@ enum byrule { struct icalrecur_iterator_impl { - struct icaltimetype dtstart; + 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 */ struct icalrecurrencetype rule; @@ -181,6 +188,10 @@ enum expand_table { ILLEGAL=3 }; +/* The split map indicates, for a particular interval, wether a BY_* + rule part expands the number of instances in the occcurrence set or + contracts it. 1=> contract, 2=>expand, and 3 means the pairing is + not allowed. */ struct expand_split_map_struct { icalrecurrencetype_frequency frequency; @@ -193,14 +204,14 @@ struct expand_split_map_struct struct expand_split_map_struct expand_map[] = { - {ICAL_SECONDLY_RECURRENCE,1,1,1,1,1,1,1,1}, - {ICAL_MINUTELY_RECURRENCE,2,1,1,1,1,1,1,1}, - {ICAL_HOURLY_RECURRENCE, 2,2,1,1,1,1,1,1}, - {ICAL_DAILY_RECURRENCE, 2,2,2,1,1,1,1,1}, - {ICAL_WEEKLY_RECURRENCE, 2,2,2,2,3,3,1,1}, - {ICAL_MONTHLY_RECURRENCE, 2,2,2,2,2,3,3,1}, - {ICAL_YEARLY_RECURRENCE, 2,2,2,2,2,2,2,2}, - {ICAL_NO_RECURRENCE, 0,0,0,0,0,0,0,0} + {ICAL_SECONDLY_RECURRENCE,{1,1,1,1,1,1,1,1}}, + {ICAL_MINUTELY_RECURRENCE,{2,1,1,1,1,1,1,1}}, + {ICAL_HOURLY_RECURRENCE, {2,2,1,1,1,1,1,1}}, + {ICAL_DAILY_RECURRENCE, {2,2,2,1,1,1,1,1}}, + {ICAL_WEEKLY_RECURRENCE, {2,2,2,2,3,3,1,1}}, + {ICAL_MONTHLY_RECURRENCE, {2,2,2,2,2,3,3,1}}, + {ICAL_YEARLY_RECURRENCE, {2,2,2,2,2,2,2,2}}, + {ICAL_NO_RECURRENCE, {0,0,0,0,0,0,0,0}} }; @@ -278,7 +289,7 @@ void setup_defaults(struct icalrecur_iterator_impl* impl, freq = impl->rule.freq; /* Re-write the BY rule arrays with data from the DTSTART time so - we don't hav to explicitly deal with DTSTART */ + we don't have to explicitly deal with DTSTART */ if(impl->by_ptrs[byrule][0] == ICAL_RECURRENCE_ARRAY_MAX && expand_map[freq].map[byrule] != CONTRACT){ @@ -296,7 +307,8 @@ void setup_defaults(struct icalrecur_iterator_impl* impl, int expand_year_days(struct icalrecur_iterator_impl* impl,short year); -icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, struct icaltimetype dtstart) +icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, + struct icaltimetype dtstart) { struct icalrecur_iterator_impl* impl; icalrecurrencetype_frequency freq; @@ -388,7 +400,9 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, struc /* Rewrite some of the rules and set up defaults to make later - processing easier */ + processing easier. Primarily, this involves copying an element + from the start time into the coresponding BY_* array when the + BY_* array is empty */ setup_defaults(impl,BY_SECOND,ICAL_SECONDLY_RECURRENCE,impl->dtstart.second, @@ -445,63 +459,121 @@ void increment_year(struct icalrecur_iterator_impl* impl, int inc) void increment_month(struct icalrecur_iterator_impl* impl, int inc) { + int years; + impl->last.month+=inc; - if (impl->last.month > 12){ - impl->last.month = 1; - increment_year(impl,1); + /* Months are offset by one */ + impl->last.month--; + + years = impl->last.month / 12; + + impl->last.month = impl->last.month % 12; + + impl->last.month++; + + if (years != 0){ + increment_year(impl,years); } } void increment_monthday(struct icalrecur_iterator_impl* impl, int inc) { - - short days_in_month = icaltime_days_in_month(impl->last.month,impl->last.year); + int i; - impl->last.day+=inc; + for(i=0; i<inc; i++){ + + short days_in_month = + icaltime_days_in_month(impl->last.month,impl->last.year); - if (impl->last.day > days_in_month){ - int md = impl->last.day -days_in_month; - impl->last.day = md; - increment_month(impl,1); + impl->last.day++; + + if (impl->last.day > days_in_month){ + impl->last.day = impl->last.day-days_in_month; + increment_month(impl,1); + } } - } void increment_hour(struct icalrecur_iterator_impl* impl, int inc) { + short days; + impl->last.hour+=inc; - if (impl->last.hour > 24){ - impl->last.hour = 0; - increment_monthday(impl,1); - } + days = impl->last.hour / 24; + impl->last.hour = impl->last.hour % 24; + if (impl->days != 0){ + increment_monthday(impl,days); + } } void increment_minute(struct icalrecur_iterator_impl* impl, int inc) { + short hours; + impl->last.minute+=inc; - if (impl->last.minute > 59){ - impl->last.minute = 0; - increment_hour(impl,1); + hours = impl->last.minute / 60; + impl->last.minute = impl->last.minute % 60; + + if (hours != 0){ + increment_hour(impl,hours); } } void increment_second(struct icalrecur_iterator_impl* impl, int inc) { + short minutes; + impl->last.second+=inc; + + minutes = impl->last.second / 60; + impl->last.second = impl->last.second % 60; + + if (minutes != 0) + { + increment_minute(impl, minutes); + } +} - if (impl->last.second > 59){ - impl->last.second = 0; - increment_minute(impl,1); - } +#if 1 + +#include "ical.h" +void test_increment() +{ + struct icalrecur_iterator_impl impl; + + impl.last = icaltime_from_string("20000101T000000Z"); + printf("Orig: %s\n",icaltime_as_ctime(impl.last)); + + increment_second(&impl,5); + printf("+ 5 sec : %s\n",icaltime_as_ctime(impl.last)); + + increment_second(&impl,355); + printf("+ 355 sec : %s\n",icaltime_as_ctime(impl.last)); + + increment_minute(&impl,5); + printf("+ 5 min : %s\n",icaltime_as_ctime(impl.last)); + + increment_minute(&impl,360); + printf("+ 360 min : %s\n",icaltime_as_ctime(impl.last)); + increment_hour(&impl,5); + printf("+ 5 hours : %s\n",icaltime_as_ctime(impl.last)); + increment_hour(&impl,43); + printf("+ 43 hours : %s\n",icaltime_as_ctime(impl.last)); + increment_monthday(&impl,3); + printf("+ 3 days : %s\n",icaltime_as_ctime(impl.last)); + increment_monthday(&impl,600); + printf("+ 600 days : %s\n",icaltime_as_ctime(impl.last)); + } +#endif short next_second(struct icalrecur_iterator_impl* impl) { @@ -766,6 +838,8 @@ int next_weekday(struct icalrecur_iterator_impl* impl) end_of_data = 1; } + /* 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); @@ -1146,29 +1220,94 @@ struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr) return impl->last; } -#include "ical.h" -void icalrecurrencetype_test() + +/************************** Type Routines **********************/ + + +void icalrecurrencetype_clear(struct icalrecurrencetype *recur) { - icalvalue *v = icalvalue_new_from_string( - ICAL_RECUR_VALUE, - "FREQ=YEARLY;UNTIL=20060101T000000;INTERVAL=2;BYDAY=SU,WE;BYSECOND=15,30; BYMONTH=1,6,11"); + memset(recur,ICAL_RECURRENCE_ARRAY_MAX_BYTE, + sizeof(struct icalrecurrencetype)); + + recur->week_start = ICAL_MONDAY_WEEKDAY; + recur->freq = ICAL_NO_RECURRENCE; + recur->interval = 1; + memset(&(recur->until),0,sizeof(struct icaltimetype)); + recur->count = 0; +} - struct icalrecurrencetype r = icalvalue_get_recur(v); - struct icaltimetype t = icaltime_from_timet( time(0), 0, 0); - struct icaltimetype next; - time_t tt; +/* The 'day' element of icalrecurrencetype_weekday is encoded to allow +reporesentation of both the day of the week ( Monday, Tueday), but +also the Nth day of the week ( First tuesday of the month, last +thursday of the year) These routines decode the day values. - struct icalrecur_iterator_impl* itr - = (struct icalrecur_iterator_impl*) icalrecur_iterator_new(r,t); +The day's position in the period ( Nth-ness) and the numerical value +of the day are encoded together as: pos*7 + dow + */ - do { +enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day) +{ + return abs(day)%8; +} + +short icalrecurrencetype_day_position(short day) +{ + return (day-icalrecurrencetype_day_day_of_week(day))/8; +} - next = icalrecur_iterator_next(itr); - tt = icaltime_as_timet(next); - printf("%s",ctime(&tt )); +/****************** Enumeration Routines ******************/ + +struct {icalrecurrencetype_weekday wd; const char * str; } +wd_map[] = { + {ICAL_SUNDAY_WEEKDAY,"SU"}, + {ICAL_MONDAY_WEEKDAY,"MO"}, + {ICAL_TUESDAY_WEEKDAY,"TU"}, + {ICAL_WEDNESDAY_WEEKDAY,"WE"}, + {ICAL_THURSDAY_WEEKDAY,"TH"}, + {ICAL_FRIDAY_WEEKDAY,"FR"}, + {ICAL_SATURDAY_WEEKDAY,"SA"}, + {ICAL_NO_WEEKDAY,0} +}; + +const char* icalrecur_weekday_to_string(icalrecurrencetype_weekday kind) +{ + int i; - } while( ! icaltime_is_null_time(next)); - + for (i=0; wd_map[i].wd != ICAL_NO_WEEKDAY; i++) { + if ( wd_map[i].wd == kind) { + return wd_map[i].str; + } + } + + return 0; } + +struct { + icalrecurrencetype_frequency kind; + const char* str; +} freq_map[] = { + {ICAL_SECONDLY_RECURRENCE,"SECONDLY"}, + {ICAL_MINUTELY_RECURRENCE,"MINUTELY"}, + {ICAL_HOURLY_RECURRENCE,"HOURLY"}, + {ICAL_DAILY_RECURRENCE,"DAILY"}, + {ICAL_WEEKLY_RECURRENCE,"WEEKLY"}, + {ICAL_MONTHLY_RECURRENCE,"MONTHLY"}, + {ICAL_YEARLY_RECURRENCE,"YEARLY"}, + {ICAL_NO_RECURRENCE,0} +}; + +const char* icalrecur_recurrence_to_string(icalrecurrencetype_frequency kind) +{ + int i; + + for (i=0; freq_map[i].kind != ICAL_NO_RECURRENCE ; i++) { + if ( freq_map[i].kind == kind ) { + return freq_map[i].str; + } + } + return 0; +} + + diff --git a/libical/src/libical/icalrecur.h b/libical/src/libical/icalrecur.h index cfafc01b02..fe82ff960c 100644 --- a/libical/src/libical/icalrecur.h +++ b/libical/src/libical/icalrecur.h @@ -17,7 +17,6 @@ The Mozilla Public License Version 1.0. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - The original code is icaltypes.h ======================================================================*/ @@ -25,13 +24,116 @@ #define ICALRECUR_H #include <time.h> -#include "icaltypes.h" -#include "icalenums.h" /* for recurrence enums */ +#include "icaltime.h" + + +/*********************************************************************** + * Recurrance enumerations +**********************************************************************/ + +typedef enum icalrecurrencetype_frequency +{ + /* These enums are used to index an array, so don't change the + order or the integers */ + + ICAL_SECONDLY_RECURRENCE=0, + ICAL_MINUTELY_RECURRENCE=1, + ICAL_HOURLY_RECURRENCE=2, + ICAL_DAILY_RECURRENCE=3, + ICAL_WEEKLY_RECURRENCE=4, + ICAL_MONTHLY_RECURRENCE=5, + ICAL_YEARLY_RECURRENCE=6, + ICAL_NO_RECURRENCE=7 + +} icalrecurrencetype_frequency; + +typedef enum icalrecurrencetype_weekday +{ + ICAL_NO_WEEKDAY, + ICAL_SUNDAY_WEEKDAY, + ICAL_MONDAY_WEEKDAY, + ICAL_TUESDAY_WEEKDAY, + ICAL_WEDNESDAY_WEEKDAY, + ICAL_THURSDAY_WEEKDAY, + ICAL_FRIDAY_WEEKDAY, + ICAL_SATURDAY_WEEKDAY +} icalrecurrencetype_weekday; + +enum { + ICAL_RECURRENCE_ARRAY_MAX = 0x7f7f, + ICAL_RECURRENCE_ARRAY_MAX_BYTE = 0x7f +}; + +const char* icalrecur_recurrence_to_string(icalrecurrencetype_frequency kind); +const char* icalrecur_weekday_to_string(icalrecurrencetype_weekday kind); + + +/********************** Recurrence type routines **************/ + +/* See RFC 2445 Section 4.3.10, RECUR Value, for an explaination of + the values and fields in struct icalrecurrencetype */ + + +struct icalrecurrencetype +{ + icalrecurrencetype_frequency freq; + + + /* until and count are mutually exclusive. */ + struct icaltimetype until; /* Hack. Must be time_t for general use */ + int count; + + short interval; + + icalrecurrencetype_weekday week_start; + + /* The BY* parameters can each take a list of values. Here I + * assume that the list of values will not be larger than the + * range of the value -- that is, the client will not name a + * value more than once. + + * Each of the lists is terminated with the value + * ICALRECURRENCE_ARRAY_MAX unless the the list is full. + */ + + short by_second[61]; + short by_minute[61]; + short by_hour[25]; + short by_day[8]; /* Encoded value, see below */ + short by_month_day[32]; + short by_year_day[367]; + short by_week_no[54]; + short by_month[13]; + short by_set_pos[367]; +}; + + +void icalrecurrencetype_clear(struct icalrecurrencetype *r); + +/* The 'day' element of icalrecurrencetype_weekday is encoded to allow +representation of both the day of the week ( Monday, Tueday), but also +the Nth day of the week ( First tuesday of the month, last thursday of +the year) These routines decode the day values */ + +/* 1 == Monday, etc. */ +enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day); + +/* 0 == any of day of week. 1 == first, 2 = second, -2 == second to last, etc */ +short icalrecurrencetype_day_position(short day); + +/* Return the next occurance of 'r' after the time specified by 'after' */ +struct icaltimetype icalrecurrencetype_next_occurance( + struct icalrecurrencetype *r, + struct icaltimetype *after); + + typedef void icalrecur_iterator; void icalrecurrencetype_test(); +/********** recurrence routines ********************/ + icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, struct icaltimetype dtstart); struct icaltimetype icalrecur_iterator_next(icalrecur_iterator*); diff --git a/libical/src/libical/sspm.c b/libical/src/libical/sspm.c index 36f69b506a..faaacb5592 100644 --- a/libical/src/libical/sspm.c +++ b/libical/src/libical/sspm.c @@ -125,6 +125,21 @@ struct minor_content_type_map +struct encoding_map { + enum sspm_encoding encoding; + char* str; +} sspm_encoding_map[] = +{ + {SSPM_NO_ENCODING,""}, + {SSPM_QUOTED_PRINTABLE_ENCODING,"quoted-printable"}, + {SSPM_8BIT_ENCODING,"8bit"}, + {SSPM_7BIT_ENCODING,"7bit"}, + {SSPM_BINARY_ENCODING,"binary"}, + {SSPM_BASE64_ENCODING,"base64"}, + {SSPM_UNKNOWN_ENCODING,""} + +}; + char* sspm_get_parameter(char* line, char* parameter) { @@ -488,6 +503,19 @@ char* sspm_minor_type_string(enum sspm_major_type type) } +char* sspm_encoding_string(enum sspm_encoding type) +{ + int i; + for (i=0; sspm_encoding_map[i].encoding != SSPM_UNKNOWN_ENCODING; + i++){ + if(type == sspm_encoding_map[i].encoding){ + return sspm_encoding_map[i].str; + } + } + + return sspm_encoding_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */ +} + /* Interpret a header line and add its data to the header structure. */ void sspm_build_header(struct sspm_header *header, char* line) @@ -543,6 +571,7 @@ void sspm_build_header(struct sspm_header *header, char* line) header->encoding = SSPM_UNKNOWN_ENCODING; } + free(lencoding); header->def = 0; @@ -570,12 +599,13 @@ char* sspm_get_next_line(struct mime_impl *impl) void sspm_store_part(struct mime_impl *impl, struct sspm_header header, - int level, void *part) + int level, void *part, size_t size) { impl->parts[impl->part_no].header = header; impl->parts[impl->part_no].level = level; impl->parts[impl->part_no].data = part; + impl->parts[impl->part_no].data_size = size; impl->part_no++; } @@ -599,8 +629,10 @@ void sspm_set_error(struct sspm_header* header, enum sspm_error error, } void* sspm_make_part(struct mime_impl *impl, - struct sspm_header *header, - struct sspm_header *parent_header) + struct sspm_header *header, + struct sspm_header *parent_header, + void **end_part, + size_t *size) { /* For a single part type, read to the boundary, if there is a @@ -609,7 +641,7 @@ void* sspm_make_part(struct mime_impl *impl, at the first blank line */ char *line; - void *part, *end_part; + void *part; int end = 0; struct sspm_action_map action = get_action( @@ -617,6 +649,7 @@ void* sspm_make_part(struct mime_impl *impl, header->major, header->minor); + *size = 0; part =action.new_part(); impl->state = IN_BODY; @@ -630,7 +663,7 @@ void* sspm_make_part(struct mime_impl *impl, if(parent_header == 0){ char* boundary; end = 1; - end_part = 0; + *end_part = 0; sspm_set_error(header,SSPM_UNEXPECTED_BOUNDARY_ERROR,line); @@ -654,7 +687,7 @@ void* sspm_make_part(struct mime_impl *impl, if(strncmp((line+2),parent_header->boundary, sizeof(parent_header->boundary)) == 0){ - end_part = action.end_part(part); + *end_part = action.end_part(part); if(sspm_is_mime_boundary(line)){ impl->state = END_OF_PART; @@ -684,7 +717,6 @@ void* sspm_make_part(struct mime_impl *impl, strcpy(boundary,line); strcat(boundary,"--"); while((line = sspm_get_next_line(impl)) != 0){ - /*printf("Error: %s\n",line);*/ if(strcmp(boundary,line)==0){ break; } @@ -693,16 +725,16 @@ void* sspm_make_part(struct mime_impl *impl, } } else { - size_t size; - char* data; + char* data=0; char* rtrn=0; - size = strlen(line); + *size = strlen(line); - data = (char*)malloc(size+2); + data = (char*)malloc(*size+2); + assert(data != 0); if (header->encoding == SSPM_BASE64_ENCODING){ - rtrn = decode_base64(data,line,&size); + rtrn = decode_base64(data,line,size); } else if(header->encoding == SSPM_QUOTED_PRINTABLE_ENCODING){ - rtrn = decode_quoted_printable(data,line,&size); + rtrn = decode_quoted_printable(data,line,size); } if(rtrn == 0){ @@ -712,9 +744,9 @@ void* sspm_make_part(struct mime_impl *impl, /* add a end-of-string after the data, just in case binary data from decode64 gets passed to a tring handling routine in add_line */ - data[size+1]='\0'; + data[*size+1]='\0'; - action.add_line(part,header,data,size); + action.add_line(part,header,data,*size); free(data); } @@ -722,7 +754,7 @@ void* sspm_make_part(struct mime_impl *impl, if (end == 0){ /* End the part if the input is exhausted */ - end_part = action.end_part(part); + *end_part = action.end_part(part); } return end_part; @@ -735,6 +767,7 @@ void* sspm_make_multipart_subpart(struct mime_impl *impl, struct sspm_header header; char *line; void* part; + size_t size; if(parent_header->boundary == 0){ /* Error. Multipart headers must have a boundary*/ @@ -785,7 +818,6 @@ void* sspm_make_multipart_subpart(struct mime_impl *impl, strcpy(boundary,line); strcat(boundary,"--"); while((line = sspm_get_next_line(impl)) != 0){ - /*printf("Error: %s\n",line);*/ if(strcmp(boundary,line)==0){ break; } @@ -809,7 +841,7 @@ void* sspm_make_multipart_subpart(struct mime_impl *impl, } if(header.error!= SSPM_NO_ERROR){ - sspm_store_part(impl,header,impl->level,0); + sspm_store_part(impl,header,impl->level,0,0); return 0; } @@ -820,7 +852,7 @@ void* sspm_make_multipart_subpart(struct mime_impl *impl, child_header = &(impl->parts[impl->part_no].header); /* Store the multipart part */ - sspm_store_part(impl,header,impl->level,0); + sspm_store_part(impl,header,impl->level,0,0); /* now get all of the sub-parts */ part = sspm_make_multipart_part(impl,child_header); @@ -834,11 +866,11 @@ void* sspm_make_multipart_subpart(struct mime_impl *impl, sspm_get_next_line(impl); /* Step past the terminating boundary */ } else { - part = sspm_make_part(impl, &header,parent_header); + sspm_make_part(impl, &header,parent_header,&part,&size); memset(&(impl->parts[impl->part_no]), 0, sizeof(struct sspm_part)); - sspm_store_part(impl,header,impl->level,part); + sspm_store_part(impl,header,impl->level,part,size); } @@ -1013,16 +1045,18 @@ int sspm_parse_mime(struct sspm_part *parts, struct sspm_header *child_header; child_header = &(impl.parts[impl.part_no].header); - sspm_store_part(&impl,header,impl.level,0); + sspm_store_part(&impl,header,impl.level,0,0); part = sspm_make_multipart_part(&impl,child_header); } else { - part = sspm_make_part(&impl, &header, 0); + void *part; + size_t size; + sspm_make_part(&impl, &header, 0,&part,&size); memset(&(impl.parts[impl.part_no]), 0, sizeof(struct sspm_part)); - sspm_store_part(&impl,header,impl.level,part); + sspm_store_part(&impl,header,impl.level,part,size); } return 0; @@ -1076,8 +1110,8 @@ The code is heavily modified by Eric Busboom. ***********************************************************************/ -unsigned char *decode_quoted_printable(unsigned char *dest, - unsigned char *src, +char *decode_quoted_printable(char *dest, + char *src, size_t *size) { int cc; @@ -1125,12 +1159,12 @@ unsigned char *decode_quoted_printable(unsigned char *dest, return(dest); } -unsigned char *decode_base64(unsigned char *dest, - unsigned char *src, - size_t *size) +char *decode_base64(char *dest, + char *src, + size_t *size) { int cc; - unsigned char buf[4] = {0,0,0,0}; + char buf[4] = {0,0,0,0}; int p = 0; int valid_data = 0; size_t size_out=0; @@ -1189,3 +1223,391 @@ unsigned char *decode_base64(unsigned char *dest, } +/*********************************************************************** + + Routines to output MIME + +**********************************************************************/ + + +struct sspm_buffer { + char* buffer; + char* pos; + size_t buf_size; + int line_pos; +}; + +void sspm_append_string(struct sspm_buffer* buf, char* string); +void sspm_write_part(struct sspm_buffer *buf,struct sspm_part *part, int *part_num); + +void sspm_append_hex(struct sspm_buffer* buf, char ch) +{ + char tmp[3]; + + sprintf(tmp,"=%02X",ch); + + sspm_append_string(buf,tmp); +} + +/* a copy of icalmemory_append_char */ +void sspm_append_char(struct sspm_buffer* buf, char ch) +{ + char *new_buf; + char *new_pos; + + size_t data_length, final_length; + + data_length = (size_t)buf->pos - (size_t)buf->buffer; + + final_length = data_length + 2; + + if ( final_length > (size_t) buf->buf_size ) { + + buf->buf_size = (buf->buf_size) * 2 + final_length +1; + + new_buf = realloc(buf->buffer,buf->buf_size); + + new_pos = (void*)((size_t)new_buf + data_length); + + buf->pos = new_pos; + buf->buffer = new_buf; + } + + *(buf->pos) = ch; + buf->pos += 1; + *(buf->pos) = 0; +} +/* A copy of icalmemory_append_string */ +void sspm_append_string(struct sspm_buffer* buf, char* string) +{ + char *new_buf; + char *new_pos; + + size_t data_length, final_length, string_length; + + string_length = strlen(string); + data_length = (size_t)buf->pos - (size_t)buf->buffer; + final_length = data_length + string_length; + + if ( final_length >= (size_t) buf->buf_size) { + + + buf->buf_size = (buf->buf_size) * 2 + final_length; + + new_buf = realloc(buf->buffer,buf->buf_size); + + new_pos = (void*)((size_t)new_buf + data_length); + + buf->pos = new_pos; + buf->buffer = new_buf; + } + + strcpy(buf->pos, string); + + buf->pos += string_length; +} + + + +static int sspm_is_printable(char c) +{ + return (c >= 33) && (c <= 126) && (c != '='); + +} + + +void sspm_encode_quoted_printable(struct sspm_buffer *buf, char* data) +{ + char *p; + int lpos = 0; + + for(p = data; *p != 0; p++){ + + if(sspm_is_printable(*p)){ + /* plain characters can represent themselves */ + /* RFC2045 Rule #2 */ + sspm_append_char(buf,*p); + lpos++; + } else if ( *p == '\t' || *p == ' ' ) { + + /* For tabs and spaces, only encode if they appear at the + end of the line */ + /* RFC2045 Rule #3 */ + + char n = *(p+1); + + if( n == '\n' || n == '\r'){ + sspm_append_hex(buf,*p); + lpos += 3; + } else { + sspm_append_char(buf,*p); + lpos++; + } + + } else if( *p == '\n' || *p == '\r'){ + sspm_append_char(buf,*p); + + lpos=0; + + } else { + /* All others need to be encoded */ + sspm_append_hex(buf,*p); + lpos+=3; + } + + + /* Add line breaks */ + if (lpos > 72){ + lpos = 0; + sspm_append_string(buf,"=\n"); + } + } +} + +static char BaseTable[64] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' +}; + +void sspm_write_base64(struct sspm_buffer *buf, char* inbuf,int size ) +{ + + char outbuf[4]; + int i; + + outbuf[0] = outbuf[1] = outbuf[2] = outbuf[3] = 65; + + switch(size){ + + case 4: + outbuf[3] = inbuf[2] & 0x3F; + + case 3: + outbuf[2] = ((inbuf[1] & 0x0F) << 2) | ((inbuf[2] & 0xC0) >> 6); + + case 2: + outbuf[0] = (inbuf[0] & 0xFC) >> 2; + outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf[1] & 0xF0) >> 4); + break; + + default: + assert(0); + } + + for(i = 0; i < 4; i++){ + + if(outbuf[i] == 65){ + sspm_append_char(buf,'='); + } else { + sspm_append_char(buf,BaseTable[(int)outbuf[i]]); + } + } +} + +void sspm_encode_base64(struct sspm_buffer *buf, char* data, size_t size) +{ + + char *p; + char inbuf[3]; + int i = 0; + int first = 1; + int lpos = 0; + + inbuf[0] = inbuf[1] = inbuf[2] = 0; + + for (p = data; *p !=0; p++){ + + if (i%3 == 0 && first == 0){ + + sspm_write_base64(buf, inbuf, 4); + lpos+=4; + + inbuf[0] = inbuf[1] = inbuf[2] = 0; + } + + assert(lpos%4 == 0); + + if (lpos == 72){ + sspm_append_string(buf,"\n"); + lpos = 0; + } + + inbuf[i%3] = *p; + + i++; + first = 0; + + } + + + /* If the inbuf was not exactly filled on the last byte, we need + to spit out the odd bytes that did get in -- either one or + two. This will result in an output of two bytes and '==' or + three bytes and '=', respectively */ + + if (i%3 == 1 && first == 0){ + sspm_write_base64(buf, inbuf, 2); + } else if (i%3 == 2 && first == 0){ + sspm_write_base64(buf, inbuf, 3); + } + +} + +void sspm_write_header(struct sspm_buffer *buf,struct sspm_header *header) +{ + + int i; + char temp[TMP_BUF_SIZE]; + char* major; + char* minor; + + /* Content-type */ + + major = sspm_major_type_string(header->major); + minor = sspm_minor_type_string(header->minor); + + if(header->minor == SSPM_UNKNOWN_MINOR_TYPE ){ + assert(header->minor_text !=0); + minor = header->minor_text; + } + + sprintf(temp,"Content-Type: %s/%s",major,minor); + + sspm_append_string(buf,temp); + + if(header->boundary != 0){ + sprintf(temp,";boundary=\"%s\"",header->boundary); + sspm_append_string(buf,temp); + } + + /* Append any content type parameters */ + if(header->content_type_params != 0){ + for(i=0; *(header->content_type_params[i])!= 0;i++){ + sprintf(temp,header->content_type_params[i]); + sspm_append_char(buf,';'); + sspm_append_string(buf,temp); + } + } + + sspm_append_char(buf,'\n'); + + /*Content-Transfer-Encoding */ + + if(header->encoding != SSPM_UNKNOWN_ENCODING && + header->encoding != SSPM_NO_ENCODING){ + sprintf(temp,"Content-Transfer-Encoding: %s\n", + sspm_encoding_string(header->encoding)); + } + + sspm_append_char(buf,'\n'); + +} + +void sspm_write_multipart_part(struct sspm_buffer *buf, + struct sspm_part *parts, + int* part_num) +{ + + int parent_level, level; + struct sspm_header *header = &(parts[*part_num].header); + /* Write the header for the multipart part */ + sspm_write_header(buf,header); + + parent_level = parts[*part_num].level; + + (*part_num)++; + + level = parts[*part_num].level; + + while(parts[*part_num].header.major != SSPM_NO_MAJOR_TYPE && + level == parent_level+1){ + + assert(header->boundary); + sspm_append_string(buf,header->boundary); + sspm_append_char(buf,'\n'); + + if (parts[*part_num].header.major == SSPM_MULTIPART_MAJOR_TYPE){ + sspm_write_multipart_part(buf,parts,part_num); + } else { + sspm_write_part(buf, &(parts[*part_num]), part_num); + } + + (*part_num)++; + level = parts[*part_num].level; + } + + sspm_append_string(buf,"\n\n--"); + sspm_append_string(buf,header->boundary); + sspm_append_string(buf,"\n"); + + (*part_num)--; /* undo last, spurious, increment */ +} + +void sspm_write_part(struct sspm_buffer *buf,struct sspm_part *part,int *part_num) +{ + + /* Write header */ + sspm_write_header(buf,&(part->header)); + + /* Write part data */ + + if(part->data == 0){ + return; + } + + if(part->header.encoding == SSPM_BASE64_ENCODING) { + assert(part->data_size != 0); + sspm_encode_base64(buf,part->data,part->data_size); + } else if(part->header.encoding == SSPM_QUOTED_PRINTABLE_ENCODING) { + sspm_encode_quoted_printable(buf,part->data); + } else { + sspm_append_string(buf,part->data); + } + + sspm_append_string(buf,"\n\n"); +} + +int sspm_write_mime(struct sspm_part *parts,size_t num_parts, + char **output_string, char* header) +{ + struct sspm_buffer buf; + int part_num =0; + + buf.buffer = malloc(4096); + buf.pos = buf.buffer; + buf.buf_size = 10; + buf.line_pos = 0; + + /* write caller's header */ + if(header != 0){ + sspm_append_string(&buf,header); + } + + if(buf.buffer[strlen(buf.buffer)-1] != '\n'){ + sspm_append_char(&buf,'\n'); + } + + /* write mime-version header */ + sspm_append_string(&buf,"Mime-Version: 1.0\n"); + + /* End of header */ + + /* Write body parts */ + while(parts[part_num].header.major != SSPM_NO_MAJOR_TYPE){ + if (parts[part_num].header.major == SSPM_MULTIPART_MAJOR_TYPE){ + sspm_write_multipart_part(&buf,parts,&part_num); + } else { + sspm_write_part(&buf, &(parts[part_num]), &part_num); + } + + part_num++; + } + + + *output_string = buf.buffer; + + return 0; +} + diff --git a/libical/src/libical/sspm.h b/libical/src/libical/sspm.h index 657b77a8d7..417f83eefd 100644 --- a/libical/src/libical/sspm.h +++ b/libical/src/libical/sspm.h @@ -37,6 +37,7 @@ #define SSPM_H enum sspm_major_type { + SSPM_NO_MAJOR_TYPE, SSPM_TEXT_MAJOR_TYPE, SSPM_IMAGE_MAJOR_TYPE, SSPM_AUDIO_MAJOR_TYPE, @@ -44,11 +45,11 @@ enum sspm_major_type { SSPM_APPLICATION_MAJOR_TYPE, SSPM_MULTIPART_MAJOR_TYPE, SSPM_MESSAGE_MAJOR_TYPE, - SSPM_UNKNOWN_MAJOR_TYPE, - SSPM_NO_MAJOR_TYPE + SSPM_UNKNOWN_MAJOR_TYPE }; enum sspm_minor_type { + SSPM_NO_MINOR_TYPE, SSPM_ANY_MINOR_TYPE, SSPM_PLAIN_MINOR_TYPE, SSPM_RFC822_MINOR_TYPE, @@ -58,8 +59,7 @@ enum sspm_minor_type { SSPM_RELATED_MINOR_TYPE, SSPM_ALTERNATIVE_MINOR_TYPE, SSPM_PARALLEL_MINOR_TYPE, - SSPM_UNKNOWN_MINOR_TYPE, - SSPM_NO_MINOR_TYPE + SSPM_UNKNOWN_MINOR_TYPE }; enum sspm_encoding { @@ -89,6 +89,7 @@ struct sspm_header enum sspm_major_type major; enum sspm_minor_type minor; char *minor_text; + char ** content_type_params; char* charset; enum sspm_encoding encoding; char* filename; @@ -100,6 +101,7 @@ struct sspm_header struct sspm_part { struct sspm_header header; int level; + size_t data_size; void *data; }; @@ -115,7 +117,7 @@ struct sspm_action_map { char* sspm_major_type_string(enum sspm_major_type type); char* sspm_minor_type_string(enum sspm_major_type type); - +char* sspm_encoding_string(enum sspm_encoding type); int sspm_parse_mime(struct sspm_part *parts, size_t max_parts, @@ -127,12 +129,15 @@ int sspm_parse_mime(struct sspm_part *parts, void sspm_free_parts(struct sspm_part *parts, size_t max_parts); -unsigned char *decode_quoted_printable(unsigned char *dest, - unsigned char *src, - size_t *size); -unsigned char *decode_base64(unsigned char *dest, - unsigned char *src, +char *decode_quoted_printable(char *dest, + char *src, size_t *size); +char *decode_base64(char *dest, + char *src, + size_t *size); + +int sspm_write_mime(struct sspm_part *parts,size_t num_parts, + char **output_string, char* header); -#endif SSPM_H +#endif /*SSPM_H*/ diff --git a/libical/src/libicalss/icaldirset.c b/libical/src/libicalss/icaldirset.c index ff5357126c..b377d54571 100644 --- a/libical/src/libicalss/icaldirset.c +++ b/libical/src/libicalss/icaldirset.c @@ -31,11 +31,10 @@ icaldirset manages a database of ical components and offers interfaces for reading, writting and searching for components. - icaldirset groups components in to clusters based on their DTSTART + icaldirset groups components in to clusters based on their DTSTAMP time -- all components that start in the same month are grouped together in a single file. All files in a sotre are kept in a single - directory. ( If a component does not have DTSTART, the store uses - DTSTAMP or CREATE ) + directory. The primary interfaces are icaldirset_first and icaldirset_next. These routine iterate through all of the components in the store, subject @@ -76,32 +75,25 @@ #include <stdlib.h> /* for rand(), srand() */ #include <sys/utsname.h> /* for uname */ #include <string.h> /* for strdup */ +#include "icaldirsetimpl.h" -struct icaldirset_impl -{ - char* dir; - icalcomponent* gauge; - icaldirset* cluster; - int first_component; - pvl_list directory; - pvl_elem directory_iterator; -}; - struct icaldirset_impl* icaldirset_new_impl() { - struct icaldirset_impl* comp; + struct icaldirset_impl* impl; - if ( ( comp = (struct icaldirset_impl*) + if ( ( impl = (struct icaldirset_impl*) malloc(sizeof(struct icaldirset_impl))) == 0) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } - return comp; + strcpy(impl->id,ICALDIRSET_ID); + + return impl; } -char* icaldirset_path(icaldirset* cluster) +const char* icaldirset_path(icaldirset* cluster) { struct icaldirset_impl *impl = icaldirset_new_impl(); @@ -125,12 +117,12 @@ icalerrorenum icaldirset_commit(icaldirset* store) } -void icaldirset_lock(char* dir) +void icaldirset_lock(const char* dir) { } -void icaldirset_unlock(char* dir) +void icaldirset_unlock(const char* dir) { } @@ -172,7 +164,7 @@ icalerrorenum icaldirset_read_directory(struct icaldirset_impl* impl) return ICAL_NO_ERROR; } -icaldirset* icaldirset_new(char* dir) +icaldirset* icaldirset_new(const char* dir) { struct icaldirset_impl *impl = icaldirset_new_impl(); struct stat sbuf; @@ -366,7 +358,7 @@ void icaldirset_add_uid(icaldirset* store, icaldirset* comp) /* This assumes that the top level component is a VCALENDAR, and there is an inner component of type VEVENT, VTODO or VJOURNAL. The inner - component must have a DTSTART property */ + component must have a DTAMP property */ icalerrorenum icaldirset_add_component(icaldirset* store, icaldirset* comp) { @@ -392,15 +384,32 @@ icalerrorenum icaldirset_add_component(icaldirset* store, icaldirset* comp) inner != 0; inner = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){ - dt = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY); - + dt = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY); + if (dt != 0){ break; } } if (dt == 0){ - icalerror_warn("The component does not have a DTSTART property, so it cannot be added to the store"); + + for(inner = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); + inner != 0; + inner = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){ + + dt = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY); + + if (dt != 0){ + break; + } + } + + } + + if (dt == 0){ + + + icalerror_warn("The component does not have a DTSTAMP or DTSTART property, so it cannot be added to the store"); icalerror_set_errno(ICAL_BADARG_ERROR); return ICAL_BADARG_ERROR; } @@ -488,7 +497,7 @@ icalerrorenum icaldirset_remove_component(icaldirset* store, icaldirset* comp) icalerrorenum error = icaldirset_next_cluster(store); if(impl->cluster != 0 && error == ICAL_NO_ERROR){ - icalfileset_get_first_component(impl->cluster,ICAL_ANY_COMPONENT); + icalfileset_get_first_component(impl->cluster); } else { /* HACK. Not strictly correct for impl->cluster==0 */ return error; @@ -503,10 +512,24 @@ icalerrorenum icaldirset_remove_component(icaldirset* store, icaldirset* comp) int icaldirset_count_components(icaldirset* store, - icalcomponent_kind kind); + icalcomponent_kind kind) +{ + /* HACK, not implemented */ + + assert(0); + + return 0; +} + + +icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c) +{ + fprintf(stderr," icaldirset_fetch_match is not implemented\n"); + assert(0); +} -icalcomponent* icaldirset_fetch(icaldirset* store, char* uid) +icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid) { icalcomponent *gauge; icalcomponent *old_gauge; @@ -532,7 +555,7 @@ icalcomponent* icaldirset_fetch(icaldirset* store, char* uid) old_gauge = impl->gauge; impl->gauge = gauge; - c= icaldirset_get_first_component(store,ICAL_ANY_COMPONENT); + c= icaldirset_get_first_component(store); impl->gauge = old_gauge; @@ -542,7 +565,7 @@ icalcomponent* icaldirset_fetch(icaldirset* store, char* uid) } -int icaldirset_has_uid(icaldirset* store, char* uid) +int icaldirset_has_uid(icaldirset* store, const char* uid) { icalcomponent *c; @@ -560,7 +583,7 @@ int icaldirset_has_uid(icaldirset* store, char* uid) icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge) -{ + { struct icaldirset_impl *impl = (struct icaldirset_impl*)store; icalerror_check_arg_re( (store!=0), "store",ICAL_BADARG_ERROR); @@ -575,16 +598,30 @@ icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge) return ICAL_NO_ERROR; } -void icaldirset_clear(icaldirset* store); -icalcomponent* icaldirset_fetch(icaldirset* store, char* uid); -int icaldirset_has_uid(icaldirset* store, char* uid); + +icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *old, + icalcomponent *new) +{ + assert(0); + return ICAL_NO_ERROR; /* HACK, not implemented */ + +} + + +void icaldirset_clear(icaldirset* store) +{ + + assert(0); + return; + /* HACK, not implemented */ +} icalcomponent* icaldirset_get_current_component(icaldirset* store) { struct icaldirset_impl *impl = (struct icaldirset_impl*)store; if(impl->cluster == 0){ - icaldirset_get_first_component(store,ICAL_ANY_COMPONENT); + icaldirset_get_first_component(store); } return icalfileset_get_current_component(impl->cluster); @@ -592,8 +629,7 @@ icalcomponent* icaldirset_get_current_component(icaldirset* store) } -icalcomponent* icaldirset_get_first_component(icaldirset* store, - icalcomponent_kind kind) +icalcomponent* icaldirset_get_first_component(icaldirset* store) { struct icaldirset_impl *impl = (struct icaldirset_impl*)store; icalerrorenum error; @@ -638,11 +674,10 @@ icalcomponent* icaldirset_get_first_component(icaldirset* store, impl->first_component = 1; - return icaldirset_get_next_component(store, kind); + return icaldirset_get_next_component(store); } -icalcomponent* icaldirset_get_next_component(icaldirset* store, - icalcomponent_kind kind) +icalcomponent* icaldirset_get_next_component(icaldirset* store) { struct icaldirset_impl *impl; icalcomponent *c; @@ -662,10 +697,10 @@ icalcomponent* icaldirset_get_next_component(icaldirset* store, /* Set the component iterator for the following for loop */ if (impl->first_component == 1){ - icalfileset_get_first_component(impl->cluster,kind); + icalfileset_get_first_component(impl->cluster); impl->first_component = 0; } else { - icalfileset_get_next_component(impl->cluster,kind); + icalfileset_get_next_component(impl->cluster); } @@ -673,9 +708,7 @@ icalcomponent* icaldirset_get_next_component(icaldirset* store, /* Iterate through all of the objects in the cluster*/ for( c = icalfileset_get_current_component(impl->cluster); c != 0; - c = icalfileset_get_next_component( - impl->cluster, - kind)){ + c = icalfileset_get_next_component(impl->cluster)){ /* If there is a gauge defined and the component does not pass the gauge, skip the rest of the loop */ @@ -698,9 +731,7 @@ icalcomponent* icaldirset_get_next_component(icaldirset* store, /* No more clusters */ return 0; } else { - c = icalfileset_get_first_component( - impl->cluster, - kind); + c = icalfileset_get_first_component(impl->cluster); return c; } diff --git a/libical/src/libicalss/icaldirset.h b/libical/src/libicalss/icaldirset.h index e9d6240aeb..7d205ecf0a 100644 --- a/libical/src/libicalss/icaldirset.h +++ b/libical/src/libicalss/icaldirset.h @@ -30,7 +30,6 @@ #define ICALDIRSET_H #include "ical.h" -#include "icalerror.h" /* icaldirset Routines for storing, fetching, and searching for ical * objects in a database */ @@ -38,11 +37,11 @@ typedef void icaldirset; -icaldirset* icaldirset_new(char* path); +icaldirset* icaldirset_new(const char* path); void icaldirset_free(icaldirset* store); -char* icaldirset_path(icaldirset* store); +const char* icaldirset_path(icaldirset* store); /* Mark the cluster as changed, so it will be written to disk when it is freed. Commit writes to disk immediately*/ @@ -61,22 +60,21 @@ icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge); void icaldirset_clear(icaldirset* store); /* Get a component by uid */ -icalcomponent* icaldirset_fetch(icaldirset* store, char* uid); -int icaldirset_has_uid(icaldirset* store, char* uid); +icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid); +int icaldirset_has_uid(icaldirset* store, const char* uid); +icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c); /* Modify components according to the MODIFY method of CAP. Works on the currently selected components. */ -icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *old, - icalcomponent *new); +icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *oldc, + icalcomponent *newc); /* Iterate through the components. If a guage has been defined, these will skip over components that do not pass the gauge */ icalcomponent* icaldirset_get_current_component(icaldirset* store); -icalcomponent* icaldirset_get_first_component(icaldirset* store, - icalcomponent_kind kind); -icalcomponent* icaldirset_get_next_component(icaldirset* store, - icalcomponent_kind kind); +icalcomponent* icaldirset_get_first_component(icaldirset* store); +icalcomponent* icaldirset_get_next_component(icaldirset* store); #endif /* !ICALDIRSET_H */ diff --git a/libical/src/libicalss/icalfileset.c b/libical/src/libicalss/icalfileset.c index 46c5cd2586..a7527ff3e0 100644 --- a/libical/src/libicalss/icalfileset.c +++ b/libical/src/libicalss/icalfileset.c @@ -30,7 +30,6 @@ #include "config.h" #endif - #include "icalfileset.h" #include <errno.h> #include <limits.h> /* For PATH_MAX */ @@ -46,21 +45,22 @@ int icalfileset_lock(icalfileset *cluster); int icalfileset_unlock(icalfileset *cluster); - -icalerrorenum icalfileset_create_cluster(char *path); +icalerrorenum icalfileset_create_cluster(const char *path); icalfileset* icalfileset_new_impl() { - struct icalfileset_impl* comp; + struct icalfileset_impl* impl; - if ( ( comp = (struct icalfileset_impl*) + if ( ( impl = (struct icalfileset_impl*) malloc(sizeof(struct icalfileset_impl))) == 0) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); errno = ENOMEM; return 0; } - return comp; + strcpy(impl->id,ICALFILESET_ID); + + return impl; } char* read_from_file(char *s, size_t size, void *d) @@ -69,7 +69,7 @@ char* read_from_file(char *s, size_t size, void *d) return c; } -icalfileset* icalfileset_new(char* path) +icalfileset* icalfileset_new(const char* path) { struct icalfileset_impl *impl = icalfileset_new_impl(); struct stat sbuf; @@ -205,7 +205,7 @@ void icalfileset_free(icalfileset* cluster) free(impl); } -char* icalfileset_path(icalfileset* cluster) +const char* icalfileset_path(icalfileset* cluster) { struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; icalerror_check_arg_rz((cluster!=0),"cluster"); @@ -250,7 +250,7 @@ int icalfileset_unlock(icalfileset *cluster) } -icalerrorenum icalfileset_create_cluster(char *path) +icalerrorenum icalfileset_create_cluster(const char *path) { FILE* f; @@ -387,11 +387,158 @@ int icalfileset_count_components(icalfileset *cluster, return icalcomponent_count_components(impl->cluster,kind); } -icalerrorenum icalfileset_select(icalfileset* cluster, icalcomponent* gauge); -void icalfileset_clear(icalfileset* cluster); +icalerrorenum icalfileset_select(icalfileset* cluster, icalcomponent* gauge) +{ + assert(0); /* HACK, not implemented */ + return ICAL_NO_ERROR; +} + +void icalfileset_clear(icalfileset* cluster) +{ + assert(0); /* HACK, not implemented */ +} + +icalcomponent* icalfileset_fetch(icalfileset* store,const char* uid) +{ + icalcompiter i; + struct icalfileset_impl* impl = (struct icalfileset_impl*)store; + + for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT); + icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){ + + icalcomponent *this = icalcompiter_deref(&i); + icalcomponent *inner = icalcomponent_get_first_real_component(this); + icalcomponent *p; + const char *this_uid; + + if(inner != 0){ + p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY); + this_uid = icalproperty_get_uid(p); + + if(this_uid==0){ + icalerror_warn("icalfileset_fetch found a component with no UID"); + continue; + } + + if (strcmp(uid,this_uid)==0){ + return this; + } + } + } + + return 0; +} + +int icalfileset_has_uid(icalfileset* store,const char* uid) +{ + assert(0); /* HACK, not implemented */ + return 0; +} + +/******* support routines for icalfileset_fetch_match *********/ + +struct icalfileset_id{ + char* uid; + char* recurrence_id; + int sequence; +}; + +void icalfileset_id_free(struct icalfileset_id *id) +{ + if(id->recurrence_id != 0){ + free(id->recurrence_id); + } + + if(id->uid != 0){ + free(id->uid); + } + +} + +struct icalfileset_id icalfileset_get_id(icalcomponent* comp) +{ + + icalcomponent *inner; + struct icalfileset_id id; + icalproperty *p; + + inner = icalcomponent_get_first_real_component(comp); + + p = icalcomponent_get_first_property(inner, ICAL_UID_PROPERTY); + + assert(p!= 0); + + id.uid = strdup(icalproperty_get_uid(p)); + + p = icalcomponent_get_first_property(inner, ICAL_SEQUENCE_PROPERTY); + + if(p == 0) { + id.sequence = 0; + } else { + id.sequence = icalproperty_get_sequence(p); + } + + p = icalcomponent_get_first_property(inner, ICAL_RECURRENCEID_PROPERTY); + + if (p == 0){ + id.recurrence_id = 0; + } else { + icalvalue *v; + v = icalproperty_get_value(p); + id.recurrence_id = strdup(icalvalue_as_ical_string(v)); + + assert(id.recurrence_id != 0); + } + + return id; +} + +/* Find the component that is related to the given + component. Currently, it just matches based on UID and + RECURRENCE-ID */ +icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *comp) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)set; + icalcompiter i; + + struct icalfileset_id comp_id, match_id; + + comp_id = icalfileset_get_id(comp); + + for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT); + icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){ + + icalcomponent *match = icalcompiter_deref(&i); + + match_id = icalfileset_get_id(match); + + if(strcmp(comp_id.uid, match_id.uid) == 0 && + ( comp_id.recurrence_id ==0 || + strcmp(comp_id.recurrence_id, match_id.recurrence_id) ==0 )){ + + /* HACK. What to do with SEQUENCE? */ + + icalfileset_id_free(&match_id); + icalfileset_id_free(&comp_id); + return match; + + } + + icalfileset_id_free(&match_id); + } + + icalfileset_id_free(&comp_id); + return 0; + +} + -icalcomponent* icalfileset_fetch(icalfileset* store, char* uid); -int icalfileset_has_uid(icalfileset* store, char* uid); +icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *old, + icalcomponent *new) +{ + assert(0); /* HACK, not implemented */ + return ICAL_NO_ERROR; +} /* Iterate through components */ @@ -405,23 +552,21 @@ icalcomponent* icalfileset_get_current_component (icalfileset* cluster) } -icalcomponent* icalfileset_get_first_component(icalfileset* cluster, - icalcomponent_kind kind) +icalcomponent* icalfileset_get_first_component(icalfileset* cluster) { struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; icalerror_check_arg_rz((cluster!=0),"cluster"); - return icalcomponent_get_first_component(impl->cluster,kind); + return icalcomponent_get_first_component(impl->cluster,ICAL_ANY_COMPONENT); } -icalcomponent* icalfileset_get_next_component(icalfileset* cluster, - icalcomponent_kind kind) +icalcomponent* icalfileset_get_next_component(icalfileset* cluster) { struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; icalerror_check_arg_rz((cluster!=0),"cluster"); - return icalcomponent_get_next_component(impl->cluster,kind); + return icalcomponent_get_next_component(impl->cluster,ICAL_ANY_COMPONENT); } diff --git a/libical/src/libicalss/icalfileset.h b/libical/src/libicalss/icalfileset.h index 8ceae632be..4430f1dc74 100644 --- a/libical/src/libicalss/icalfileset.h +++ b/libical/src/libicalss/icalfileset.h @@ -40,10 +40,10 @@ typedef void icalfileset; */ -icalfileset* icalfileset_new(char* path); +icalfileset* icalfileset_new(const char* path); void icalfileset_free(icalfileset* cluster); -char* icalfileset_path(icalfileset* cluster); +const char* icalfileset_path(icalfileset* cluster); /* Mark the cluster as changed, so it will be written to disk when it is freed. Commit writes to disk immediately. */ @@ -65,19 +65,22 @@ icalerrorenum icalfileset_select(icalfileset* store, icalcomponent* gauge); void icalfileset_clear(icalfileset* store); /* Get and search for a component by uid */ -icalcomponent* icalfileset_fetch(icalfileset* cluster, char* uid); -int icalfileset_has_uid(icalfileset* cluster, char* uid); +icalcomponent* icalfileset_fetch(icalfileset* cluster, const char* uid); +int icalfileset_has_uid(icalfileset* cluster, const char* uid); +icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *c); +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *oldcomp, + icalcomponent *newcomp); + /* Iterate through components. If a guage has been defined, these will skip over components that do not pass the gauge */ icalcomponent* icalfileset_get_current_component (icalfileset* cluster); -icalcomponent* icalfileset_get_first_component(icalfileset* cluster, - icalcomponent_kind kind); -icalcomponent* icalfileset_get_next_component(icalfileset* cluster, - icalcomponent_kind kind); - +icalcomponent* icalfileset_get_first_component(icalfileset* cluster); +icalcomponent* icalfileset_get_next_component(icalfileset* cluster); /* Return a reference to the internal component. You probably should not be using this. */ diff --git a/libical/src/libicalss/icalfilesetimpl.h b/libical/src/libicalss/icalfilesetimpl.h index de447c64eb..767dceeadd 100644 --- a/libical/src/libicalss/icalfilesetimpl.h +++ b/libical/src/libicalss/icalfilesetimpl.h @@ -33,7 +33,11 @@ /* This definition is in its own file so it can be kept out of the main header file, but used by "friend classes" like icaldirset*/ +#define ICALFILESET_ID "fset" + struct icalfileset_impl { + + char id[5]; /*fset*/ char *path; icalcomponent* cluster; int changed; diff --git a/libical/src/libicalss/icalgauge.c b/libical/src/libicalss/icalgauge.c index 60ce1587cd..0bbcd20bfc 100644 --- a/libical/src/libicalss/icalgauge.c +++ b/libical/src/libicalss/icalgauge.c @@ -27,6 +27,45 @@ ======================================================================*/ #include "ical.h" +#include "icalgauge.h" +#include "icalgaugeimpl.h" +#include <stdlib.h> + + +extern char* input_buffer; +extern char* input_buffer_p; +int ssparse(void); + +struct icalgauge_impl *icalss_yy_gauge; + +icalgauge* icalgauge_new_from_sql(char* sql) +{ + struct icalgauge_impl *impl; + + int r; + + if ( ( impl = (struct icalgauge_impl*) + malloc(sizeof(struct icalgauge_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + impl->select = icalcomponent_new(ICAL_XROOT_COMPONENT); + impl->from = icalcomponent_new(ICAL_XROOT_COMPONENT); + impl->where = icalcomponent_new(ICAL_XROOT_COMPONENT); + + icalss_yy_gauge = impl; + + input_buffer_p = input_buffer = sql; + r = ssparse(); + + return impl; +} + + +void icalgauge_free(icalgauge* gauge) +{ +} /* Convert a VQUERY component into a gauge */ icalcomponent* icalgauge_make_gauge(icalcomponent* query); @@ -44,22 +83,18 @@ icalcomponent* icalgauge_make_gauge(icalcomponent* query); When a gauge has several sub-components, the results of testing the target against each of them is ORed together - the target component will pass if it matches any of the sub-components in the - gauge. However, the results of matching the proeprties in a + gauge. However, the results of matching the properties in a sub-component are ANDed -- the target must match every property in a gauge sub-component to match the sub-component. Here is an example: BEGIN:XROOT - BEGIN:VCOMPONENT - BEGIN:VEVENT DTSTART;X-LIC-COMPARETYPE=LESS:19981025T020000 ORGANIZER;X-LIC-COMPARETYPE=EQUAL:mrbig@host.com - END:VEVENT - BEGIN:VEVENT + END:XROOT + BEGIN:XROOT LOCATION;X-LIC-COMPARETYPE=EQUAL:McNary's Pub - END:VEVENT - END:VCALENDAR END:XROOT This gauge has two sub-components; one which will match a VEVENT @@ -194,9 +229,11 @@ int icalgauge_test(icalcomponent* comp, icalerror_check_arg_rz( (comp!=0), "comp"); icalerror_check_arg_rz( (gauge!=0), "gauge"); - for(gauge = icalcomponent_get_first_component(gaugecontainer,ICAL_ANY_COMPONENT); + for(gauge = icalcomponent_get_first_component(gaugecontainer, + ICAL_ANY_COMPONENT); gauge != 0; - gauge = icalcomponent_get_next_component(gaugecontainer,ICAL_ANY_COMPONENT)){ + gauge = icalcomponent_get_next_component(gaugecontainer, + ICAL_ANY_COMPONENT)){ pass += icalgauge_test_recurse(comp, gauge); } diff --git a/libical/src/libicalss/icalgauge.h b/libical/src/libicalss/icalgauge.h index 401d9b7347..2fbb3aab8c 100644 --- a/libical/src/libicalss/icalgauge.h +++ b/libical/src/libicalss/icalgauge.h @@ -29,8 +29,14 @@ #ifndef ICALGAUGE_H #define ICALGAUGE_H -icalcomponent* icalgauge_new_from_vquery(char* vquery); -char* icalgauge_as_vquery(icalcomponent* gauge); +typedef void icalgauge; + +icalgauge* icalgauge_new_from_sql(char* sql); + +void icalgauge_free(icalgauge* gauge); + +char* icalgauge_as_sql(icalcomponent* gauge); + int icalgauge_test(icalcomponent* comp, icalcomponent* gaugecontainer); diff --git a/libical/src/libicalss/icalset.c b/libical/src/libicalss/icalset.c index 01a36c0129..2ffe0deff2 100644 --- a/libical/src/libicalss/icalset.c +++ b/libical/src/libicalss/icalset.c @@ -5,9 +5,9 @@ Icalset is the "base class" for representations of a collection of - iCal components. Derived classes (actually delegatees) include: + iCal components. Derived classes (actually delegates) include: - icalfileset Store componetns in a single file + icalfileset Store components in a single file icaldirset Store components in multiple files in a directory icalheapset Store components on the heap icalmysqlset Store components in a mysql database. @@ -37,49 +37,330 @@ #include "ical.h" #include "icalset.h" #include "icalfileset.h" +#include "icalfilesetimpl.h" #include "icaldirset.h" +#include "icaldirsetimpl.h" +#include <stdlib.h> /*#include "icalheapset.h"*/ /*#include "icalmysqlset.h"*/ -icalset* icalset_new_file(char* path); +#define ICALSET_ID "set " -icalset* icalset_new_dir(char* path); - -icalset* icalset_new_heap(void); - -icalset* icalset_new_mysql(char* path); - -void icalset_free(icalset* set); +struct icalset_fp { + void (*free)(icalset* set); + const char* (*path)(icalset* set); + void (*mark)(icalset* set); + icalerrorenum (*commit)(icalset* set); + icalerrorenum (*add_component)(icalset* set, icalcomponent* comp); + icalerrorenum (*remove_component)(icalset* set, icalcomponent* comp); + int (*count_components)(icalset* set, + icalcomponent_kind kind); + icalerrorenum (*select)(icalset* set, icalcomponent* gauge); + void (*clear)(icalset* set); + icalcomponent* (*fetch)(icalset* set, const char* uid); + icalcomponent* (*fetch_match)(icalset* set, icalcomponent *comp); + int (*has_uid)(icalset* set, const char* uid); + icalerrorenum (*modify)(icalset* set, icalcomponent *old, + icalcomponent *new); + icalcomponent* (*get_current_component)(icalset* set); + icalcomponent* (*get_first_component)(icalset* set); + icalcomponent* (*get_next_component)(icalset* set); +}; + +struct icalset_fp icalset_dirset_fp = { + icaldirset_free, + icaldirset_path, + icaldirset_mark, + icaldirset_commit, + icaldirset_add_component, + icaldirset_remove_component, + icaldirset_count_components, + icaldirset_select, + icaldirset_clear, + icaldirset_fetch, + icaldirset_fetch_match, + icaldirset_has_uid, + icaldirset_modify, + icaldirset_get_current_component, + icaldirset_get_first_component, + icaldirset_get_next_component +}; + + +struct icalset_fp icalset_fileset_fp = { + icalfileset_free, + icalfileset_path, + icalfileset_mark, + icalfileset_commit, + icalfileset_add_component, + icalfileset_remove_component, + icalfileset_count_components, + icalfileset_select, + icalfileset_clear, + icalfileset_fetch, + icalfileset_fetch_match, + icalfileset_has_uid, + icalfileset_modify, + icalfileset_get_current_component, + icalfileset_get_first_component, + icalfileset_get_next_component +}; + +struct icalset_impl { + + char id[5]; /* "set " */ + + void *derived_impl; + struct icalset_fp *fp; +}; + +/* Figure out what was actually passed in as the set. This could be a + set or and of the derived types such as dirset or fileset. Note + this routine returns a value, not a reference, to avoid memory + leaks in the methods */ +struct icalset_impl icalset_get_impl(icalset* set) +{ + struct icalset_impl impl; + + memset(&impl,0,sizeof(impl)); + icalerror_check_arg_rv( (set!=0),"set"); + + if(strcmp((char*)set,ICALSET_ID)==0) { + /* It is actually a set, so just sent the reference back out. */ + return *(struct icalset_impl*)set; + } else if(strcmp((char*)set,ICALFILESET_ID)==0) { + /* Make a new set from the fileset */ + impl.fp = &icalset_fileset_fp; + impl.derived_impl = set; + strcpy(impl.id,ICALFILESET_ID);/* HACK. Is this necessary? */ + return impl; + } else if(strcmp((char*)set,ICALDIRSET_ID)==0) { + /* Make a new set from the dirset */ + impl.fp = &icalset_dirset_fp; + impl.derived_impl = set; + strcpy(impl.id,ICALDIRSET_ID);/* HACK. Is this necessary? */ + return impl; + } else { + /* The type of set is unknown, so throw an error */ + icalerror_assert((0),"Unknown set type"); + return impl; + } +} + + +struct icalset_impl* icalset_new_impl() +{ + + struct icalset_impl* impl; + + if ( ( impl = (struct icalset_impl*) + malloc(sizeof(struct icalset_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + strcpy(impl->id,ICALSET_ID); + + impl->derived_impl = 0; + impl->fp = 0; + + return impl; +} + +struct icalset_impl* icalset_new_file_from_ref(icalfileset *fset) +{ + struct icalset_impl *impl = icalset_new_impl(); + + icalerror_check_arg_rz( (fset!=0),"fset"); + + if(impl == 0){ + free(impl); + return 0; + } + + impl->derived_impl = fset; + + if (impl->derived_impl == 0){ + free(impl); + return 0; + } + + impl->fp = &icalset_fileset_fp; + + return (struct icalset_impl*)impl; +} + +icalset* icalset_new_file(const char* path) +{ + icalfileset *fset = icalfileset_new(path); + + if(fset == 0){ + return 0; + } + + return (icalset*)icalset_new_file_from_ref(fset); +} + +icalset* icalset_new_dir_from_ref(icaldirset *dset) +{ + + struct icalset_impl *impl = icalset_new_impl(); + + icalerror_check_arg_rz( (dset!=0),"dset"); + + if(impl == 0){ + return 0; + } + + impl->derived_impl = dset; + + if (impl->derived_impl == 0){ + free(impl); + return 0; + } + + impl->fp = &icalset_dirset_fp; + + return impl; +} + +icalset* icalset_new_dir(const char* path) +{ + icaldirset *dset = icaldirset_new(path); + + if(dset == 0){ + return 0; + } + + return icalset_new_dir_from_ref(dset); +} + +icalset* icalset_new_heap(void) +{ + struct icalset_impl *impl = icalset_new_impl(); -char* icalset_path(icalset* set); -void icalset_mark(icalset* set); + if(impl == 0){ + free(impl); + return 0; + } -icalerrorenum icalset_commit(icalset* set); + return 0; +} -icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp); +icalset* icalset_new_mysql(const char* path) +{ + struct icalset_impl *impl = icalset_new_impl(); -icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp); + if(impl == 0){ + free(impl); + return 0; + } -int icalset_count_components(icalset* set, - icalcomponent_kind kind); + return 0; +} -icalerrorenum icalset_select(icalset* set, icalcomponent* gauge); +void icalset_free(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->free))(impl.derived_impl); -void icalset_clear_select(icalset* set); + if(strcmp((char*)set,ICALSET_ID)) { + free(set); + } +} -icalcomponent* icalset_fetch(icalset* set, char* uid); +const char* icalset_path(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->path))(impl.derived_impl); +} -int icalset_has_uid(icalset* set, char* uid); +void icalset_mark(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->mark))(impl.derived_impl); +} + +icalerrorenum icalset_commit(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->commit))(impl.derived_impl); +} + +icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->add_component))(impl.derived_impl,comp); +} + +icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->remove_component))(impl.derived_impl,comp); +} + +int icalset_count_components(icalset* set,icalcomponent_kind kind) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->count_components))(impl.derived_impl,kind); +} + +icalerrorenum icalset_select(icalset* set, icalcomponent* gauge) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->select))(impl.derived_impl,gauge); +} + +void icalset_clear(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->clear))(impl.derived_impl); +} + +icalcomponent* icalset_fetch(icalset* set, const char* uid) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->fetch))(impl.derived_impl,uid); +} + +icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->fetch_match))(impl.derived_impl,comp); +} + + +int icalset_has_uid(icalset* set, const char* uid) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->has_uid))(impl.derived_impl,uid); +} icalerrorenum icalset_modify(icalset* set, icalcomponent *old, - icalcomponent *new); - -icalcomponent* icalset_get_current_component(icalset* set); - -icalcomponent* icalset_get_first_component(icalset* set); - -icalcomponent* icalset_get_next_component(icalset* set); + icalcomponent *new) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->modify))(impl.derived_impl,old,new); +} + +icalcomponent* icalset_get_current_component(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->get_current_component))(impl.derived_impl); +} + +icalcomponent* icalset_get_first_component(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->get_first_component))(impl.derived_impl); +} + +icalcomponent* icalset_get_next_component(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->get_next_component))(impl.derived_impl); +} diff --git a/libical/src/libicalss/icalset.h b/libical/src/libicalss/icalset.h index 15bb71f72e..d4678e3bed 100644 --- a/libical/src/libicalss/icalset.h +++ b/libical/src/libicalss/icalset.h @@ -52,15 +52,15 @@ typedef enum icalset_kind { /* Create a specific derived type of set */ -icalset* icalset_new_file(char* path); -icalset* icalset_new_dir(char* path); +icalset* icalset_new_file(const char* path); +icalset* icalset_new_dir(const char* path); icalset* icalset_new_heap(void); -icalset* icalset_new_mysql(char* path); +icalset* icalset_new_mysql(const char* path); /*icalset* icalset_new_cap(icalcstp* cstp);*/ void icalset_free(icalset* set); -char* icalset_path(icalset* set); +const char* icalset_path(icalset* set); /* Mark the cluster as changed, so it will be written to disk when it is freed. Commit writes to disk immediately*/ @@ -79,13 +79,14 @@ icalerrorenum icalset_select(icalset* set, icalcomponent* gauge); void icalset_clear_select(icalset* set); /* Get a component by uid */ -icalcomponent* icalset_fetch(icalset* set, char* uid); -int icalset_has_uid(icalset* set, char* uid); +icalcomponent* icalset_fetch(icalset* set, const char* uid); +int icalset_has_uid(icalset* set, const char* uid); +icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *c); /* Modify components according to the MODIFY method of CAP. Works on the currently selected components. */ -icalerrorenum icalset_modify(icalset* set, icalcomponent *old, - icalcomponent *new); +icalerrorenum icalset_modify(icalset* set, icalcomponent *oldc, + icalcomponent *newc); /* Iterate through the components. If a guage has been defined, these will skip over components that do not pass the gauge */ diff --git a/libical/src/libicalvcal/icalvcal.c b/libical/src/libicalvcal/icalvcal.c index d21dd4acc6..9ae00a7d90 100644 --- a/libical/src/libicalvcal/icalvcal.c +++ b/libical/src/libicalvcal/icalvcal.c @@ -20,6 +20,23 @@ The original code is icalvcal.c + + + The icalvcal_convert routine calls icalvcal_traverse_objects to do + its work.s his routine steps through through all of the properties + and components of a VObject. For each name of a property or a + component, icalvcal_traverse_objects looks up the name in + conversion_table[]. This table indicates wether the name is of a + component or a property, lists a routine to handle conversion, and + has extra data for the conversion. + + The conversion routine will create new iCal components or properties + and add them to the iCal component structure. + + The most common conversion routine is dc_prop. This routine converts + properties for which the text representation of the vCal component + is identical the iCal representation. + ======================================================================*/ #include "icalvcal.h" @@ -43,7 +60,7 @@ struct conversion_table_struct { struct conversion_table_struct conversion_table[]; void* dc_prop(int icaltype, VObject *object); -static void traverse_objects(VObject *object,icalcomponent* last_comp, +static void icalvcal_traverse_objects(VObject *object,icalcomponent* last_comp, icalproperty* last_prop) { VObjectIterator iterator; @@ -66,6 +83,8 @@ static void traverse_objects(VObject *object,icalcomponent* last_comp, } } + /* Did not find the object. It may be an X-property, or an unknown + property */ if (conversion_table[i].vcalname == 0){ /* Handle X properties */ @@ -158,10 +177,10 @@ static void traverse_objects(VObject *object,icalcomponent* last_comp, should use it as the 'last_comp' */ if(subc!=0){ - traverse_objects(eachProp,subc,last_prop); + icalvcal_traverse_objects(eachProp,subc,last_prop); } else { - traverse_objects(eachProp,last_comp,last_prop); + icalvcal_traverse_objects(eachProp,last_comp,last_prop); } } } @@ -180,7 +199,7 @@ icalcomponent* icalvcal_convert(VObject *object){ } - traverse_objects(object,container,0); + icalvcal_traverse_objects(object,container,0); /* HACK. I am using the extra 'container' component because I am lazy. I know there is a way to get rid of it, but I did not care diff --git a/libical/src/test/recur.c b/libical/src/test/recur.c index 4d3188f9c2..2967ee7977 100644 --- a/libical/src/test/recur.c +++ b/libical/src/test/recur.c @@ -52,11 +52,9 @@ int main(int argc, char *argv[]) cin = icalfileset_new(argv[1]); assert(cin != 0); - for (itr = icalfileset_get_first_component(cin, - ICAL_ANY_COMPONENT); + for (itr = icalfileset_get_first_component(cin); itr != 0; - itr = icalfileset_get_next_component(cin, - ICAL_ANY_COMPONENT)){ + itr = icalfileset_get_next_component(cin)){ desc = icalcomponent_get_first_property(itr,ICAL_DESCRIPTION_PROPERTY); assert(desc !=0); diff --git a/libical/src/test/testmime.c b/libical/src/test/testmime.c index a912983f84..5dfc3b7d31 100644 --- a/libical/src/test/testmime.c +++ b/libical/src/test/testmime.c @@ -86,6 +86,7 @@ char* read_stream(char *s, size_t size, void *d) } + int main(int argc, char* argv[]) { FILE *f; @@ -135,7 +136,7 @@ int main(int argc, char* argv[]) { opt.stress = 1; break; } - case 'b':{ /* test base64 encoding*/ + case 'b':{ /* test base64 decoding*/ if(opt.stress+opt.normal+opt.qp != 0){ fprintf(stderr, "%s: Use only one of n,s,b and q\n", @@ -144,7 +145,7 @@ int main(int argc, char* argv[]) { opt.base64 = 1; break; } - case 'q':{ /* test quoted-printable encoding*/ + case 'q':{ /* test quoted-printable decoding*/ if(opt.stress+opt.base64+opt.normal != 0){ fprintf(stderr, "%s: Use only one of n,s,b and q\n", |