aboutsummaryrefslogtreecommitdiffstats
path: root/libical/src/test/stow.c
diff options
context:
space:
mode:
Diffstat (limited to 'libical/src/test/stow.c')
-rw-r--r--libical/src/test/stow.c533
1 files changed, 533 insertions, 0 deletions
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);
+}
+