struct icalperiodtype icalperiodtype_from_string (const char* str)
{

    struct icalperiodtype p, null_p;
    char *s = icalmemory_strdup(str);
    char *start, *end = s;
    icalerrorstate es;

    /* Errors are normally generated in the following code, so save
       the error state for resoration later */

    icalerrorenum e = icalerrno;

    p.start = p.end = icaltime_null_time();
    p.duration = icaldurationtype_from_int(0);

    null_p = p;

    if(s == 0) goto error;

    start = s;
    end = strchr(s, '/');

    if(end == 0) goto error;

    *end = 0;
    end++;

    p.start = icaltime_from_string(start);

    if (icaltime_is_null_time(p.start)) goto error;

    es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR);
    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL);

    p.end = icaltime_from_string(end);

    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es);


    if (icaltime_is_null_time(p.end)) {

        p.duration = icaldurationtype_from_string(end);

        if(icaldurationtype_as_int(p.duration) == 0) goto error;
    }

    icalerrno = e;

    icalmemory_free_buffer(s);

    return p;

error:
    icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);

    if (s)
        icalmemory_free_buffer (s);
    return null_p;
}
Beispiel #2
0
/**
 * @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
}
int icalperiodtype_is_null_period(struct icalperiodtype p) {

    if(icaltime_is_null_time(p.start) &&
            icaltime_is_null_time(p.end) &&
            icaldurationtype_is_null_duration(p.duration)) {
        return 1;
    } else {
        return 0;
    }
}
char* icalperiodtype_as_ical_string_r(struct icalperiodtype p)
{

    const char* start;
    const char* end;

    char *buf;
    size_t buf_size = 40;
    char* buf_ptr = 0;

    buf = (char*)icalmemory_new_buffer(buf_size);
    buf_ptr = buf;


    start = icaltime_as_ical_string_r(p.start);
    icalmemory_append_string(&buf, &buf_ptr, &buf_size, start);
    icalmemory_free_buffer(start);

    if(!icaltime_is_null_time(p.end)) {
        end = icaltime_as_ical_string_r(p.end);
    } else {
        end = icaldurationtype_as_ical_string_r(p.duration);
    }

    icalmemory_append_char(&buf, &buf_ptr, &buf_size, '/');

    icalmemory_append_string(&buf, &buf_ptr, &buf_size, end);
    icalmemory_free_buffer(end);

    return buf;
}
Beispiel #5
0
int main(int argc, char *argv[]) {
    struct icalrecurrencetype recur;
    icalrecur_iterator *ritr;
    struct icaltimetype dtstart, next;
    char *icr = "FREQ=WEEKLY;INTERVAL=2;COUNT=6;BYDAY=WE,SA,SU";
    char *dtstr = "20081217T133000";
    int howmany = 1;

    if (argc > 0) {
        icr = argv[1];
    }
    if (argc > 1) {
        howmany = atoi(argv[2]);
    }
    if (argc > 2) {
        dtstr = argv[3];
    }
        
    dtstart = icaltime_from_string(dtstr);
    recur = icalrecurrencetype_from_string(icr);
    ritr = icalrecur_iterator_new(recur, dtstart);

    printf("Using rule: %s\n", icr);
    printf("Iterating %d occurrences beginning from %s\n", howmany, dtstr);

    if (ritr) {
        while (howmany-- && !icaltime_is_null_time(next)) {
            next = icalrecur_iterator_next(ritr);
            printf("%s\n", icaltime_as_ical_string_r(next));
        }
    } else {
        printf("Error: %d\n", icalerrno);
    }
}
Beispiel #6
0
/**
 * e_cal_util_is_first_instance:
 * @comp: an #ECalComponent instance
 * @rid: a recurrence ID
 * @tz_cb: (closure tz_cb_data) (scope call): The #ECalRecurResolveTimezoneFn to call
 * @tz_cb_data: (closure): User data to be passed to the @tz_cb callback
 *
 * Returns whether the given @rid is the first instance of
 * the recurrence defined in the @comp.
 *
 * Return: Whether the @rid identifies the first instance of @comp.
 *
 * Since: 3.16
 **/
gboolean
e_cal_util_is_first_instance (ECalComponent *comp,
			      struct icaltimetype rid,
			      ECalRecurResolveTimezoneFn tz_cb,
			      gpointer tz_cb_data)
{
	CheckFirstInstanceData ifs;
	icalcomponent *icalcomp;
	time_t start, end;

	g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
	g_return_val_if_fail (!icaltime_is_null_time (rid), FALSE);

	ifs.rid = rid;
	ifs.matches = FALSE;

	icalcomp = e_cal_component_get_icalcomponent (comp);
	start = icaltime_as_timet (icalcomponent_get_dtstart (icalcomp)) - 24 * 60 * 60;
	end = icaltime_as_timet (icalcomponent_get_dtend (icalcomp)) + 24 * 60 * 60;

	e_cal_recur_generate_instances (comp, start, end, check_first_instance_cb, &ifs,
		tz_cb, tz_cb_data, icaltimezone_get_utc_timezone ());

	return ifs.matches;
}
Beispiel #7
0
struct icaltriggertype icaltriggertype_from_string(const char* str)
{

    
    struct icaltriggertype tr, null_tr;
    int old_ieaf = icalerror_errors_are_fatal;

