This commit was generated by cvs2svn to compensate for changes in r6917,
which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=6918
This commit is contained in:
@ -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")),
|
||||
icalproperty_new_description("Project XYZ Review Meeting"),
|
||||
|
||||
/* Again, note the use of strdup to give libical
|
||||
ownership of a static string. */
|
||||
|
||||
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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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){
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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){
|
||||
|
||||
if (parts[i].header.encoding != 0){
|
||||
icalcomponent_add_property(comp,
|
||||
icalproperty_new_xlicmimeencoding(parts[i].header.encoding));
|
||||
icalproperty_new_xlicmimecontenttype((char*)
|
||||
icalmemory_strdup(mimetype)));
|
||||
|
||||
}
|
||||
|
||||
if (parts[i].header.encoding != SSPM_NO_ENCODING){
|
||||
|
||||
icalcomponent_add_property(comp,
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
if (impl->last.second > 59){
|
||||
impl->last.second = 0;
|
||||
increment_minute(impl,1);
|
||||
}
|
||||
|
||||
|
||||
minutes = impl->last.second / 60;
|
||||
impl->last.second = impl->last.second % 60;
|
||||
|
||||
if (minutes != 0)
|
||||
{
|
||||
increment_minute(impl, minutes);
|
||||
}
|
||||
}
|
||||
|
||||
#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));
|
||||
|
||||
struct icalrecurrencetype r = icalvalue_get_recur(v);
|
||||
struct icaltimetype t = icaltime_from_timet( time(0), 0, 0);
|
||||
struct icaltimetype next;
|
||||
time_t tt;
|
||||
|
||||
struct icalrecur_iterator_impl* itr
|
||||
= (struct icalrecur_iterator_impl*) icalrecur_iterator_new(r,t);
|
||||
|
||||
do {
|
||||
|
||||
next = icalrecur_iterator_next(itr);
|
||||
tt = icaltime_as_timet(next);
|
||||
|
||||
printf("%s",ctime(&tt ));
|
||||
|
||||
} while( ! icaltime_is_null_time(next));
|
||||
|
||||
recur->week_start = ICAL_MONDAY_WEEKDAY;
|
||||
recur->freq = ICAL_NO_RECURRENCE;
|
||||
recur->interval = 1;
|
||||
memset(&(recur->until),0,sizeof(struct icaltimetype));
|
||||
recur->count = 0;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
||||
The day's position in the period ( Nth-ness) and the numerical value
|
||||
of the day are encoded together as: pos*7 + dow
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/****************** 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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*);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
#endif SSPM_H
|
||||
int sspm_write_mime(struct sspm_part *parts,size_t num_parts,
|
||||
char **output_string, char* header);
|
||||
|
||||
#endif /*SSPM_H*/
|
||||
|
||||
@ -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(icaldirset* store, char* uid)
|
||||
icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c)
|
||||
{
|
||||
fprintf(stderr," icaldirset_fetch_match is not implemented\n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
icalcomponent* icalfileset_fetch(icalfileset* store, char* uid);
|
||||
int icalfileset_has_uid(icalfileset* store, char* uid);
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -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. */
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
char* icalset_path(icalset* set);
|
||||
|
||||
void icalset_mark(icalset* set);
|
||||
|
||||
icalerrorenum icalset_commit(icalset* set);
|
||||
|
||||
icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp);
|
||||
|
||||
icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp);
|
||||
|
||||
int icalset_count_components(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);
|
||||
};
|
||||
|
||||
icalerrorenum icalset_select(icalset* set, icalcomponent* gauge);
|
||||
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
|
||||
};
|
||||
|
||||
void icalset_clear_select(icalset* set);
|
||||
|
||||
icalcomponent* icalset_fetch(icalset* set, char* uid);
|
||||
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
|
||||
};
|
||||
|
||||
int icalset_has_uid(icalset* set, char* uid);
|
||||
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();
|
||||
|
||||
|
||||
if(impl == 0){
|
||||
free(impl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
icalset* icalset_new_mysql(const char* path)
|
||||
{
|
||||
struct icalset_impl *impl = icalset_new_impl();
|
||||
|
||||
if(impl == 0){
|
||||
free(impl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void icalset_free(icalset* set)
|
||||
{
|
||||
struct icalset_impl impl = icalset_get_impl(set);
|
||||
return (*(impl.fp->free))(impl.derived_impl);
|
||||
|
||||
if(strcmp((char*)set,ICALSET_ID)) {
|
||||
free(set);
|
||||
}
|
||||
}
|
||||
|
||||
const char* icalset_path(icalset* set)
|
||||
{
|
||||
struct icalset_impl impl = icalset_get_impl(set);
|
||||
return (*(impl.fp->path))(impl.derived_impl);
|
||||
}
|
||||
|
||||
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 *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);
|
||||
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);
|
||||
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);
|
||||
icalcomponent* icalset_get_next_component(icalset* set)
|
||||
{
|
||||
struct icalset_impl impl = icalset_get_impl(set);
|
||||
return (*(impl.fp->get_next_component))(impl.derived_impl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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",
|
||||
|
||||
Reference in New Issue
Block a user