コード例 #1
0
ファイル: pbs_ical.c プロジェクト: suresh-thelkar/pbspro-1
/**
 * @brief
 * 	Get the occurrence as defined by the given recurrence rule,
 * 	index, and start time. This function assumes that the
 * 	time dtsart passed in is the one to start the occurrence from.
 *
 * @par	NOTE: This function should be made reentrant such that
 * 	it can be looped over without having to loop over every occurrence
 * 	over and over again.
 *
 * @param[in] rrule - The recurrence rule as defined by the user
 * @param[in] dtstart - The start time from which to start
 * @param[in] tz - The timezone associated to the recurrence rule
 * @param[in] idx - The index of the occurrence to start counting from
 *
 * @return 	time_t
 * @retval	The date of the next occurrence or -1 if the date exceeds libical's
 * 		Unix time in 2038
 *
 */
time_t
get_occurrence(char *rrule, time_t dtstart, char *tz, int idx)
{


#ifdef LIBICAL
	struct icalrecurrencetype rt;
	struct icaltimetype start;
	icaltimezone *localzone;
	struct icaltimetype next;
	struct icalrecur_iterator_impl *itr;
	int i;
	time_t next_occr = dtstart;

	if (rrule == NULL)
		return dtstart;

	if (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 -1;

	rt = icalrecurrencetype_from_string(rrule);

	start = icaltime_from_timet_with_zone(dtstart, 0, NULL);
	icaltimezone_convert_time(&start, icaltimezone_get_utc_timezone(), localzone);
	next = start;

	itr = (struct icalrecur_iterator_impl*) icalrecur_iterator_new(rt, start);
	/* Skip as many occurrences as specified by idx */
	for (i = 0; i < idx && !icaltime_is_null_time(next); i++)
		next = icalrecur_iterator_next(itr);

	if (!icaltime_is_null_time(next)) {
		icaltimezone_convert_time(&next, localzone,
			icaltimezone_get_utc_timezone());
		next_occr = icaltime_as_timet(next);
	}
	else next_occr = -1; /* If reached end of possible date-time return -1 */

		icalrecur_iterator_free(itr);

	return next_occr;

#else

	return dtstart;
#endif
}
コード例 #2
0
ファイル: pbs_ical.c プロジェクト: agurban/pbspro
/**
 * @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);
	icalerror_errors_are_fatal = 0;
	localzone = icaltimezone_get_builtin_timezone(tz);

	if (localzone == NULL)
		return 0;

	now = time((time_t *)0);
	date_limit = now + DATE_LIMIT;

	rt = icalrecurrencetype_from_string(rrule);

	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);

	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
}
コード例 #3
0
VALUE occurrences( VALUE self, VALUE dtstart, VALUE dtend, VALUE rrule ) {
  char * _rrule;
  struct icaltimetype start, end;
  time_t tt;
  VALUE  tv_sec, occurr = rb_ary_new();

  /* Get method ID for Time.tv_sec */
  ID time_tv_sec  = rb_intern( "tv_sec" );
  ID to_string    = rb_intern( "to_string" );

  if( TYPE( rrule ) != T_STRING && rb_respond_to( rrule, to_string ) )
    rrule = rb_funcall( rrule, to_string, 0 );

  Check_Type(rrule, T_STRING);
  _rrule = RSTRING(rrule)->ptr;

  dtstart = to_time( dtstart, "dtstart" );
  dtend   = to_time( dtend,   "dtend" );

  /* Apply .tv_sec to our Time objects (if they are Times ...) */
  tv_sec = rb_funcall( dtstart, time_tv_sec, 0 );
  tt     = NUM2INT( tv_sec );
  start  = icaltime_from_timet( tt, 0 );

  tv_sec = rb_funcall( dtend, time_tv_sec, 0 );
  tt     = NUM2INT( tv_sec );
  end    = icaltime_from_timet( tt, 0 );

  icalerror_clear_errno();
  icalerror_set_error_state( ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL);

  struct icalrecurrencetype recur = icalrecurrencetype_from_string( _rrule );
  if( icalerrno != ICAL_NO_ERROR ) {
    rb_raise(rb_eArgError, "Malformed RRule");
    return Qnil;
  }

  icalrecur_iterator* ritr = icalrecur_iterator_new( recur, start );

  while(1) {
    struct icaltimetype next = icalrecur_iterator_next(ritr);

    if( icaltime_is_null_time(next) || ( icaltime_compare( next, end ) > 0 ) ) {
      icalrecur_iterator_free(ritr);
      return occurr;
    }

    rb_ary_push( occurr, rb_time_new( icaltime_as_timet( next ), 0 ) );
  };

  icalrecur_iterator_free(ritr);
  return occurr;
}
コード例 #4
0
ファイル: errors.c プロジェクト: BenjamenMeyer/libical
void program_errors()
{
    /*Most routines will set icalerrno on errors. This is an
      enumeration defined in icalerror.h */

    icalerror_clear_errno();

    (void)icalcomponent_new(ICAL_VEVENT_COMPONENT);

    if (icalerrno != ICAL_NO_ERROR){

        fprintf(stderr,"Horrible libical error: %s\n",
                icalerror_strerror(icalerrno));

    }

}
コード例 #5
0
ファイル: icalcalendar.c プロジェクト: BenjamenMeyer/libical
icalset *icalcalendar_get_booked(icalcalendar *impl)
{
    char dir[MAXPATHLEN];

    icalerror_check_arg_rz((impl != 0), "impl");

    dir[0] = '\0';
    strncpy(dir, impl->dir, MAXPATHLEN - 1);
    strncat(dir, "/", MAXPATHLEN - strlen(dir) - 1);
    strncat(dir, BOOKED_DIR, MAXPATHLEN - strlen(dir) - 1);
    dir[MAXPATHLEN - 1] = '\0';

    if (impl->booked == 0) {
        icalerror_clear_errno();
        impl->booked = icaldirset_new(dir);
        assert(icalerrno == ICAL_NO_ERROR);
    }

    return impl->booked;
}
コード例 #6
0
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 ));
}
コード例 #7
0
ファイル: icalspanlist.c プロジェクト: xfce-mirror/orage
icalspanlist* icalspanlist_new(icalset *set, 
			       struct icaltimetype start,
			       struct icaltimetype end)
{
    struct icaltime_span range;
    pvl_elem itr;
    icalcomponent *c,*inner;
    icalcomponent_kind kind, inner_kind;
    icalspanlist *sl; 
    struct icaltime_span *freetime;