    tr.time= icaltime_null_time();
    tr.duration = icaldurationtype_from_int(0);

    null_tr = tr;

    if(str == 0) goto error;


    icalerror_errors_are_fatal = 0;

    tr.time = icaltime_from_string(str);

    icalerror_errors_are_fatal = old_ieaf;

    if (icaltime_is_null_time(tr.time)){

	tr.duration = icaldurationtype_from_string(str);

	if(icaldurationtype_as_int(tr.duration) == 0) goto error;
    } 

    return tr;

 error:
    icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
    return null_tr;

}
void
icalvalue_set_datetimeperiod(icalvalue* impl, struct icaldatetimeperiodtype v)
{
    icalerror_check_arg_rv( (impl!=0),"value");
    
    icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE);

    if(!icaltime_is_null_time(v.time)){
	if(!icaltime_is_valid_time(v.time)){
	    icalerror_set_errno(ICAL_BADARG_ERROR);
	    return;
	}
	impl->kind = ICAL_DATETIME_VALUE;
	icalvalue_set_datetime(impl,v.time);
    } else if (!icalperiodtype_is_null_period(v.period)) {
	if(!icalperiodtype_is_valid_period(v.period)){
	    icalerror_set_errno(ICAL_BADARG_ERROR);
	    return;
	}
	impl->kind = ICAL_PERIOD_VALUE;
	icalvalue_set_period(impl,v.period);
    } else {
	icalerror_set_errno(ICAL_BADARG_ERROR);
    }
}
Beispiel #9
0
PRTime calDateTime::IcaltimeToPRTime(icaltimetype const* icalt, icaltimezone const* tz)
{
    icaltimetype tt;
    PRExplodedTime et;

    /* If the time is the special null time, return 0. */
    if (icaltime_is_null_time(*icalt)) {
        return 0;
    }

    if (tz) {
        // use libical for timezone conversion, as it can handle all ics
        // timezones. having nspr do it is much harder.
        tt = icaltime_convert_to_zone(*icalt, const_cast<icaltimezone *>(tz));
    } else {
        tt = *icalt;
    }

    /* Empty the destination */
    memset(&et, 0, sizeof(struct PRExplodedTime));

    /* Fill the fields */
    if (icaltime_is_date(tt)) {
        et.tm_sec = et.tm_min = et.tm_hour = 0;
    } else {
        et.tm_sec = tt.second;
        et.tm_min = tt.minute;
        et.tm_hour = tt.hour;
    }
    et.tm_mday = static_cast<int16_t>(tt.day);
    et.tm_month = static_cast<int16_t>(tt.month-1);
    et.tm_year = static_cast<int16_t>(tt.year);

    return PR_ImplodeTime(&et);
}
Beispiel #10
0
icaltime_span icaltime_span_new(struct icaltimetype dtstart, struct icaltimetype dtend, int is_busy)
{
    icaltime_span span;

    span.is_busy = is_busy;

    span.start = icaltime_as_timet_with_zone(dtstart,
                                             dtstart.zone ? dtstart.
                                             zone : icaltimezone_get_utc_timezone());

    if (icaltime_is_null_time(dtend)) {
        if (!icaltime_is_date(dtstart)) {
            /* If dtstart is a DATE-TIME and there is no DTEND nor DURATION
               it takes no time */
            span.end = span.start;
            return span;
        } else {
            dtend = dtstart;
        }
    }

    span.end = icaltime_as_timet_with_zone(dtend,
                                           dtend.zone ? dtend.
                                           zone : icaltimezone_get_utc_timezone());

    if (icaltime_is_date(dtstart)) {
        /* no time specified, go until the end of the day.. */
        span.end += 60 * 60 * 24 - 1;
    }
    return span;
}
Beispiel #11
0
/**     @brief  Return the time as seconds past the UNIX epoch
 *
 *      While this function is not currently deprecated, it probably won't do
 *      what you expect, unless you know what you're doing. In particular, you
 *      should only pass an icaltime in UTC, since no conversion is done. Even
 *      in that case, it's probably better to just use
 *      icaltime_as_timet_with_zone().
 */
