aboutsummaryrefslogtreecommitdiffstats
path: root/libical/src
diff options
context:
space:
mode:
authorEric Busboom <ericb@src.gnome.org>2000-05-15 12:25:38 +0800
committerEric Busboom <ericb@src.gnome.org>2000-05-15 12:25:38 +0800
commitdf7ae02e104cb32ce5854679ba4cd27e0b2086a9 (patch)
tree1fa9d082dcc6da46cbd98729e769be1ae21c492e /libical/src
parentdf22a401de5575b3813070a6bcafb20ec0ef6e22 (diff)
downloadgsoc2013-evolution-df7ae02e104cb32ce5854679ba4cd27e0b2086a9.tar.gz
gsoc2013-evolution-df7ae02e104cb32ce5854679ba4cd27e0b2086a9.tar.zst
gsoc2013-evolution-df7ae02e104cb32ce5854679ba4cd27e0b2086a9.zip
Initial revision
svn path=/trunk/; revision=3034
Diffstat (limited to 'libical/src')
-rw-r--r--libical/src/libicalss/icalcsdb.h61
-rw-r--r--libical/src/libicalss/icalcstp.h113
-rw-r--r--libical/src/test/regression.out431
-rw-r--r--libical/src/test/stow.c533
4 files changed, 1138 insertions, 0 deletions
diff --git a/libical/src/libicalss/icalcsdb.h b/libical/src/libicalss/icalcsdb.h
new file mode 100644
index 0000000000..d40d3eb6cb
--- /dev/null
+++ b/libical/src/libicalss/icalcsdb.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalcsdb.h Calendar Server Database
+ CREATOR: eric 23 December 1999
+
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 1999 Eric Busboom
+ http://www.softwarestudio.org
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+======================================================================*/
+
+#ifndef ICALCSDB_H
+#define ICALCSDB_H
+
+#include "ical.h"
+
+typedef void icalcsdb;
+
+icalcsdb* icalcsdb_new(char* path);
+void icalcsdb_free(icalcsdb* csdb);
+
+icalerrorenum icalcsdb_create(icalcsdb* db, char* calid);
+
+icalerrorenum icalcsdb_delete(icalcsdb* db, char* calid);
+
+icalerrorenum icalcsdb_move(icalcsdb* db, char* oldcalid, char* newcalid);
+
+char* icalcsdb_generateuid(icalcsdb* db);
+
+icalcalendar* icalcsdb_get_calendar(icalcsdb* db, char* calid);
+
+icalcluster* icalcsdb_get_vcars(icalcsdb* db);
+
+icalcluster* icalcsdb_get_properties(icalcsdb* db);
+
+icalcluster* icalcsdb_get_capabilities(icalcsdb* db);
+
+icalcluster* icalcsdb_get_timezones(icalcsdb* db);
+
+
+#endif /* !ICALCSDB_H */
+
+
+
diff --git a/libical/src/libicalss/icalcstp.h b/libical/src/libicalss/icalcstp.h
new file mode 100644
index 0000000000..78541f937e
--- /dev/null
+++ b/libical/src/libicalss/icalcstp.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalcstp.h
+ CREATOR: eric 20 April 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 1999 Eric Busboom
+ http://www.softwarestudio.org
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+ The original author is Eric Busboom
+ The original code is icalcstp.h
+
+======================================================================*/
+
+
+#ifndef ICALCSTP_H
+#define ICALCSTP_H
+
+#include "ical.h"
+
+typedef void* icalcstp;
+
+typedef struct icalcstp_stubs;
+
+icalcstp* icalcstp_new(icalcstp_stubs* stubs,
+ int incoming, int outgoing);
+
+void* icalcstp_free(icalcstp* cstp);
+
+/* Send or recieve data directly to/from the network. These calls are
+ needed for the AUTHENTICATE command and possibly others */
+int icalcstp_send(char*);
+char* icalcstp_recieve(char*);
+
+int icalcstp_set_timeout(icalcstp* cstp, int sec);
+
+typedef struct icalcstp_response {
+ icalrequeststatus code
+ char caluid[1024];
+ void* result;
+} icalcstp_response;
+
+
+/********************** Server (Reciever) Interfaces *************************/
+
+/* On the server side, the caller will recieve data from the incoming
+ socket and pass it to icalcstp_process_incoming. The caller then
+ takes the return from _process_incoming and sends it out through
+ the socket. This gives the caller a point of control. If the cstp
+ code connected to the socket itself, it would be hard for the
+ caller to do anything else after the cstp code was started.
+
+ However, some commands will use the sockets directly, though the
+ _send and _recieve routines. Example is Authenticate and Starttls,
+ which need several exchanges of data*/
+
+/* Process a single line of incomming data */
+char* icalcstp_process_incoming(icalcstp* cstp, char* string);
+
+/* Er, they aren't really stubs, but pointers to the rountines that
+ icalcstp_process_incoming will call when it recognizes a CSTP
+ command in the data. BTW, the CONTINUE command is named 'cont'
+ because 'continue' is a C keyword */
+
+struct icalcstp_stubs {
+ icalcstp_response (*abort)(icalcstp* cstp);
+ icalcstp_response (*authenticate)(icalcstp* cstp, char* mechanism,
+ char* data);
+ icalcstp_response (*capability)(icalcstp* cstp);
+ icalcstp_response (*cont)(icalcstp* cstp, unsigned int time);
+ icalcstp_response (*disconnect)(icalcstp* cstp);
+ icalcstp_response (*identify)(icalcstp* cstp, char* id);
+ icalcstp_response (*starttls)(icalcstp* cstp, char* command,
+ char* data);
+ icalcstp_response (*sendata)(icalcstp* cstp, unsigned int time,
+ icalcomponent *comp);
+ icalcstp_response (*unknown)(icalcstp* cstp, char* command, char* data);
+}
+
+/********************** Client (Sender) Interfaces **************************/
+
+/* On the client side, the cstp code is connected directly to the
+ socket, because the callers point of control is at the interfaces
+ below. */
+
+icalcstp_response icalcstp_abort(icalcstp* cstp);
+icalcstp_response icalcstp_authenticate(icalcstp* cstp, char* mechanism,
+ char* data);
+icalcstp_response icalcstp_capability(icalcstp* cstp);
+icalcstp_response icalcstp_continue(icalcstp* cstp, unsigned int time);
+icalcstp_response icalcstp_disconnect(icalcstp* cstp);
+icalcstp_response icalcstp_identify(icalcstp* cstp, char* id);
+icalcstp_response icalcstp_starttls(icalcstp* cstp, char* command,
+ char* data);
+icalcstp_response icalcstp_sendata(icalcstp* cstp, unsigned int time,
+ icalcomponent *comp);
+
+#endif /* !ICALCSTP_H */
+
+
+
diff --git a/libical/src/test/regression.out b/libical/src/test/regression.out
new file mode 100644
index 0000000000..646e184bc4
--- /dev/null
+++ b/libical/src/test/regression.out
@@ -0,0 +1,431 @@
+
+------------Test strings---------------
+foo\;bar\;bats
+foo\;b\nar\;ba\tts
+
+------------Test recur---------------
+FREQ=DAILY;COUNT=5;BYDAY=MO,TU,WE,TH,FR
+FREQ=YEARLY;UNTIL=12345600T123456;BYSETPOS=-1,2
+FREQ=YEARLY;UNTIL=12345600T123456;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=SU;BYMONTH=1
+FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR
+FREQ=WEEKLY;INTERVAL=20;BYDAY=TU
+
+------------Test duration---------------
+PT8H30M
+19971015T050000Z/PT8H30M
+19971015T050000Z/19971015T060000Z
+
+------------Test Restriction---------------
+#### 0 ####
+BEGIN:VCALENDAR
+VERSION
+ :2.0
+PRODID
+ :-//RDU Software//NONSGML HandCal//EN
+METHOD
+ :CANCEL
+BEGIN:VTIMEZONE
+TZID
+ :US_Eastern
+BEGIN:DAYLIGHT
+DTSTART
+ :20000303T065738Z
+RDATE
+ :20000303T065738Z/20000303T075738Z
+TZOFFSETFROM
+ :-000004
+TZOFFSETTO
+ :-000005
+TZNAME
+ :EST
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART
+ :20000303T065738Z
+RDATE
+ :20000303T065738Z/20000303T075738Z
+TZOFFSETFROM
+ :-000005
+TZOFFSETTO
+ :-000004
+TZNAME
+ :EST
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP
+ :20000303T065738Z
+UID
+ :guid-1.host1.com
+ORGANIZER
+ ;ROLE=CHAIR
+ :mrbig@host.com
+ATTENDEE
+ ;ROLE=REQ-PARTICIPANT
+ ;RSVP=TRUE
+ ;CUTYPE=GROUP
+ :employee-A@host.com
+DESCRIPTION
+ :Project XYZ Review Meeting
+CATEGORIES
+ :MEETING
+CLASS
+ :PUBLIC
+CREATED
+ :20000303T065738Z
+SUMMARY
+ :XYZ Project Review
+DTSTART
+ ;TZID=US-Eastern
+ :20000303T065738Z
+DTEND
+ ;TZID=US-Eastern
+ :20000303T065738Z
+LOCATION
+ :1CP Conference Room 4350
+X-LIC-ERROR
+ ;X-LIC-ERRORTYPE=INVALID_ITIP
+ :Failed iTIP restrictions for property SEQUENCE. Expected 1 instances
+ of the property and got 0
+END:VEVENT
+END:VCALENDAR
+
+
+------------Test Compare---------------
+0
+-1
+1
+0
+-1
+1
+BEGIN:VCALENDAR
+BEGIN:VEVENT
+COMMENT
+ ;X-LIC-COMPARETYPE=EQUAL
+ :Comment
+END:VEVENT
+END:VCALENDAR
+1
+
+------------Test Memory---------------
+1: 0x807d938 1) When in the Course of human events,
+2: 0x807dd40 2) it becomes necessary for one people to dissolve the political bands which have connected them with another,
+3: 0x807e148 3) and to assume among the powers of the earth,
+4: 0x807e550 4) the separate and equal station to which the Laws of Nature and of Nature's God entitle them,
+5: 0x807ec88 5) a decent respect to the opinions of mankind requires that they
+6: 0x807f090 6) should declare the causes which impel them to the separation.
+7: 0x807f498 7) We hold these truths to be self-evident,
+8: 0x807f8a0 8) that all men are created equal,
+Final: 1) When in the Course of human events, 2) it becomes necessary for one people to dissolve the political bands which have connected them with another, 3) and to assume among the powers of the earth, 4) the separate and equal station to which the Laws of Nature and of Nature's God entitle them, 5) a decent respect to the opinions of mankind requires that they 6) should declare the causes which impel them to the separation. 7) We hold these truths to be self-evident, 8) that all men are created equal,
+Final buffer size: 806
+Char-by-Char buffer: abcdefghijabcdefghij¹
+
+------------Test Values---------------
+caladdress 1: cap://value/1
+caladdress 2: cap://value/2
+String: cap://value/2
+Clone: cap://value/2
+caladdress 1: 1
+caladdress 2: 2
+String: 2
+Clone: 2
+date 1: 20000303
+date 2: 20000303
+Clone: 20000303
+Invalid type: 0x807d2c8
+
+------------Test Parameters-----------
+Common Name: A Common Name
+As String: CN=A Common Name
+
+------------Test Properties-----------
+Prop parameter: A Common Name 1
+Prop parameter: A Common Name 2
+Prop parameter: A Common Name 3
+Prop parameter: A Common Name 4
+Prop value: Another Comment
+As iCAL string:
+ COMMENT
+ ;CN=A Common Name 1
+ ;CN=A Common Name 2
+ ;CN=A Common Name 3
+ ;CN=A Common Name 4
+ :Another Comment
+
+Clone:
+ COMMENT
+ ;CN=A Common Name 1
+ ;CN=A Common Name 2
+ ;CN=A Common Name 3
+ ;CN=A Common Name 4
+ :Another Comment
+
+Invalid type: 0x807d598
+
+------------Test Components ----------
+Original Component:
+BEGIN:VCALENDAR
+VERSION
+ :2.0
+PRODID
+ :-//RDU Software//NONSGML HandCal//EN
+COMMENT
+ ;CN=A Common Name 1
+ :A Comment
+BEGIN:VEVENT
+VERSION
+ :2.0
+DESCRIPTION
+ :This is an event
+COMMENT
+ ;CN=A Common Name 1
+ ;CN=A Common Name 2
+ ;CN=A Common Name 3
+ ;CN=A Common Name 4
+ :Another Comment
+X-LIC-ERROR
+ ;X-LIC-ERRORTYPE=COMPONENT_PARSE_ERROR
+ :This is only a test
+END:VEVENT
+END:VCALENDAR
+
+
+Child Component:
+BEGIN:VEVENT
+VERSION
+ :2.0
+DESCRIPTION
+ :This is an event
+COMMENT
+ ;CN=A Common Name 1
+ ;CN=A Common Name 2
+ ;CN=A Common Name 3
+ ;CN=A Common Name 4
+ :Another Comment
+X-LIC-ERROR
+ ;X-LIC-ERRORTYPE=COMPONENT_PARSE_ERROR
+ :This is only a test
+END:VEVENT
+
+
+
+------------Create Components --------
+BEGIN:VCALENDAR
+VERSION
+ :2.0
+PRODID
+ :-//RDU Software//NONSGML HandCal//EN
+BEGIN:VTIMEZONE
+TZID
+ :US_Eastern
+BEGIN:DAYLIGHT
+DTSTART
+ :20000303T065738Z
+RDATE
+ :20000303T065738Z/20000303T075738Z
+TZOFFSETFROM
+ :-000004
+TZOFFSETTO
+ :-000005
+TZNAME
+ :EST
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART
+ :20000303T065738Z
+RDATE
+ :20000303T065738Z/20000303T075738Z
+TZOFFSETFROM
+ :-000004
+TZOFFSETTO
+ :-000005
+TZNAME
+ :EST
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP
+ :20000303T065738Z
+UID
+ :guid-1.host1.com
+ORGANIZER
+ ;ROLE=CHAIR
+ :mrbig@host.com
+ATTENDEE
+ ;ROLE=REQ-PARTICIPANT
+ ;RSVP=TRUE
+ ;CUTYPE=GROUP
+ :employee-A@host.com
+DESCRIPTION
+ :Project XYZ Review Meeting
+CATEGORIES
+ :MEETING
+CLASS
+ :PUBLIC
+CREATED
+ :20000303T065738Z
+SUMMARY
+ :XYZ Project Review
+DTSTART
+ ;TZID=US-Eastern
+ :20000303T065738Z
+DTEND
+ ;TZID=US-Eastern
+ :20000303T065738Z
+LOCATION
+ :1CP Conference Room 4350
+END:VEVENT
+END:VCALENDAR
+
+
+------------Test Parser---------------
+BEGIN:VCALENDAR
+PRODID
+ :\"-//RDU Software//NONSGML HandCal//EN\"
+VERSION
+ :2.0
+BEGIN:VTIMEZONE
+TZID
+ :US-Eastern
+BEGIN:STANDARD
+DTSTART
+ :19981025T020000
+RDATE
+ :19981025T020000
+TZOFFSETFROM
+ :-040000
+TZOFFSETTO
+ :-050000
+TZNAME
+ :EST
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART
+ :19990404T020000
+RDATE
+ :19990404T020000
+TZOFFSETFROM
+ :-050000
+TZOFFSETTO
+ :-040000
+TZNAME
+ :EDT
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP
+ :19980309T231000Z
+UID
+ :guid-1.host1.com
+ORGANIZER
+ ;ROLE=CHAIR
+ :MAILTO:mrbig@host.com
+ATTENDEE
+ ;RSVP=TRUE
+ ;ROLE=REQ-PARTICIPANT
+ ;CUTYPE=GROUP
+ :MAILTO:employee-A@host.com
+DESCRIPTION
+ :Project XYZ Review Meeting
+CATEGORIES
+ :MEETING
+CLASS
+ :PUBLIC
+CREATED
+ :19980309T130000Z
+SUMMARY
+ :XYZ Project Review
+DTSTART
+ ;TZID=US-Eastern
+ :19980312T083000
+DTEND
+ ;TZID=US-Eastern
+ :19980312T093000
+LOCATION
+ :1CP Conference Room 4350
+END:VEVENT
+BEGIN:X-LIC-UNKNOWN
+X-LIC-ERROR
+ ;X-LIC-ERRORTYPE=COMPONENT_PARSE_ERROR
+ :Parse error in component name: 'BOOGA'
+DTSTAMP
+ :19980309T231000Z
+X-LIC-FOO
+ :Booga
+X-LIC-ERROR
+ ;X-LIC-ERRORTYPE=PROPERTY_PARSE_ERROR
+ :Parse error in property name: 'DTSTOMP'
+UID
+ :guid-1.host1.com
+END:X-LIC-UNKNOWN
+END:VCALENDAR
+
+
+----- Create Components with vaargs ---
+BEGIN:VCALENDAR
+VERSION
+ :2.0
+PRODID
+ :-//RDU Software//NONSGML HandCal//EN
+BEGIN:VTIMEZONE
+TZID
+ :US_Eastern
+BEGIN:DAYLIGHT
+DTSTART
+ :20000303T065738Z
+RDATE
+ :20000303T065738Z/20000303T075738Z
+TZOFFSETFROM
+ :-000004
+TZOFFSETTO
+ :-000005
+TZNAME
+ :EST
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART
+ :20000303T065738Z
+RDATE
+ :20000303T065738Z/20000303T075738Z
+TZOFFSETFROM
+ :-000005
+TZOFFSETTO
+ :-000004
+TZNAME
+ :EST
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP
+ :20000303T065738Z
+UID
+ :guid-1.host1.com
+ORGANIZER
+ ;ROLE=CHAIR
+ :mrbig@host.com
+ATTENDEE
+ ;ROLE=REQ-PARTICIPANT
+ ;RSVP=TRUE
+ ;CUTYPE=GROUP
+ :employee-A@host.com
+DESCRIPTION
+ :Project XYZ Review Meeting
+CATEGORIES
+ :MEETING
+CLASS
+ :PUBLIC
+CREATED
+ :20000303T065738Z
+SUMMARY
+ :XYZ Project Review
+DTSTART
+ ;TZID=US-Eastern
+ :20000303T065738Z
+DTEND
+ ;TZID=US-Eastern
+ :20000303T065738Z
+LOCATION
+ :1CP Conference Room 4350
+END:VEVENT
+END:VCALENDAR
+
diff --git a/libical/src/test/stow.c b/libical/src/test/stow.c
new file mode 100644
index 0000000000..d7629855c5
--- /dev/null
+++ b/libical/src/test/stow.c
@@ -0,0 +1,533 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: stow.c
+ CREATOR: eric 29 April 2000
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000 Eric Busboom
+ http://www.softwarestudio.org
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+ The Initial Developer of the Original Code is Eric Busboom
+
+ ======================================================================*/
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h> /* for PATH_MAX */
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/utsname.h> /* for uname */
+#include <sys/stat.h> /* for stat */
+#include <unistd.h> /* for stat, getpid */
+
+#include "ical.h"
+#include "icalcalendar.h"
+
+
+char* program_name;
+#define TMPSIZE 2048
+
+enum options {
+ STORE_IN_DIR,
+ STORE_IN_DB,
+ INPUT_IS_EMAIL,
+ INPUT_IS_ICAL,
+ INPUT_FROM_STDIN,
+ INPUT_FROM_FILE
+};
+
+struct options_struct
+{
+ enum options storage;
+ enum options input_type;
+ char* input_file;
+ char* input_text;
+ char* calid;
+ char* caldir;
+};
+
+
+
+char* lowercase(char* str)
+{
+ char* p = 0;
+ char* new = strdup(str);
+
+ if(str ==0){
+ return 0;
+ }
+
+ for(p = new; *p!=0; p++){
+ *p = tolower(*p);
+ }
+
+ return new;
+}
+
+char* get_local_attendee(struct options_struct *opt)
+{
+ char attendee[PATH_MAX];
+ char* user = getenv("USER");
+
+ struct utsname uts;
+
+ uname(&uts);
+
+ /* HACK nodename may not be a fully qualified domain name */
+ snprintf(attendee,PATH_MAX,"%s@%s",user,uts.nodename);
+
+ return lowercase(attendee);
+}
+
+void usage(char *message)
+{
+}
+
+icalcomponent* get_first_real_component(icalcomponent *comp)
+{
+ icalcomponent *c;
+
+ for(c = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT);
+ c != 0;
+ c = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){
+ if (icalcomponent_isa(c) == ICAL_VEVENT_COMPONENT ||
+ icalcomponent_isa(c) == ICAL_VTODO_COMPONENT ||
+ icalcomponent_isa(c) == ICAL_VJOURNAL_COMPONENT )
+ {
+ return c;
+ }
+ }
+
+ return 0;
+}
+
+
+
+char* make_mime(char* to, char* from, char* subject,
+ char* text_message, char* method, char* ical_message)
+{
+ size_t size = strlen(to)+strlen(from)+strlen(subject)+
+ strlen(text_message)+ strlen(ical_message)+TMPSIZE;
+
+ char mime_part_1[TMPSIZE];
+ char mime_part_2[TMPSIZE];
+ char content_id[TMPSIZE];
+ char boundary[TMPSIZE];
+ struct utsname uts;
+ char* m;
+
+
+ if ((m = malloc(sizeof(char)*size)) == 0){
+ fprintf(stderr,"%s: Can't allocate memory: %s\n",program_name,strerror(errno));
+ exit(1);
+ }
+
+ uname(&uts);
+
+ srand(time(0)<<getpid());
+ sprintf(content_id,"%d-%d@%s",time(0),rand(),uts.nodename);
+ sprintf(boundary,"%d-%d-%s",time(0),rand(),uts.nodename);
+
+ sprintf(mime_part_1,"Content-ID: %s\n\
+Content-type: text/plain\n\
+Content-Description: Text description of error message\n\n\
+%s\n\n%s",
+ content_id,text_message,boundary);
+
+ if(ical_message != 0 && method != 0){
+ sprintf(mime_part_2,"\nContent-ID: %s\n\
+Content-type: text/calendar; method=%s\n\
+Content-Description: ICal component reply\n\n\
+%s\n\n%s--\n",
+ content_id,method,ical_message,boundary);
+ }
+
+ sprintf(m,"To: %s\n\
+From: %s\n\
+Subject: %s\n\
+MIME-Version: 1.0\n\
+Content-ID: %s\n\
+Content-Type: multipart/mixed; boundary=\"%s\"\n\
+\n\
+ This is a multimedia message in MIME format\n\
+\n\
+%s
+",
+ to,from,subject,content_id,boundary,boundary,
+ mime_part_1);
+
+ if(ical_message != 0 && method != 0){
+ strcat(m, mime_part_2);
+ } else {
+ strcat(m,"--\n");
+ }
+
+ return m;
+}
+
+/* The incoming component had fatal errors */
+void return_failure(icalcomponent* comp, char* message, struct options_struct *opt)
+{
+
+
+ fputs(make_mime("Dest", "Source", "iMIP error",
+ message, "reply",
+ icalcomponent_as_ical_string(comp)),stdout);
+
+}
+
+/* The program had a fatal error and could not process the incoming component*/
+void return_error(icalcomponent* comp, char* message, struct options_struct *opt)
+{
+
+
+ fputs(make_mime("Dest", "Source", "iMIP system failure",
+ message, 0,0),stdout);
+
+}
+
+char* check_component(icalcomponent* comp, struct options_struct *opt)
+{
+ static char static_component_error_str[PATH_MAX];
+ char* component_error_str=0;
+ icalcomponent* inner;
+ int errors = 0;
+ icalproperty *p;
+ int found_attendee = 0;
+
+ /* This do/while loop only executes once because it is being used
+ to fake exceptions */
+
+ do {
+
+ /* Check that the root component is a VCALENDAR */
+ if(icalcomponent_isa(comp) != ICAL_VCALENDAR_COMPONENT){
+ strcpy(static_component_error_str,
+ "Root component is not a VCALENDAR");
+ component_error_str = static_component_error_str;
+ break;
+ }
+
+ /* Check that the component passes iTIP restrictions */
+
+ errors = icalcomponent_count_errors(comp);
+ icalrestriction_check(comp);
+
+ if(errors != icalcomponent_count_errors(comp)){
+ strcpy(static_component_error_str,
+ "The component does not conform to iTIP restrictions");
+ component_error_str = static_component_error_str;
+ break;
+ }
+
+ /* Check that the component has a METHOD */
+
+ if (!icalcomponent_get_first_property(comp,ICAL_METHOD_PROPERTY) == 0)
+ {
+ strcpy(static_component_error_str,
+ "Component does not have a METHOD property");
+ component_error_str = static_component_error_str;
+ break;
+ }
+
+ /* Check for this user as an attendee */
+
+
+ inner = get_first_real_component(comp);
+
+ for(p = icalcomponent_get_first_property(inner,ICAL_ATTENDEE_PROPERTY);
+ p != 0;
+ p = icalcomponent_get_next_property(inner,ICAL_ATTENDEE_PROPERTY)){
+
+ char* s = icalproperty_get_attendee(p);
+ char* lower_attendee = lowercase(s);
+ char* local_attendee = get_local_attendee(opt);
+
+ /* Check that attendee begins with "mailto:" */
+ if (strncmp(lower_attendee,"mailto:",7) == 0){
+ /* skip over the mailto: part */
+ lower_attendee += 7;
+
+ if(strcmp(lower_attendee,local_attendee) == 0){
+ found_attendee = 1;
+ }
+
+ lower_attendee -= 7;
+
+ free(local_attendee);
+ free(lower_attendee);
+
+ }
+ }
+
+ if (found_attendee == 0){
+ char* local_attendee = get_local_attendee(opt);
+ snprintf(static_component_error_str,PATH_MAX,
+ "This target user (%s) is not listed as an attendee",
+ local_attendee );
+ component_error_str = static_component_error_str;
+ free(local_attendee);
+
+ break;
+ }
+
+ } while(0);
+
+ return component_error_str;
+}
+
+void get_options(int argc, char* argv[], struct options_struct *opt)
+{
+ opt->storage = STORE_IN_DIR;
+ opt->input_type = INPUT_FROM_STDIN;
+ opt->input_file = 0;
+ opt->input_text = 0;
+ opt->calid = 0;
+ opt->caldir = 0;
+}
+
+char* check_options(struct options_struct *opt)
+{
+ return 0;
+}
+
+void store_component(icalcomponent *comp, icalcalendar* cal,
+ struct options_struct *opt)
+{
+
+ icalcluster *incoming = 0;
+ icalerrorenum error;
+
+ incoming = icalcalendar_get_incoming(cal);
+
+ if (incoming == 0){
+ fprintf(stderr,"%s: Failed to get incoming component directory: %s\n",
+ program_name, icalerror_strerror(icalerrno));
+ exit(1);
+ }
+
+ error = icalcluster_add_component(incoming,comp);
+
+ if (error != ICAL_NO_ERROR){
+ fprintf(stderr,"%s: Failed to write incoming component: %s\n",
+ program_name, icalerror_strerror(icalerrno));
+ exit(1);
+ }
+
+ error = icalcluster_commit(incoming);
+
+ if (error != ICAL_NO_ERROR){
+ fprintf(stderr,"%s: Failed to commit incoming cluster: %s\n",
+ program_name, icalerror_strerror(icalerrno));
+ exit(1);
+ }
+
+ return;
+}
+
+enum file_type
+{
+ ERROR,
+ NO_FILE,
+ DIRECTORY,
+ REGULAR,
+ OTHER
+};
+
+enum file_type test_file(char *path)
+{
+ struct stat sbuf;
+ enum file_type type;
+
+ errno = 0;
+
+ /* Check if the path already exists and if it is a directory*/
+ if (stat(path,&sbuf) != 0){
+
+ /* A file by the given name does not exist, or there was
+ another error */
+ if(errno == ENOENT)
+ {
+ type = NO_FILE;
+ } else {
+ type = ERROR;
+ }
+
+ } else {
+ /* A file by the given name exists, but is it a directory? */
+
+ if (S_ISDIR(sbuf.st_mode)){
+ type = DIRECTORY;
+ } else if(S_ISREG(sbuf.st_mode)){
+ type = REGULAR;
+ } else {
+ type = OTHER;
+ }
+ }
+
+ return type;
+}
+
+icalcalendar* get_calendar(icalcomponent* comp, struct options_struct *opt)
+{
+
+ struct stat sbuf;
+ char calpath[PATH_MAX];
+ char facspath[PATH_MAX];
+ char* home = getenv("HOME");
+ char* user = getenv("USER");
+ enum file_type type;
+ icalcalendar* cal;
+
+ snprintf(facspath,PATH_MAX,"%s/.facs",home);
+
+ type = test_file(facspath);
+
+ errno = 0;
+ if (type == NO_FILE){
+
+ if(mkdir(facspath,0775) != 0){
+ fprintf(stderr,"%s: Failed to create calendar store directory %s: %s\n",
+ program_name,facspath, strerror(errno));
+ exit(1);
+ } else {
+ printf("%s: Creating calendar store directory %s\n",program_name,facspath);
+ }
+
+ } else if(type==REGULAR || type == ERROR){
+ fprintf(stderr,"%s: Cannot create calendar store directory %s\n",
+ program_name,facspath);
+ exit(1);
+ }
+
+
+
+ snprintf(calpath,PATH_MAX,"%s/%s",facspath,user);
+
+ type = test_file(calpath);
+
+ errno = 0;
+
+ if (type == NO_FILE){
+
+ if(mkdir(calpath,0775) != 0){
+ fprintf(stderr,"%s: Failed to create calendar directory %s: %s\n",
+ program_name,calpath, strerror(errno));
+ } else {
+ printf("%s: Creating calendar store directory %s\n",program_name,facspath);
+ }
+ } else if(type==REGULAR || type == ERROR){
+ fprintf(stderr,"%s: Cannot create calendar directory %s\n",
+ program_name,calpath);
+ exit(1);
+ }
+
+ cal = icalcalendar_new(calpath);
+
+ if(cal == 0){
+ fprintf(stderr,"%s: Failed to open calendar at %s: %s",
+ program_name,calpath,icalerror_strerror(icalerrno));
+ exit(1);
+ }
+
+ return cal;
+
+}
+
+char* read_stream(char *s, size_t size, void *d)
+{
+ char *c = fgets(s,size, (FILE*)d);
+
+ return c;
+}
+
+icalcomponent* read_component(struct options_struct *opt)
+{
+ FILE *stream;
+ icalcomponent *comp;
+ icalparser* parser = icalparser_new();
+ char* line;
+
+ if(opt->input_type == INPUT_FROM_FILE){
+ stream = fopen(opt->input_file,"r");
+
+ if (stream == 0){
+ perror("Can't open input file");
+ exit(1);
+ }
+
+ } else {
+ stream = stdin;
+ }
+
+ assert(stream != 0);
+ icalparser_set_gen_data(parser,stream);
+
+ do {
+ line = icalparser_get_line(parser,read_stream);
+
+ comp = icalparser_add_line(parser,line);
+
+ if (comp != 0){
+ icalparser_claim(parser);
+ return comp;
+ }
+
+ } while ( line != 0);
+
+ if(opt->input_type == INPUT_FROM_FILE){
+ fclose(stream);
+ }
+
+ return comp;
+ }
+
+int main(int argc, char* argv[] )
+{
+ char* options_error_str;
+ char* component_error_str;
+ icalcalendar* cal;
+ icalcomponent* comp, *reply;
+ struct options_struct opt;
+
+ program_name = argv[0];
+
+ get_options(argc, argv, &opt);
+
+ if ( (options_error_str = check_options(&opt)) != 0 ){
+ usage(options_error_str);
+ exit(1);
+ }
+
+ comp = read_component(&opt);
+
+ if ( (component_error_str = check_component(comp,&opt)) != 0){
+ return_failure(comp, component_error_str, &opt);
+ exit(1);
+ }
+
+ cal = get_calendar(comp,&opt);
+
+ store_component(comp,cal, &opt);
+
+ icalcomponent_free(comp);
+ icalcalendar_free(cal);
+
+ exit(0);
+}
+