icalerrorstate icalerror_supress(const char *error) { icalerrorenum e = icalerror_error_from_string(error); icalerrorstate es; if(e == ICAL_NO_ERROR) { return ICAL_ERROR_UNKNOWN; } es = icalerror_get_error_state(e); icalerror_set_error_state(e, ICAL_ERROR_NONFATAL); return es; }
VALUE duration_to_fixnum( VALUE self, VALUE duration ) { struct icaldurationtype dur_struct; char * _duration; ID to_string = rb_intern( "to_string" ); if( TYPE( duration ) != T_STRING && rb_respond_to( duration, to_string ) ) duration = rb_funcall( duration, to_string, 0 ); Check_Type(duration, T_STRING); _duration = RSTRING(duration)->ptr; icalerror_clear_errno(); icalerror_set_error_state( ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL); dur_struct = icaldurationtype_from_string( _duration ); if( icaldurationtype_is_bad_duration( dur_struct ) ) rb_raise(rb_eArgError, "Malformed Duration"); return LONG2FIX(icaldurationtype_as_int( dur_struct )); }
void test_recur_file() { icalset *cin = 0; struct icaltimetype next; icalcomponent *itr; icalproperty *desc, *dtstart, *rrule; struct icalrecurrencetype recur; icalrecur_iterator* ritr; time_t tt; char* file; int num_recurs_found = 0; icalfileset_options options = {O_RDONLY, 0644, 0}; icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); #ifndef WIN32 signal(SIGALRM,sig_alrm); #endif file = getenv("ICAL_RECUR_FILE"); if (!file) file = TEST_DATADIR "/recur.txt"; #ifndef WIN32 alarm(15); /* to get file lock */ #endif cin = icalset_new(ICAL_FILE_SET, file, &options); #ifndef WIN32 alarm(0); #endif ok("opening file with recurring events", (cin!=NULL)); assert(cin!=NULL); for (itr = icalfileset_get_first_component(cin); itr != 0; itr = icalfileset_get_next_component(cin)){ int badcomp = 0; int expected_events = 0; char msg[128]; struct icaltimetype start = icaltime_null_time(); struct icaltimetype startmin = icaltime_from_timet(1,0); struct icaltimetype endmax = icaltime_null_time(); const char *desc_str = "malformed component"; desc = icalcomponent_get_first_property(itr,ICAL_DESCRIPTION_PROPERTY); dtstart = icalcomponent_get_first_property(itr,ICAL_DTSTART_PROPERTY); rrule = icalcomponent_get_first_property(itr,ICAL_RRULE_PROPERTY); if (desc) { desc_str = icalproperty_get_description(desc); } ok((char*)desc_str, !(desc == 0 || dtstart == 0 || rrule == 0)); if (desc == 0 || dtstart == 0 || rrule == 0) { badcomp = 1; if (VERBOSE) { printf("\n******** Error in input component ********\n"); printf("The following component is malformed:\n %s\n", desc_str); } continue; } if (VERBOSE) { printf("\n\n#### %s\n",desc_str); printf("#### %s\n",icalvalue_as_ical_string(icalproperty_get_value(rrule))); } recur = icalproperty_get_rrule(rrule); start = icalproperty_get_dtstart(dtstart); ritr = icalrecur_iterator_new(recur,start); tt = icaltime_as_timet(start); if (VERBOSE) printf("#### %s\n",ctime(&tt )); icalrecur_iterator_free(ritr); for(ritr = icalrecur_iterator_new(recur,start), next = icalrecur_iterator_next(ritr); !icaltime_is_null_time(next); next = icalrecur_iterator_next(ritr)){ tt = icaltime_as_timet(next); if (VERBOSE) printf(" %s",ctime(&tt )); } icalrecur_iterator_free(ritr); num_recurs_found = 0; expected_events = get_expected_numevents(itr); icalcomponent_foreach_recurrence(itr, startmin, endmax, recur_callback, &num_recurs_found); sprintf(msg," expecting total of %d events", expected_events); int_is(msg, num_recurs_found, expected_events); } icalset_free(cin); }
int main(int c, char *argv[]){ icalset *clusterin, *clusterout = NULL; icalcomponent *itr; int count=0; int tostdout = 0; if(c < 2 || c > 3){ usage(argv[0]); exit(1); } if (c == 2){ tostdout = 1; } /*icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL);*/ #ifdef SIGALRM signal(SIGALRM,sig_alrm); alarm(10); #endif clusterin = icalfileset_new(argv[1]); #ifdef SIGALRM alarm(0); #endif if (clusterin == 0){ printf("Could not open input cluster \"%s\"\n",argv[1]); if(icalerrno!= ICAL_NO_ERROR){ printf("Error: %s\n",icalerror_strerror(icalerrno)); } exit(1); } if (!tostdout){ #ifdef SIGALRM alarm(10); #endif clusterout = icalfileset_new(argv[2]); #ifdef SIGALRM alarm(0); #endif if (clusterout == 0){ printf("Could not open output cluster \"%s\"\n",argv[2]); exit(1); } } for (itr = icalset_get_first_component(clusterin); itr != 0; itr = icalset_get_next_component(clusterin)){ icalerror_set_error_state(ICAL_BADARG_ERROR, ICAL_ERROR_NONFATAL); icalrestriction_check(itr); icalerror_set_error_state(ICAL_BADARG_ERROR, ICAL_ERROR_DEFAULT); if (itr != 0){ if(tostdout){ printf("--------------\n%s\n",icalcomponent_as_ical_string(itr)); } else { icalfileset_add_component(clusterout, icalcomponent_new_clone(itr)); } count++; } else { printf("Got NULL component"); } } printf("Transfered %d components\n",count); icalset_free(clusterin); if (!tostdout){ icalfileset_mark(clusterout); icalset_free(clusterout); } return 0; }
icalcomponent* icalparser_parse(icalparser *parser, char* (*line_gen_func)(char *s, size_t size, void* d)) { char* line; icalcomponent *c=0; icalcomponent *root=0; icalerrorstate es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR); int cont; icalerror_check_arg_rz((parser !=0),"parser"); icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL); do{ line = icalparser_get_line(parser, line_gen_func); if ((c = icalparser_add_line(parser,line)) != 0){ if(icalcomponent_get_parent(c) !=0){ /* This is bad news... assert? */ } assert(parser->root_component == 0); assert(pvl_count(parser->components) ==0); if (root == 0){ /* Just one component */ root = c; } else if(icalcomponent_isa(root) != ICAL_XROOT_COMPONENT) { /*Got a second component, so move the two components under an XROOT container */ icalcomponent *tempc = icalcomponent_new(ICAL_XROOT_COMPONENT); icalcomponent_add_component(tempc, root); icalcomponent_add_component(tempc, c); root = tempc; } else if(icalcomponent_isa(root) == ICAL_XROOT_COMPONENT) { /* Already have an XROOT container, so add the component to it*/ icalcomponent_add_component(root, c); } else { /* Badness */ assert(0); } c = 0; } cont = 0; if(line != 0){ icalmemory_free_buffer(line); cont = 1; } } while ( cont ); icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es); return root; }
int main(int argc, char *argv[]) { icalset *cin; struct icaltimetype next; icalcomponent *itr; icalproperty *desc, *dtstart, *rrule; struct icalrecurrencetype recur; icalrecur_iterator* ritr; time_t tt; char* file; icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); #ifndef WIN32 signal(SIGALRM,sig_alrm); #endif if (argc <= 1) { file = "../../test-data/recur.txt"; } else if (argc == 2) { file = argv[1]; } else { fprintf(stderr,"usage: recur [input file]\n"); exit(1); } #ifndef WIN32 alarm(300); /* to get file lock */ #endif cin = icalfileset_new(file); #ifndef WIN32 alarm(0); #endif if(cin == 0) { fprintf(stderr,"recur: can't open file %s\n",file); exit(1); } for (itr = icalfileset_get_first_component(cin); itr != 0; itr = icalfileset_get_next_component(cin)) { struct icaltimetype start = icaltime_from_timet(1,0); struct icaltimetype end = icaltime_today(); desc = icalcomponent_get_first_property(itr,ICAL_DESCRIPTION_PROPERTY); dtstart = icalcomponent_get_first_property(itr,ICAL_DTSTART_PROPERTY); rrule = icalcomponent_get_first_property(itr,ICAL_RRULE_PROPERTY); if (desc == 0 || dtstart == 0 || rrule == 0) { printf("\n******** Error in input component ********\n"); printf("The following component is malformed:\n %s\n", icalcomponent_as_ical_string(itr)); continue; } printf("\n\n#### %s\n",icalproperty_get_description(desc)); printf("#### %s\n",icalvalue_as_ical_string(icalproperty_get_value(rrule))); recur = icalproperty_get_rrule(rrule); start = icalproperty_get_dtstart(dtstart); ritr = icalrecur_iterator_new(recur,start); tt = icaltime_as_timet(start); printf("#### %s\n",ctime(&tt )); icalrecur_iterator_free(ritr); for(ritr = icalrecur_iterator_new(recur,start), next = icalrecur_iterator_next(ritr); !icaltime_is_null_time(next); next = icalrecur_iterator_next(ritr)) { tt = icaltime_as_timet(next); printf(" %s",ctime(&tt )); } icalrecur_iterator_free(ritr); icalcomponent_foreach_recurrence(itr, start, end, recur_callback, NULL); } icalset_free(cin); icaltimezone_free_builtin_timezones(); icalmemory_free_ring(); free_zone_directory(); return 0; }
/** * @brief * Check if a recurrence rule is valid and consistent. * The recurrence rule is verified against a start date and checks * that the frequency of the recurrence matches the duration of the * submitted reservation. If the duration of a reservation exceeds the * granularity of the frequency then an error message is displayed. * * @par The recurrence rule is checked to contain a COUNT or an UNTIL. * * @par Note that the PBS_TZID environment variable HAS to be set for the occurrence's * dates to be correctly computed. * * @param[in] rrule - The recurrence rule to unroll * @param[in] dtstart - The start time associated to the reservation (1st occurrence) * @param[in] dtend - The end time associated to the reservation (1st occurrence) * @param[in] duration - The duration of an occurrence. This is used when a reservation is * submitted using the -D (duration) param instead of an end time * @param[in] tz - The timezone associated to the recurrence rule * @param[in] err_code - A pointer to the error code to return. Codes are defined in pbs_error.h * * @return int * @retval The total number of occurrences that the recurrence rule and start date * * define. 1 for an advance reservation. * */ int check_rrule(char *rrule, time_t dtstart, time_t dtend, char *tz, int *err_code) { #ifdef LIBICAL /* Standing Reservation Recurrence */ int count = 1; struct icalrecurrencetype rt; struct icaltimetype start; struct icaltimetype next; struct icaltimetype first; struct icaltimetype prev; struct icalrecur_iterator_impl *itr; icaltimezone *localzone; int time_err = 0; int i; long min_occr_duration = -1; long tmp_occr_duration = 0; long duration; *err_code = 0; icalerror_clear_errno(); icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); icalerror_errors_are_fatal = 0; if (tz == NULL || rrule == NULL) return 0; localzone = icaltimezone_get_builtin_timezone(tz); /* If the timezone info directory is not accessible * then bail */ if (localzone == NULL) { *err_code = PBSE_BAD_ICAL_TZ; return 0; } rt = icalrecurrencetype_from_string(rrule); /* Check if by_day rules are defined and valid * the first item in the array of by_* rule * determines whether the item exists or not. */ for (i = 0; rt.by_day[i] < 8; i++) { if (rt.by_day[i] <= 0) { *err_code = PBSE_BAD_RRULE_SYNTAX; return 0; } } /* Check if by_hour rules are defined and valid * the first item in the array of by_* rule * determines whether the item exists or not. */ for (i = 0; rt.by_hour[i] < 25; i++) { if (rt.by_hour[i] < 0) { *err_code = PBSE_BAD_RRULE_SYNTAX; return 0; } } /* Check if the rest of the by_* rules are defined * and valid. * currently no support for * BYMONTHDAY, BYYEARDAY, BYSECOND, * BYMINUTE, BYWEEKNO, or BYSETPOS * */ if (rt.by_second[0] < 61 || /* by_second is negative such as in -10 */ rt.by_minute[0] < 61 || /* by_minute is negative such as in -10 */ rt.by_year_day[0] < 367 || /* a year day is defined */ rt.by_month_day[0] < 31 || /* a month day is defined */ rt.by_week_no[0] < 52 || /* a week number is defined */ rt.by_set_pos[0] < 367) { /* a set pos is defined */ *err_code = PBSE_BAD_RRULE_SYNTAX; return 0; } /* Require that either a COUNT or UNTIL be passed. But not both. */ if ((rt.count == 0 && icaltime_is_null_time(rt.until)) || (rt.count != 0 && !icaltime_is_null_time(rt.until))) { *err_code = PBSE_BAD_RRULE_SYNTAX2; /* Undefined iCalendar synax. A valid COUNT or UNTIL is required */ return 0; } start = icaltime_from_timet(dtstart, 0); icaltimezone_convert_time(&start, icaltimezone_get_utc_timezone(), localzone); itr = (struct icalrecur_iterator_impl*) icalrecur_iterator_new(rt, start); duration = dtend -dtstart; /* First check if the syntax of the iCalendar rule is valid */ next = icalrecur_iterator_next(itr); /* Catch case where first occurrence date is in the past */ if (icaltime_is_null_time(next)) { *err_code = PBSE_BADTSPEC; icalrecur_iterator_free(itr); return 0; } first = next; prev = first; for (next=icalrecur_iterator_next(itr); !icaltime_is_null_time(next); next=icalrecur_iterator_next(itr), count++) { /* The interval duration between two occurrences * is the time between the end of an occurrence and the * start of the next one */ tmp_occr_duration = icaltime_as_timet(next) - icaltime_as_timet(prev); /* Set the minimum time interval between occurrences */ if (min_occr_duration == -1) min_occr_duration = tmp_occr_duration; else if (tmp_occr_duration > 0 && tmp_occr_duration < min_occr_duration) min_occr_duration = tmp_occr_duration; prev = next; } /* clean up */ icalrecur_iterator_free(itr); if (icalerrno != ICAL_NO_ERROR) { *err_code = PBSE_BAD_RRULE_SYNTAX; /* Undefined iCalendar syntax */ return 0; } /* Then check if the duration fits in the frequency rule */ switch (rt.freq) { case ICAL_SECONDLY_RECURRENCE: { if (duration > 1) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_SECONDLY; /* SECONDLY recurrence duration cannot exceed 1 second */ time_err++; } break; } case ICAL_MINUTELY_RECURRENCE: { if (duration > 60) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_MINUTELY; /* MINUTELY recurrence duration cannot exceed 1 minute */ time_err++; } break; } case ICAL_HOURLY_RECURRENCE: { if (duration > (60*60)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno =1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_HOURLY; /* HOURLY recurrence duration cannot exceed 1 hour */ time_err++; } break; } case ICAL_DAILY_RECURRENCE: { if (duration > (60*60*24)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_DAILY; /* DAILY recurrence duration cannot exceed 24 hours */ time_err++; } break; } case ICAL_WEEKLY_RECURRENCE: { if (duration > (60*60*24*7)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_WEEKLY; /* WEEKLY recurrence duration cannot exceed 1 week */ time_err++; } break; } case ICAL_MONTHLY_RECURRENCE: { if (duration > (60*60*24*30)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_MONTHLY; /* MONTHLY recurrence duration cannot exceed 1 month */ time_err++; } break; } case ICAL_YEARLY_RECURRENCE: { if (duration > (60*60*24*30*365)) { #ifdef NAS /* localmod 005 */ icalerrno = ICAL_BADARG_ERROR; #else icalerrno = 1; #endif /* localmod 005 */ *err_code = PBSE_BAD_RRULE_YEARLY; /* YEARLY recurrence duration cannot exceed 1 year */ time_err++; } break; } default: { icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); return 0; } } if (time_err) return 0; /* If the requested reservation duration exceeds * the occurrence's duration then print an error * message and return */ if (count != 1 && duration > min_occr_duration) { *err_code = PBSE_BADTSPEC; /* Bad Time Specification(s) */ return 0; } return count; #else *err_code = PBSE_BAD_RRULE_SYNTAX; /* iCalendar is undefined */ return 0; #endif }
/** * @brief * Returns the number of occurrences defined by a recurrence rule. * * @par The total number of occurrences is currently limited to a hardcoded * 3 years limit from the current date. * * @par NOTE: Determine whether 3 years limit is the right way to go about setting * a limit on the total number of occurrences. * * @param[in] rrule - The recurrence rule as defined by the user * @param[in] tt - The start time of the first occurrence * @param[in] tz - The timezone associated to the recurrence rule * * @return int * @retval the total number of occurrences * */ int get_num_occurrences(char *rrule, time_t dtstart, char *tz) { #ifdef LIBICAL struct icalrecurrencetype rt; struct icaltimetype start; icaltimezone *localzone; struct icaltimetype next; struct icalrecur_iterator_impl *itr; time_t now; time_t date_limit; int num_resv = 0; /* if any of the argument is NULL, we are dealing with * advance reservation, so return 1 occurrence */ if (rrule == NULL || tz == NULL) return 1; icalerror_clear_errno(); icalerror_set_error_state(ICAL_PARSE_ERROR, ICAL_ERROR_NONFATAL); #ifdef LIBICAL_API2 icalerror_set_errors_are_fatal(0); #else icalerror_errors_are_fatal = 0; #endif localzone = icaltimezone_get_builtin_timezone(tz); if (localzone == NULL) return 0; now = time(NULL); date_limit = now + DATE_LIMIT; rt = icalrecurrencetype_from_string(rrule); start = icaltime_from_timet_with_zone(dtstart, 0, NULL); icaltimezone_convert_time(&start, icaltimezone_get_utc_timezone(), localzone); itr = (struct icalrecur_iterator_impl*) icalrecur_iterator_new(rt, start); next = icalrecur_iterator_next(itr); /* Compute the total number of occurrences. * Breaks out if the total number of allowed occurrences is exceeded */ while (!icaltime_is_null_time(next) && (icaltime_as_timet(next) < date_limit)) { num_resv++; next = icalrecur_iterator_next(itr); } icalrecur_iterator_free(itr); return num_resv; #else if (rrule == NULL) return 1; return 0; #endif }