time_t icaltime_as_timet(const struct icaltimetype tt)
{
    struct tm stm;
    time_t t;

    /* If the time is the special null time, return 0. */
    if (icaltime_is_null_time(tt)) {
        return 0;
    }

    /* Copy the icaltimetype to a struct tm. */
    memset(&stm, 0, sizeof(struct tm));

    if (icaltime_is_date(tt)) {
        stm.tm_sec = stm.tm_min = stm.tm_hour = 0;
    } else {
        stm.tm_sec = tt.second;
        stm.tm_min = tt.minute;
        stm.tm_hour = tt.hour;
    }

    stm.tm_mday = tt.day;
    stm.tm_mon = tt.month - 1;
    stm.tm_year = tt.year - 1900;
    stm.tm_isdst = -1;

    t = make_time(&stm, 0);

    return t;
}
Beispiel #12
0
/**
 * @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
}
void calDateTime::FromIcalTime(icaltimetype const* icalt, calITimezone * tz)
{
    icaltimetype t = *icalt;
    mIsValid = (icaltime_is_null_time(t) ||
                icaltime_is_valid_time(t) ? true : false);

    mIsDate = t.is_date ? true : false;
    if (mIsDate) {
        t.hour = 0;
        t.minute = 0;
        t.second = 0;
    }

    if (mIsValid) {
        t = icaltime_normalize(t);
    }

    mYear = static_cast<int16_t>(t.year);
    mMonth = static_cast<int16_t>(t.month - 1);
    mDay = static_cast<int16_t>(t.day);
    mHour = static_cast<int16_t>(t.hour);
    mMinute = static_cast<int16_t>(t.minute);
    mSecond = static_cast<int16_t>(t.second);

    if (tz) {
        mTimezone = tz;
    } else {
        mTimezone = cal::detectTimezone(t, nullptr);
    }
#if defined(DEBUG)
    if (mTimezone) {
        if (t.is_utc) {
            nsCOMPtr<calITimezone> ctz = cal::UTC();
            NS_ASSERTION(SameCOMIdentity(mTimezone, ctz), "UTC mismatch!");
        } else if (!t.zone) {
            nsAutoCString tzid;
            mTimezone->GetTzid(tzid);
            if (tzid.EqualsLiteral("floating")) {
                nsCOMPtr<calITimezone> ctz = cal::floating();
                NS_ASSERTION(SameCOMIdentity(mTimezone, ctz), "floating mismatch!");
            }
        } else {
            nsAutoCString tzid;
            mTimezone->GetTzid(tzid);
            NS_ASSERTION(tzid.Equals(icaltimezone_get_tzid(const_cast<icaltimezone *>(t.zone))),
                         "tzid mismatch!");
        }
    }
#endif

    mWeekday = static_cast<int16_t>(icaltime_day_of_week(t) - 1);
    mYearday = static_cast<int16_t>(icaltime_day_of_year(t));

    // mNativeTime: not moving the existing date to UTC,
    // but merely representing it a UTC-based way.
    t.is_date = 0;
    mNativeTime = IcaltimeToPRTime(&t, icaltimezone_get_utc_timezone());
}
int icaltriggertype_is_null_trigger(struct icaltriggertype tr)
{
    if(icaltime_is_null_time(tr.time) && 
       icaldurationtype_is_null_duration(tr.duration)){
        return 1;
    }

    return 0;
}
int icalperiodtype_is_valid_period(struct icalperiodtype p) {
    if(icaltime_is_valid_time(p.start) &&
            (icaltime_is_valid_time(p.end) || icaltime_is_null_time(p.end)) )
    {
        return 1;
    }

    return 0;
}
Beispiel #16
0
NS_IMETHODIMP
calDateTime::SetIcalString(nsACString const& aIcalString)
{
    NS_ENSURE_FALSE(mImmutable, NS_ERROR_OBJECT_IS_IMMUTABLE);
    icaltimetype icalt;
    icalt = icaltime_from_string(PromiseFlatCString(aIcalString).get());
    if (icaltime_is_null_time(icalt)) {
        return static_cast<nsresult>(calIErrors::ICS_ERROR_BASE + icalerrno);
    }
    FromIcalTime(&icalt, nullptr);
    return NS_OK;
}
Beispiel #17
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;
}
void
icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v)
{
    icalerror_check_arg_rv( (value!=0),"value");
    
   if(!icaltime_is_null_time(v.time)){
       icalvalue_set_datetime(value,v.time);
       value->kind = ICAL_DATETIME_VALUE;
   } else {
       icalvalue_set_duration(value,v.duration);
       value->kind = ICAL_DURATION_VALUE;
   }
}
/* readonly attribute boolean isFinite; */
NS_IMETHODIMP
calRecurrenceRule::GetIsFinite(bool *_retval)
{
    NS_ENSURE_ARG_POINTER(_retval);

    if ((mIsByCount && mIcalRecur.count == 0) ||
        (!mIsByCount && icaltime_is_null_time(mIcalRecur.until)))
    {
        *_retval = false;
    } else {
        *_retval = true;
    }
    return NS_OK;
}
static char *
get_ical_rid (icalcomponent *ical)
{
  icalproperty        *prop;
  struct icaltimetype  ical_time;

  prop = icalcomponent_get_first_property (ical, ICAL_RECURRENCEID_PROPERTY);
  if (!prop)
    return NULL;

  ical_time = icalproperty_get_recurrenceid (prop);

  return icaltime_is_valid_time (ical_time) && !icaltime_is_null_time (ical_time) ?
    g_strdup (icaltime_as_ical_string (ical_time)) : NULL;
}
NS_IMETHODIMP
calPeriod::SetIcalString(const nsACString &aIcalString) {
  if (mImmutable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  struct icalperiodtype ip;
  ip = icalperiodtype_from_string(PromiseFlatCString(aIcalString).get());
  // XXX Shortcut. Assumes nobody tried to overrule our impl. of calIDateTime
  mStart = new calDateTime(&ip.start, nullptr);
  if (icaltime_is_null_time(ip.end)) {
    struct icaltimetype end;
    end = icaltime_add(ip.start, ip.duration);
    mEnd = new calDateTime(&end, nullptr);
  } else {
    mEnd = new calDateTime(&ip.end, nullptr);
  }
  return NS_OK;
}
Beispiel #22
0
/*
 * Add an XML element for an iCalendar Period.
 */
static void icalperiodtype_add_as_xml_element(xmlNodePtr xtype,
        struct icalperiodtype p)
{
    const char *start;
    const char *end;

    start = icaltime_as_iso_string(p.start);
    xmlNewTextChild(xtype, NULL, BAD_CAST "start", BAD_CAST start);

    if (!icaltime_is_null_time(p.end)) {
        end = icaltime_as_iso_string(p.end);
        xmlNewTextChild(xtype, NULL, BAD_CAST "end", BAD_CAST end);
    }
    else {
        end = icaldurationtype_as_ical_string(p.duration);
        xmlNewTextChild(xtype, NULL, BAD_CAST "duration", BAD_CAST end);
    }
}
Beispiel #23
0
/*
 * Construct a JSON string for an iCalendar Period.
 */
static char *icalperiodtype_as_json_string(struct icalperiodtype p)
{
    static char str[42];
    const char *start;
    const char *end;

    start = icaltime_as_iso_string(p.start);
    snprintf(str, sizeof(str), "%s/", start);

    if (!icaltime_is_null_time(p.end))
        end = icaltime_as_iso_string(p.end);
    else
        end = icaldurationtype_as_ical_string(p.duration);

    strlcat(str, end, sizeof(str));

    return str;
}
struct icaltriggertype icaltriggertype_from_string(const char* str)
{

    
    struct icaltriggertype tr, null_tr;
    icalerrorstate es = ICAL_ERROR_DEFAULT;
    icalerrorenum e;

    tr.time= icaltime_null_time();
    tr.duration = icaldurationtype_from_int(0);

    null_tr = tr;


    /* Suppress errors so a failure in icaltime_from_string() does not cause an abort */
    es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR);
    if(str == 0) goto error;
    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL);
    e = icalerrno;
    icalerror_set_errno(ICAL_NO_ERROR);

    tr.time = icaltime_from_string(str);

    if (icaltime_is_null_time(tr.time)){

	tr.duration = icaldurationtype_from_string(str);

        if (icaldurationtype_is_bad_duration(tr.duration)) goto error;
    } 

    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es);
    icalerror_set_errno(e);
    return tr;

 error:
    icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es);
    icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
    return tr;

}
int main()
{

	const char *rrule = "FREQ=DAILY;UNTIL=20080820T143500Z"; 
	icaltimetype dtstart = icaltime_from_timet(time(0) - (2*24*3600), 0);
	time_t viewend;

	struct icalrecurrencetype recur;
	time_t utc_tim;
	time_t dtst_utc;
	bool loopexit = false;

	recur = icalrecurrencetype_from_string(rrule);

	printf ("date is given by %d:%d:%d\n\n", dtstart.year, dtstart.month, dtstart.day);
	
	dtst_utc = icaltime_as_timet(dtstart);
	icalrecur_iterator *ritr;
	ritr = icalrecur_iterator_new(recur, dtstart);


	struct icaltimetype next;
	next = icalrecur_iterator_next(ritr);

	while ((!icaltime_is_null_time(next)) && (!loopexit)) {

		utc_tim = icaltime_as_timet(next);

		if (time (0) < utc_tim)
		{
			printf ("Recurrent time : %s\n", ctime(&utc_tim));
			loopexit = true;
		}

		next = icalrecur_iterator_next(ritr);
	}

	icalrecur_iterator_free(ritr);
}
Beispiel #26
0
/**     Return the time as seconds past the UNIX epoch, using the
 *      given timezone.
 *
 *      This convenience method combines a call to icaltime_convert_to_zone()
 *      with a call to icaltime_as_timet().
 *      If the input timezone is null, no conversion is done; that is, the
 *      time is simply returned as time_t in its native timezone.
 */