    if ( ( sl = (struct icalspanlist_impl*)
	   malloc(sizeof(struct icalspanlist_impl))) == 0) {
	icalerror_set_errno(ICAL_NEWFAILED_ERROR);
	return 0;
    }

    sl->spans =  pvl_newlist();
    sl->start =  start;
    sl->end   =  end;

    range.start = icaltime_as_timet(start);
    range.end = icaltime_as_timet(end);

    /* Get a list of spans of busy time from the events in the set
       and order the spans based on the start time */

   for(c = icalset_get_first_component(set);
	c != 0;
	c = icalset_get_next_component(set)){

       kind  = icalcomponent_isa(c);
       inner = icalcomponent_get_inner(c);

       if(!inner){
	   continue;
       }

       inner_kind = icalcomponent_isa(inner);

       if( kind != ICAL_VEVENT_COMPONENT &&
	   inner_kind != ICAL_VEVENT_COMPONENT){
	   continue;
       }
       
       icalerror_clear_errno();
       
       icalcomponent_foreach_recurrence(c, start, end, 
					icalspanlist_new_callback, 
					(void*)sl);
       
   }
    
    /* Now Fill in the free time spans. loop through the spans. if the
       start of the range is not within the span, create a free entry
       that runs from the start of the range to the start of the
       span. */

     for( itr = pvl_head(sl->spans);
	 itr != 0;
	 itr = pvl_next(itr))
    {
	struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr);

	if ((freetime=(struct icaltime_span *)
	     malloc(sizeof(struct icaltime_span))) == 0){
	    icalerror_set_errno(ICAL_NEWFAILED_ERROR);
	    return 0;
	    }

	if(range.start < s->start){
	    freetime->start = range.start; 
	    freetime->end = s->start;
	    
	    freetime->is_busy = 0;


	    pvl_insert_ordered(sl->spans,compare_span,(void*)freetime);
	} else {
	    free(freetime);
	}
	
	range.start = s->end;
    }
     
     /* If the end of the range is null, then assume that everything
        after the last item in the calendar is open and add a span
        that indicates this */

     if( icaltime_is_null_time(end)){
	 struct icaltime_span* last_span;

	 last_span = (struct icaltime_span*)pvl_data(pvl_tail(sl->spans));

	 if (last_span != 0){

	     if ((freetime=(struct icaltime_span *)
		  malloc(sizeof(struct icaltime_span))) == 0){
		 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
		 return 0;
	     }	
	
	     freetime->is_busy = 0;
	     freetime->start = last_span->end;
	     freetime->end = freetime->start;
	     pvl_insert_ordered(sl->spans,compare_span,(void*)freetime);
	 }
     }


     return sl;
}
コード例 #8
0
ファイル: pbs_ical.c プロジェクト: agurban/pbspro
/**
 * @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
}