/*====================================================================== FILE: regression-storage.c CREATOR: eric 03 April 1999 (C) COPYRIGHT 1999 Eric Busboom DESCRIPTION: This library is free software; you can redistribute it and/or modify it under the terms of either: The LGPL as published by the Free Software Foundation, version 2.1, available at: https://www.gnu.org/licenses/lgpl-2.1.html Or: The Mozilla Public License Version 2.0. You may obtain a copy of the License at https://www.mozilla.org/MPL/ The original author is Eric Busboom The original code is usecases.c ======================================================================*/ #ifdef HAVE_CONFIG_H #include #endif #include "regression.h" #include "libical/ical.h" #include "libicalss/icalss.h" #include #define OUTPUT_FILE "filesetout.ics" /* define sample calendar struct */ struct calendar { int ID; size_t total_size; /* offsets */ size_t total_size_offset; size_t vcalendar_size_offset; size_t vcalendar_offset; size_t title_size_offset; size_t title_offset; /* data */ size_t vcalendar_size; char *vcalendar; size_t title_size; char *title; }; int vcalendar_init(struct calendar **cal, const char *vcalendar, const char *title); #if defined(HAVE_BDB) #include int get_title(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey); char *parse_vcalendar(const DBT *dbt); char *pack_calendar(struct calendar *cal, size_t size); struct calendar *unpack_calendar(char *str, size_t size); #endif //krazy:cond=style /* static char str[] = "BEGIN:VCALENDAR\n\ PRODID:\"-//RDU Software//NONSGML HandCal//EN\"\n\ VERSION:2.0\n\ BEGIN:VTIMEZONE\n\ TZID:US-Eastern\n\ BEGIN:STANDARD\n\ DTSTART:19981025T020000\n\ RDATE:19981025T020000\n\ TZOFFSETFROM:-0400\n\ TZOFFSETTO:-0500\n\ TZNAME:EST\n\ END:STANDARD\n\ BEGIN:DAYLIGHT\n\ DTSTART:19990404T020000\n\ RDATE:19990404T020000\n\ TZOFFSETFROM:-0500\n\ TZOFFSETTO:-0400\n\ TZNAME:EDT\n\ END:DAYLIGHT\n\ END:VTIMEZONE\n\ BEGIN:VEVENT\n\ DTSTAMP:19980309T231000Z\n\ UID:guid-1.host1.com\n\ ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com\n\ ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com\n\ DESCRIPTION:Project XYZ Review Meeting\n\ CATEGORIES:MEETING\n\ CLASS:PUBLIC\n\ CREATED:19980309T130000Z\n\ SUMMARY:XYZ Project Review\n\ DTSTART;TZID=US-Eastern:19980312T083000\n\ DTEND;TZID=US-Eastern:19980312T093000\n\ LOCATION:1CP Conference Room 4350\n\ END:VEVENT\n\ BEGIN:BOOGA\n\ DTSTAMP:19980309T231000Z\n\ X-LIC-FOO:Booga\n\ DTSTOMP:19980309T231000Z\n\ UID:guid-1.host1.com\n\ END:BOOGA\n\ END:VCALENDAR"; */ char str2[] = "BEGIN:VCALENDAR\n\ PRODID:\"-//RDU Software//NONSGML HandCal//EN\"\n\ VERSION:2.0\n\ BEGIN:VEVENT\n\ DTSTAMP:19980309T231000Z\n\ UID:guid-1.host1.com\n\ ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com\n\ ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com\n\ DESCRIPTION:Project XYZ Review Meeting\n\ CATEGORIES:MEETING\n\ CLASS:PUBLIC\n\ CREATED:19980309T130000Z\n\ SUMMARY:XYZ Project Review\n\ DTSTART;TZID=US-Eastern:19980312T083000\n\ DTEND;TZID=US-Eastern:19980312T093000\n\ LOCATION:1CP Conference Room 4350\n\ END:VEVENT\n\ END:VCALENDAR\n\ "; //krazy:endcond=style void test_fileset_extended(void) { icalset *cout; int month = 0; int count = 0; struct icaltimetype start, end; icalcomponent *c, *clone, *itr; icalsetiter iter; start = icaltime_from_timet_with_zone(time(0), 0, NULL); end = start; end.hour++; cout = icalfileset_new(OUTPUT_FILE); ok("Opening output file", (cout != 0)); assert(cout != 0); c = icalparser_parse_string(str2); ok("Parsing str2", (c != 0)); assert(c != 0); icalset_free(cout); /* Add data to the file */ for (month = 1; month < 10; month++) { icalcomponent *event; icalproperty *dtstart, *dtend; cout = icalfileset_new(OUTPUT_FILE); ok("Opening output file", (cout != 0)); assert(cout != 0); start.month = month; end.month = month; clone = icalcomponent_new_clone(c); ok("Making clone of output file", (clone != 0)); assert(clone != 0); event = icalcomponent_get_first_component(clone, ICAL_VEVENT_COMPONENT); ok("Getting first event from clone", (event != 0)); assert(event != 0); dtstart = icalcomponent_get_first_property(event, ICAL_DTSTART_PROPERTY); ok("find DTSTART", (dtstart != 0)); assert(dtstart != 0); icalproperty_set_dtstart(dtstart, start); dtend = icalcomponent_get_first_property(event, ICAL_DTEND_PROPERTY); ok("find DTEND", (dtend != 0)); assert(dtend != 0); icalproperty_set_dtend(dtend, end); (void)icalfileset_add_component(cout, clone); (void)icalfileset_commit(cout); icalcomponent_free(clone); icalset_free(cout); } /* Print them out */ cout = icalfileset_new(OUTPUT_FILE); ok("Opening output file", (cout != 0)); assert(cout != 0); for (iter = icalfileset_begin_component(cout, ICAL_ANY_COMPONENT, 0, NULL); icalsetiter_deref(&iter) != 0; icalsetiter_next(&iter)) { icalcomponent *event; icalproperty *dtstart, *dtend; itr = icalsetiter_deref(&iter); count++; event = icalcomponent_get_first_component(itr, ICAL_VEVENT_COMPONENT); dtstart = icalcomponent_get_first_property(event, ICAL_DTSTART_PROPERTY); dtend = icalcomponent_get_first_property(event, ICAL_DTEND_PROPERTY); if (VERBOSE) { printf("%d %s %s\n", count, icalproperty_as_ical_string(dtstart), icalproperty_as_ical_string(dtend)); } } /* Remove all of them */ icalset_free(cout); cout = icalfileset_new(OUTPUT_FILE); ok("Opening output file", (cout != 0)); assert(cout != 0); /* need to advance the iterator first before calling remove_componenet() */ /* otherwise, iter will contain a "removed" component and icalsetiter_next(&iter) */ /* will fail. */ iter = icalfileset_begin_component(cout, ICAL_ANY_COMPONENT, 0, NULL); itr = icalsetiter_deref(&iter); while (itr != 0) { (void)icalsetiter_next(&iter); (void)icalfileset_remove_component(cout, itr); icalcomponent_free(itr); itr = icalsetiter_deref(&iter); } icalset_free(cout); /* Print them out again */ cout = icalfileset_new(OUTPUT_FILE); ok("Opening output file", (cout != 0)); assert(cout != 0); count = 0; for (itr = icalfileset_get_first_component(cout); itr != 0; itr = icalfileset_get_next_component(cout)) { icalcomponent *event; icalproperty *dtstart, *dtend; count++; event = icalcomponent_get_first_component(itr, ICAL_VEVENT_COMPONENT); dtstart = icalcomponent_get_first_property(event, ICAL_DTSTART_PROPERTY); dtend = icalcomponent_get_first_property(event, ICAL_DTEND_PROPERTY); printf("%d %s %s\n", count, icalproperty_as_ical_string(dtstart), icalproperty_as_ical_string(dtend)); } icalset_free(cout); icalcomponent_free(c); } #if defined(HAVE_BDB) /* In this example, we're storing a calendar with several components under the reference id "calendar_7286" and retrieving records based on title, "month_1" through "month_10". We use a number of the "optional" arguments to specify secondary indices, sub-databases (i.e. having multiple databases residing within a single Berkeley DB file), and keys for storage and retrieval. */ void test_bdbset() { icalset *cout; int month = 0; int count = 0; /* int num_components=0;*/ /* int szdata_len=0;*/ /* int ret=0;*/ /* char *subdb, *szdata, *szpacked_data;*/ /* char uid[255];*/ struct icaltimetype start, end; icalcomponent *c, *clone, *itr; DBT key, data; /* DBC *dbcp;*/ /* struct calendar *cal;*/ /* int cal_size;*/ return; // for now... TODO fix these broken tests.. start = icaltime_from_timet_with_zone(time(0), 0, NULL); end = start; end.hour++; /* Note: as per the Berkeley DB ref pages: * * The database argument is optional, and allows applications to * have multiple databases in a single file. Although no database * argument needs to be specified, it is an error to attempt to * open a second database in a file that was not initially created * using a database name. * */ /*subdb = "calendar_id"; */ /* open database, using subdb */ cout = icalbdbset_new("calendar.db", ICALBDB_EVENTS, DB_HASH, 0); /* sdbp = icalbdbset_secondary_open(dbp, DATABASE, "title", get_title, DB_HASH); */ c = icalparser_parse_string(str2); assert(c != 0); /* Add data to the file */ for (month = 1; month < 10; month++) { icalcomponent *event; icalproperty *dtstart, *dtend; /* retrieve data */ // cout = icalbdbset_new(dbp, sdbp, NULL); // assert(cout != 0); start.month = month; end.month = month; clone = icalcomponent_new_clone(c); assert(clone != 0); event = icalcomponent_get_first_component(clone, ICAL_VEVENT_COMPONENT); assert(event != 0); dtstart = icalcomponent_get_first_property(event, ICAL_DTSTART_PROPERTY); assert(dtstart != 0); icalproperty_set_dtstart(dtstart, start); dtend = icalcomponent_get_first_property(event, ICAL_DTEND_PROPERTY); assert(dtend != 0); icalproperty_set_dtend(dtend, end); assert(icalcomponent_get_first_property(event, ICAL_LOCATION_PROPERTY) != 0); #if 0 /* change the uid to include the month */ sprintf(uid, "%s_%d", icalcomponent_get_uid(clone), month); icalcomponent_set_uid(clone, uid); #endif (void)icalbdbset_add_component(cout, clone); /* commit changes */ (void)icalbdbset_commit(cout); (void)icalcomponent_count_components(clone, ICAL_ANY_COMPONENT); icalset_free(cout); } /* try out the cursor operations */ memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); #if 0 ret = icalbdbset_acquire_cursor(dbp, &dbcp); ret = icalbdbset_get_first(dbcp, &key, &data); ret = icalbdbset_get_next(dbcp, &key, &data); ret = icalbdbset_get_last(dbcp, &key, &data); #endif /* Print them out */ for (month = 1, count = 0; month < 10; month++) { for (itr = icalbdbset_get_first_component(cout); itr != 0; itr = icalbdbset_get_next_component(cout)) { icalcomponent *event; icalproperty *dtstart, *dtend; count++; event = icalcomponent_get_first_component(itr, ICAL_VEVENT_COMPONENT); dtstart = icalcomponent_get_first_property(event, ICAL_DTSTART_PROPERTY); dtend = icalcomponent_get_first_property(event, ICAL_DTEND_PROPERTY); printf("%d %s %s\n", count, icalproperty_as_ical_string(dtstart), icalproperty_as_ical_string(dtend)); } icalset_free(cout); } /* open database */ // cout = icalbdbset_bdb_open("calendar.db", "title", DB_HASH, 0644); /* sdbp = icalbdbset_secondary_open(dbp, DATABASE, "title", get_title, DB_HASH); */ /* Remove all of them */ for (month = 1; month < 10; month++) { for (itr = icalbdbset_get_first_component(cout); itr != 0; itr = icalbdbset_get_next_component(cout)) { (void)icalbdbset_remove_component(cout, itr); } (void)icalbdbset_commit(cout); icalset_free(cout); } /* Print them out again */ for (month = 1, count = 0; month < 10; month++) { for (itr = icalbdbset_get_first_component(cout); itr != 0; itr = icalbdbset_get_next_component(cout)) { icalcomponent *event; icalproperty *dtstart, *dtend; count++; event = icalcomponent_get_first_component(itr, ICAL_VEVENT_COMPONENT); dtstart = icalcomponent_get_first_property(event, ICAL_DTSTART_PROPERTY); dtend = icalcomponent_get_first_property(event, ICAL_DTEND_PROPERTY); printf("%d %s %s\n", count, icalproperty_as_ical_string(dtstart), icalproperty_as_ical_string(dtend)); } icalset_free(cout); } } #endif int vcalendar_init(struct calendar **rcal, const char *vcalendar, const char *title) { size_t vcalendar_size, title_size, total_size; struct calendar *cal; if (vcalendar) { vcalendar_size = strlen(vcalendar); } else { vcalendar = ""; vcalendar_size = strlen(vcalendar); } if (title) { title_size = strlen(title); } else { title = ""; title_size = strlen(title); } total_size = sizeof(struct calendar) + vcalendar_size + title_size; if ((cal = (struct calendar *)malloc(total_size)) == NULL) { return 0; } memset(cal, 0, total_size); /* offsets */ cal->total_size_offset = sizeof(int); cal->vcalendar_size_offset = (sizeof(int) * 7); cal->vcalendar_offset = cal->vcalendar_size_offset + sizeof(int); cal->title_size_offset = cal->vcalendar_offset + vcalendar_size; cal->title_offset = cal->title_size_offset + sizeof(int); /* sizes */ cal->total_size = total_size; cal->vcalendar_size = vcalendar_size; cal->title_size = title_size; if (*vcalendar) /* we know that vcalendar is not NULL here */ cal->vcalendar = strdup(vcalendar); if (*title) /* we know that title is not NULL here */ cal->title = strdup(title); *rcal = cal; return 0; } /* get_title -- extracts a secondary key (the vcalendar) * from a primary key/data pair */ /* just create a random title for now */ #if defined(HAVE_BDB) int get_title(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey) { icalcomponent *cl; static char title[255]; _unused(dbp); _unused(pkey); memset(skey, 0, sizeof(DBT)); cl = icalparser_parse_string((char *)pdata->data); snprintf(title, sizeof(title), "title_%s", icalcomponent_get_uid(cl)); skey->data = strdup(title); skey->size = (u_int32_t) strlen(skey->data); return (0); } char *pack_calendar(struct calendar *cal, size_t size) { char *str; if ((str = (char *)malloc(sizeof(char) * size)) == NULL) return 0; /* ID */ memcpy(str, &cal->ID, sizeof(cal->ID)); /* total_size */ memcpy(str + cal->total_size_offset, &cal->total_size, sizeof(cal->total_size)); /* vcalendar_size */ memcpy(str + cal->vcalendar_size_offset, &cal->vcalendar_size, sizeof(cal->vcalendar_size)); /* vcalendar */ memcpy(str + cal->vcalendar_offset, cal->vcalendar, cal->vcalendar_size); /* title_size */ memcpy(str + cal->title_size_offset, &cal->title_size, sizeof(cal->title_size)); /* title */ memcpy(str + cal->title_offset, cal->title, cal->title_size); return str; } struct calendar *unpack_calendar(char *str, size_t size) { struct calendar *cal; if ((cal = (struct calendar *)malloc(size)) == NULL) { return 0; } memset(cal, 0, size); /* offsets */ cal->total_size_offset = sizeof(int); cal->vcalendar_size_offset = (sizeof(int) * 7); cal->vcalendar_offset = cal->vcalendar_size_offset + sizeof(int); /* ID */ memcpy(&cal->ID, str, sizeof(cal->ID)); /* total_size */ memcpy(&cal->total_size, str + cal->total_size_offset, sizeof(cal->total_size)); /* vcalendar_size */ memcpy(&cal->vcalendar_size, str + cal->vcalendar_size_offset, sizeof(cal->vcalendar_size)); if ((cal->vcalendar = (char *)malloc(sizeof(char) * cal->vcalendar_size)) == NULL) { free(cal); return 0; } /* vcalendar */ memcpy(cal->vcalendar, (char *)(str + cal->vcalendar_offset), cal->vcalendar_size); cal->title_size_offset = cal->vcalendar_offset + cal->vcalendar_size; cal->title_offset = cal->title_size_offset + sizeof(int); /* title_size */ memcpy(&cal->title_size, str + cal->title_size_offset, sizeof(cal->title_size)); if ((cal->title = (char *)malloc(sizeof(char) * cal->title_size)) == NULL) { free(cal->vcalendar); free(cal); return 0; } /* title */ memcpy(cal->title, (char *)(str + cal->title_offset), cal->title_size); return cal; } char *parse_vcalendar(const DBT *dbt) { char *str; struct calendar *cal; str = (char *)dbt->data; cal = unpack_calendar(str, dbt->size); str = cal->vcalendar; free(cal); return str; } #endif void test_dirset_extended(void) { icalcomponent *c; icalgauge *gauge; icalerrorenum error; icalcomponent *itr; icalset *cluster; struct icalperiodtype rtime; icalset *s = icaldirset_new("store"); icalset *s2 = icaldirset_new("store-new"); int i, count = 0; ok("Open dirset 'store'", (s != 0)); assert(s != 0); rtime.start = icaltime_from_timet_with_zone(time(0), 0, NULL); cluster = icalfileset_new(OUTPUT_FILE); ok("Open fileset to duplicate 4 times", (cluster != 0)); assert(cluster != 0); #define NUMCOMP 4 /* Duplicate every component in the cluster NUMCOMP times */ icalerror_clear_errno(); for (i = 1; i < NUMCOMP + 1; i++) { /*rtime.start.month = i%12; */ rtime.start.month = i; rtime.end = rtime.start; rtime.end.hour++; for (itr = icalfileset_get_first_component(cluster); itr != 0; itr = icalfileset_get_next_component(cluster)) { icalcomponent *inner; icalproperty *p; inner = icalcomponent_get_first_component(itr, ICAL_VEVENT_COMPONENT); if (inner == 0) { continue; } /* Change the dtstart and dtend times in the component pointed to by Itr */ (void)icalcomponent_new_clone(itr); inner = icalcomponent_get_first_component(itr, ICAL_VEVENT_COMPONENT); ok("Duplicating component...", (icalerrno == ICAL_NO_ERROR) && (inner != 0)); assert(icalerrno == ICAL_NO_ERROR); assert(inner != 0); /* DTSTART */ p = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY); ok("Fetching DTSTART", (icalerrno == ICAL_NO_ERROR)); assert(icalerrno == ICAL_NO_ERROR); if (p == 0) { p = icalproperty_new_dtstart(rtime.start); icalcomponent_add_property(inner, p); } else { icalproperty_set_dtstart(p, rtime.start); } ok("Adding DTSTART property", (icalerrno == ICAL_NO_ERROR)); assert(icalerrno == ICAL_NO_ERROR); /* DTEND */ p = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY); ok("Fetching DTEND property", (icalerrno == ICAL_NO_ERROR)); assert(icalerrno == ICAL_NO_ERROR); if (p == 0) { p = icalproperty_new_dtstart(rtime.end); icalcomponent_add_property(inner, p); } else { icalproperty_set_dtstart(p, rtime.end); } ok("Setting DTEND property", (icalerrno == ICAL_NO_ERROR)); assert(icalerrno == ICAL_NO_ERROR); if (VERBOSE) printf("\n----------\n%s\n---------\n", icalcomponent_as_ical_string(inner)); error = icaldirset_add_component(s, icalcomponent_new_clone(itr)); ok("Adding component to dirset", (icalerrno == ICAL_NO_ERROR)); assert(error == ICAL_NO_ERROR); _unused(error); } } gauge = icalgauge_new_from_sql( "SELECT * FROM VEVENT WHERE " "VEVENT.SUMMARY = 'Submit Income Taxes' OR " "VEVENT.SUMMARY = 'Bastille Day Party'", 0); ok("Creating complex Gauge", (gauge != 0)); (void)icaldirset_select(s, gauge); for (c = icaldirset_get_first_component(s); c != 0; c = icaldirset_get_next_component(s)) { printf("Got one! (%d)\n", count++); printf("%s", icalcomponent_as_ical_string(c)); if (icaldirset_add_component(s2, c) == 0) { printf("Failed to write!\n"); } icalcomponent_free(c); } icalset_free(s2); for (c = icaldirset_get_first_component(s); c != 0; c = icaldirset_get_next_component(s)) { printf("%s", icalcomponent_as_ical_string(c)); } /* Remove all of the components */ i = 0; while ((c = icaldirset_get_current_component(s)) != 0) { i++; (void)icaldirset_remove_component(s, c); } icalset_free(s); icalset_free(cluster); }