time_t icaltime_as_timet_with_zone(const struct icaltimetype tt, const icaltimezone *zone)
{
    icaltimezone *utc_zone;
    struct tm stm;
    time_t t;
    struct icaltimetype local_tt;

    utc_zone = icaltimezone_get_utc_timezone();

    /* If the time is the special null time, return 0. */
    if (icaltime_is_null_time(tt)) {
        return 0;
    }

    local_tt = tt;

    /* Clear the is_date flag, so we can convert the time. */
    local_tt.is_date = 0;

    /* Use our timezone functions to convert to UTC. */
    icaltimezone_convert_time(&local_tt, (icaltimezone *) zone, utc_zone);

    /* Copy the icaltimetype to a struct tm. */
    memset(&stm, 0, sizeof(struct tm));

    stm.tm_sec = local_tt.second;
    stm.tm_min = local_tt.minute;
    stm.tm_hour = local_tt.hour;
    stm.tm_mday = local_tt.day;
    stm.tm_mon = local_tt.month - 1;
    stm.tm_year = local_tt.year - 1900;
    stm.tm_isdst = -1;

    t = icaltime_timegm(&stm);

    return t;
}
Beispiel #27
0
/**
 * e_cal_util_split_at_instance:
 * @icalcomp: A (recurring) #icalcomponent
 * @rid: The base RECURRENCE-ID to remove
 * @master_dtstart: The DTSTART of the master object
 *
 * Splits a recurring @icalcomp into two at time @rid. The returned icalcomponent
 * is modified @icalcomp which contains recurrences beginning at @rid, inclusive.
 * The instance identified by @rid should exist. The @master_dtstart can be
 * a null time, then it is read from the @icalcomp.
 *
 * Use e_cal_util_remove_instances() with E_CAL_OBJ_MOD_THIS_AND_FUTURE mode
 * on the @icalcomp to remove the overlapping interval from it, if needed.
 *
 * Returns: the split icalcomponent, or %NULL.
 *
 * Since: 3.16
 **/
icalcomponent *
e_cal_util_split_at_instance (icalcomponent *icalcomp,
			      struct icaltimetype rid,
			      struct icaltimetype master_dtstart)
{
	icalproperty *prop;
	struct instance_data instance;
	struct icaltimetype start, end;
	struct icaldurationtype duration;
	GSList *remove_props = NULL, *link;

	g_return_val_if_fail (icalcomp != NULL, NULL);
	g_return_val_if_fail (!icaltime_is_null_time (rid), NULL);

	/* Make sure this is really recurring */
	if (!icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY) &&
	    !icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY))
		return NULL;

	/* Make sure the specified instance really exists */
	start = icaltime_convert_to_zone (rid, icaltimezone_get_utc_timezone ());
	end = start;
	icaltime_adjust (&end, 0, 0, 0, 1);

	instance.start = icaltime_as_timet (start);
	instance.found = FALSE;
	icalcomponent_foreach_recurrence (icalcomp, start, end,
					  check_instance, &instance);
	/* Make the copy */
	icalcomp = icalcomponent_new_clone (icalcomp);

	e_cal_util_remove_instances_ex (icalcomp, rid, E_CAL_OBJ_MOD_THIS_AND_PRIOR, TRUE, FALSE);

	start = rid;
	if (icaltime_is_null_time (master_dtstart))
		master_dtstart = icalcomponent_get_dtstart (icalcomp);
	duration = icalcomponent_get_duration (icalcomp);

	/* Expect that DTSTART and DTEND are already set when the instance could not be found */
	if (instance.found) {
		icalcomponent_set_dtstart (icalcomp, start);
		/* Update either DURATION or DTEND */
		if (icaltime_is_null_time (icalcomponent_get_dtend (icalcomp))) {
			icalcomponent_set_duration (icalcomp, duration);
		} else {
			end = start;
			if (duration.is_neg)
				icaltime_adjust (&end, -duration.days - 7 * duration.weeks, -duration.hours, -duration.minutes, -duration.seconds);
			else
				icaltime_adjust (&end, duration.days + 7 * duration.weeks, duration.hours, duration.minutes, duration.seconds);
			icalcomponent_set_dtend (icalcomp, end);
		}
	}

	/* any RRULE with 'count' should be shortened */
	for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
	     prop;
	     prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) {
		struct icaltimetype recur;
		struct icalrecurrencetype rule;

		rule = icalproperty_get_rrule (prop);

		if (rule.count != 0) {
			gint occurrences_count = 0;
			icalrecur_iterator *iter;

			iter = icalrecur_iterator_new (rule, master_dtstart);
			while (recur = icalrecur_iterator_next (iter), !icaltime_is_null_time (recur) && occurrences_count < rule.count) {
				if (icaltime_compare (recur, rid) >= 0)
					break;

				occurrences_count++;
			}

			icalrecur_iterator_free (iter);

			if (icaltime_is_null_time (recur)) {
				remove_props = g_slist_prepend (remove_props, prop);
			} else {
				rule.count -= occurrences_count;
				icalproperty_set_rrule (prop, rule);
				icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE");
			}
		}
	}

	for (link = remove_props; link; link = g_slist_next (link)) {
		prop = link->data;

		icalcomponent_remove_property (icalcomp, prop);
	}

	g_slist_free (remove_props);

	return icalcomp;
}
Beispiel #28
0
static void
e_cal_util_remove_instances_ex (icalcomponent *icalcomp,
				struct icaltimetype rid,
				ECalObjModType mod,
				gboolean keep_rid,
				gboolean can_add_exrule)
{
	icalproperty *prop;
	struct icaltimetype itt, recur;
	struct icalrecurrencetype rule;
	icalrecur_iterator *iter;
	GSList *remove_props = NULL, *rrules = NULL, *link;

	g_return_if_fail (icalcomp != NULL);
	g_return_if_fail (mod != E_CAL_OBJ_MOD_ALL);

	/* First remove RDATEs and EXDATEs in the indicated range. */
	for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY);
	     prop;
	     prop = icalcomponent_get_next_property (icalcomp, ICAL_RDATE_PROPERTY)) {
		struct icaldatetimeperiodtype period;

		period = icalproperty_get_rdate (prop);
		if (time_matches_rid (period.time, rid, mod) && (!keep_rid ||
		    icaltime_compare (period.time, rid) != 0))
			remove_props = g_slist_prepend (remove_props, prop);
	}
	for (prop = icalcomponent_get_first_property (icalcomp, ICAL_EXDATE_PROPERTY);
	     prop;
	     prop = icalcomponent_get_next_property (icalcomp, ICAL_EXDATE_PROPERTY)) {
		itt = icalproperty_get_exdate (prop);
		if (time_matches_rid (itt, rid, mod) && (!keep_rid ||
		    icaltime_compare (itt, rid) != 0))
			remove_props = g_slist_prepend (remove_props, prop);
	}

	for (link = remove_props; link; link = g_slist_next (link)) {
		prop = link->data;

		icalcomponent_remove_property (icalcomp, prop);
	}

	g_slist_free (remove_props);
	remove_props = NULL;

	/* If we're only removing one instance, just add an EXDATE. */
	if (mod == E_CAL_OBJ_MOD_THIS) {
		prop = icalproperty_new_exdate (rid);
		icalcomponent_add_property (icalcomp, prop);
		return;
	}

	/* Otherwise, iterate through RRULEs */
	/* FIXME: this may generate duplicate EXRULEs */
	for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
	     prop;
	     prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) {
		rrules = g_slist_prepend (rrules, prop);
	}

	for (link = rrules; link; link = g_slist_next (link)) {
		prop = link->data;
		rule = icalproperty_get_rrule (prop);

		iter = icalrecur_iterator_new (rule, rid);
		recur = icalrecur_iterator_next (iter);

		if (mod & E_CAL_OBJ_MOD_THIS_AND_FUTURE) {
			/* Truncate the rule at rid. */
			if (!icaltime_is_null_time (recur)) {
				/* Use count if it was used */
				if (rule.count > 0) {
					gint occurrences_count = 0;
					icalrecur_iterator *count_iter;
					struct icaltimetype count_recur;

					count_iter = icalrecur_iterator_new (rule, icalcomponent_get_dtstart (icalcomp));
					while (count_recur = icalrecur_iterator_next (count_iter), !icaltime_is_null_time (count_recur) && occurrences_count < rule.count) {
						if (icaltime_compare (count_recur, rid) >= 0)
							break;

						occurrences_count++;
					}

					icalrecur_iterator_free (count_iter);

					if (keep_rid && icaltime_compare (count_recur, rid) == 0)
						occurrences_count++;

					/* The caller should make sure that the remove will keep at least one instance */
					g_warn_if_fail (occurrences_count > 0);

					rule.count = occurrences_count;
				} else {
					if (keep_rid && icaltime_compare (recur, rid) == 0)
						rule.until = icaltime_add (rid, icalcomponent_get_duration (icalcomp));
					else
						rule.until = rid;
					icaltime_adjust (&rule.until, 0, 0, 0, -1);
				}

				icalproperty_set_rrule (prop, rule);
				icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE");
			}
		} else {
			/* (If recur == rid, skip to the next occurrence) */
			if (!keep_rid && icaltime_compare (recur, rid) == 0)
				recur = icalrecur_iterator_next (iter);

			/* If there is a recurrence after rid, add
			 * an EXRULE to block instances up to rid.
			 * Otherwise, just remove the RRULE.
			 */
			if (!icaltime_is_null_time (recur)) {
				if (can_add_exrule) {
					rule.count = 0;
					/* iCalendar says we should just use rid
					 * here, but Outlook/Exchange handle
					 * UNTIL incorrectly.
					 */
					if (keep_rid && icaltime_compare (recur, rid) == 0) {
						struct icaldurationtype duration = icalcomponent_get_duration (icalcomp);
						duration.is_neg = !duration.is_neg;
						rule.until = icaltime_add (rid, duration);
					} else
						rule.until = icaltime_add (rid, icalcomponent_get_duration (icalcomp));
					prop = icalproperty_new_exrule (rule);
					icalcomponent_add_property (icalcomp, prop);
				}
			} else {
				remove_props = g_slist_prepend (remove_props, prop);
			}
		}

		icalrecur_iterator_free (iter);
	}

	for (link = remove_props; link; link = g_slist_next (link)) {
		prop = link->data;

		icalcomponent_remove_property (icalcomp, prop);
	}

	g_slist_free (remove_props);
	g_slist_free (rrules);
}
Beispiel #29
0
/*
 * Construct an iCalendar property value from XML content.
 */
static icalvalue *xml_element_to_icalvalue(xmlNodePtr xtype,
        icalvalue_kind kind)
{
    icalvalue *value = NULL;
    xmlNodePtr node;
    xmlChar *content = NULL;

    switch (kind) {

    case ICAL_GEO_VALUE: {
        struct icalgeotype geo;

        node = xmlFirstElementChild(xtype);
        if (!node) {
            syslog(LOG_WARNING, "Missing <latitude> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "latitude")) {
            syslog(LOG_WARNING,
                   "Expected <latitude> XML element, received %s", node->name);
            break;
        }

        content = xmlNodeGetContent(node);
        geo.lat = atof((const char *) content);

        node = xmlNextElementSibling(node);
        if (!node) {
            syslog(LOG_WARNING, "Missing <longitude> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "longitude")) {
            syslog(LOG_WARNING,
                   "Expected <longitude> XML element, received %s", node->name);
            break;
        }

        xmlFree(content);
        content = xmlNodeGetContent(node);
        geo.lon = atof((const char *) content);

        value = icalvalue_new_geo(geo);

        break;
    }

    case ICAL_PERIOD_VALUE: {
        struct icalperiodtype p;

        p.start = p.end = icaltime_null_time();
        p.duration = icaldurationtype_from_int(0);

        node = xmlFirstElementChild(xtype);
        if (!node) {
            syslog(LOG_WARNING, "Missing <start> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "start")) {
            syslog(LOG_WARNING,
                   "Expected <start> XML element, received %s", node->name);
            break;
        }

        content = xmlNodeGetContent(node);
        p.start = icaltime_from_string((const char *) content);
        if (icaltime_is_null_time(p.start)) break;

        node = xmlNextElementSibling(node);
        if (!node) {
            syslog(LOG_WARNING, "Missing <end> / <duration> XML element");
            break;
        }
        else if (!xmlStrcmp(node->name, BAD_CAST "end")) {
            xmlFree(content);
            content = xmlNodeGetContent(node);
            p.end = icaltime_from_string((const char *) content);
            if (icaltime_is_null_time(p.end)) break;
        }
        else if (!xmlStrcmp(node->name, BAD_CAST "duration")) {
            xmlFree(content);
            content = xmlNodeGetContent(node);
            p.duration = icaldurationtype_from_string((const char *) content);
            if (icaldurationtype_as_int(p.duration) == 0) break;
        }
        else {
            syslog(LOG_WARNING,
                   "Expected <end> / <duration> XML element, received %s",
                   node->name);
            break;
        }

        value = icalvalue_new_period(p);

        break;
    }

    case ICAL_RECUR_VALUE: {
        struct buf rrule = BUF_INITIALIZER;
        struct hash_table byrules;
        struct icalrecurrencetype rt;
        char *sep = "";

        construct_hash_table(&byrules, 10, 1);

        /* create an iCal RRULE string from xCal <recur> sub-elements */
        for (node = xmlFirstElementChild(xtype); node;
                node = xmlNextElementSibling(node)) {

            content = xmlNodeGetContent(node);
            if (!xmlStrncmp(node->name, BAD_CAST "by", 2)) {
                /* BY* rules can have a list of values -
                   assemble them using a hash table */
                struct buf *vals =
                    hash_lookup((const char *) node->name, &byrules);

                if (vals) {
                    /* append this value to existing list */
                    buf_printf(vals, ",%s", (char *) content);
                }
                else {
                    /* create new list with this valiue */
                    vals = xzmalloc(sizeof(struct buf));
                    buf_setcstr(vals, (char *) content);
                    hash_insert((char *) node->name, vals, &byrules);
                }
            }
            else {
                /* single value rpart */
                buf_printf(&rrule, "%s%s=%s", sep,
                           ucase((char *) node->name), (char *) content);
                sep = ";";
            }

            xmlFree(content);
            content = NULL;
        }

        /* append the BY* rules to RRULE buffer */
        hash_enumerate(&byrules,
                       (void (*)(const char*, void*, void*)) &append_byrule,
                       &rrule);
        free_hash_table(&byrules, NULL);

        /* parse our iCal RRULE string */
        rt = icalrecurrencetype_from_string(buf_cstring(&rrule));
        buf_free(&rrule);

        if (rt.freq != ICAL_NO_RECURRENCE) value = icalvalue_new_recur(rt);

        break;
    }

    case ICAL_REQUESTSTATUS_VALUE: {
        struct icalreqstattype rst = { ICAL_UNKNOWN_STATUS, NULL, NULL };
        short maj, min;

        node = xmlFirstElementChild(xtype);
        if (!node) {
            syslog(LOG_WARNING, "Missing <code> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "code")) {
            syslog(LOG_WARNING,
                   "Expected <code> XML element, received %s", node->name);
            break;
        }

        content = xmlNodeGetContent(node);
        if (sscanf((const char *) content, "%hd.%hd", &maj, &min) == 2) {
            rst.code = icalenum_num_to_reqstat(maj, min);
        }
        if (rst.code == ICAL_UNKNOWN_STATUS) {
            syslog(LOG_WARNING, "Unknown request-status code");
            break;
        }

        node = xmlNextElementSibling(node);
        if (!node) {
            syslog(LOG_WARNING, "Missing <description> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "description")) {
            syslog(LOG_WARNING,
                   "Expected <description> XML element, received %s",
                   node->name);
            break;
        }

        xmlFree(content);
        content = xmlNodeGetContent(node);
        rst.desc = (const char *) content;

        node = xmlNextElementSibling(node);
        if (node) {
            if (xmlStrcmp(node->name, BAD_CAST "data")) {
                syslog(LOG_WARNING,
                       "Expected <data> XML element, received %s", node->name);
                break;
            }

            xmlFree(content);
            content = xmlNodeGetContent(node);
            rst.debug = (const char *) content;
        }

        value = icalvalue_new_requeststatus(rst);
        break;
    }

    case ICAL_UTCOFFSET_VALUE: {
        int n, utcoffset, hours, minutes, seconds = 0;
        char sign;

        content = xmlNodeGetContent(xtype);
        n = sscanf((const char *) content, "%c%02d:%02d:%02d",
                   &sign, &hours, &minutes, &seconds);

        if (n < 3) {
            syslog(LOG_WARNING, "Unexpected utc-offset format");
            break;
        }

        utcoffset = hours*3600 + minutes*60 + seconds;

        if (sign == '-') utcoffset = -utcoffset;

        value = icalvalue_new_utcoffset(utcoffset);
        break;
    }

    default:
        content = xmlNodeGetContent(xtype);
        value = icalvalue_new_from_string(kind, (const char *) content);
        break;
    }

    if (content) xmlFree(content);

    return value;
}
Beispiel #30
0
/*
 * Add the proper XML element for an iCalendar value.
 */
static void icalproperty_add_value_as_xml_element(xmlNodePtr xprop,
        icalproperty *prop)

{
    const char *type, *str = NULL;
    xmlNodePtr xtype;
    const icalvalue *value;
    char buf[40];

    /* Add type */
    type = lcase(icalmemory_tmp_copy(
                     icalproperty_value_kind_as_string(prop)));
    xtype = xmlNewChild(xprop, NULL, BAD_CAST type, NULL);


    /* Add value */
    value = icalproperty_get_value(prop);

    switch (icalvalue_isa(value)) {
    case ICAL_DATE_VALUE:
        str = icaltime_as_iso_string(icalvalue_get_date(value));
        break;

    case ICAL_DATETIME_VALUE:
        str = icaltime_as_iso_string(icalvalue_get_datetime(value));
        break;

    case ICAL_DATETIMEPERIOD_VALUE: {
        struct icaldatetimeperiodtype dtp =
            icalvalue_get_datetimeperiod(value);

        if (!icaltime_is_null_time(dtp.time)) {
            str = icaltime_as_iso_string(dtp.time);
            break;
        }
        else {
            icalperiodtype_add_as_xml_element(xtype, dtp.period);
            return;
        }
    }

    case ICAL_GEO_VALUE: {
        struct icalgeotype geo = icalvalue_get_geo(value);

        snprintf(buf, sizeof(buf), "%f", geo.lat);
        xmlNewTextChild(xtype, NULL, BAD_CAST "latitude", BAD_CAST buf);
        snprintf(buf, sizeof(buf), "%f", geo.lon);
        xmlNewTextChild(xtype, NULL, BAD_CAST "longitude", BAD_CAST buf);
        return;
    }

    case ICAL_PERIOD_VALUE:
        icalperiodtype_add_as_xml_element(xtype, icalvalue_get_period(value));
        return;

    case ICAL_RECUR_VALUE: {
        struct icalrecurrencetype recur = icalvalue_get_recur(value);

        icalrecurrencetype_add_as_xxx(&recur, xtype, NULL,
                                      &icalrecur_add_string_as_xml_element);
        return;
    }

    case ICAL_REQUESTSTATUS_VALUE: {
        struct icalreqstattype stat = icalvalue_get_requeststatus(value);

        if (!stat.desc) stat.desc = icalenum_reqstat_desc(stat.code);

        snprintf(buf, sizeof(buf), "%u.%u",
                 icalenum_reqstat_major(stat.code),
                 icalenum_reqstat_minor(stat.code));
        xmlNewTextChild(xtype, NULL, BAD_CAST "code", BAD_CAST buf);
        xmlNewTextChild(xtype, NULL, BAD_CAST "description", BAD_CAST stat.desc);
        if (stat.debug)
            xmlNewTextChild(xtype, NULL, BAD_CAST "data", BAD_CAST stat.debug);

        return;
    }

    case ICAL_TRIGGER_VALUE: {
        struct icaltriggertype trig = icalvalue_get_trigger(value);

        if (!icaltime_is_null_time(trig.time))
            str = icaltime_as_iso_string(trig.time);
        else
            str = icaldurationtype_as_ical_string(trig.duration);
        break;
    }

    case ICAL_UTCOFFSET_VALUE:
        str = icalvalue_utcoffset_as_iso_string(value);
        break;

    default:
        str = icalvalue_as_ical_string(value);

        switch (icalproperty_isa(prop)) {
        case ICAL_CATEGORIES_PROPERTY:
        case ICAL_RESOURCES_PROPERTY:
        case ICAL_POLLPROPERTIES_PROPERTY:
            if (strchr(str, ',')) {
                /* Handle multi-valued properties */
                tok_t tok;

                tok_init(&tok, str, ",", TOK_TRIMLEFT|TOK_TRIMRIGHT|TOK_EMPTY);
                str = tok_next(&tok);
                xmlAddChild(xtype, xmlNewText(BAD_CAST str));

                while ((str = tok_next(&tok))) {
                    if (*str) {
                        xtype = xmlNewChild(xprop, NULL, BAD_CAST type, NULL);
                        xmlAddChild(xtype, xmlNewText(BAD_CAST str));
                    }
                }
                tok_fini(&tok);
                return;
            }

        default:
            break;
        }

        break;
    }

    if (str) xmlAddChild(xtype, xmlNewText(BAD_CAST str));
}