Exemple #1
0
/**
 * e_cal_util_construct_instance:
 * @icalcomp: A recurring #icalcomponent
 * @rid: The RECURRENCE-ID to construct a component for
 *
 * This checks that @rid indicates a valid recurrence of @icalcomp, and
 * if so, generates a copy of @comp containing a RECURRENCE-ID of @rid.
 *
 * Returns: the instance, or %NULL.
 **/
icalcomponent *
e_cal_util_construct_instance (icalcomponent *icalcomp,
                               struct icaltimetype rid)
{
	struct instance_data instance;
	struct icaltimetype start, end;

	g_return_val_if_fail (icalcomp != NULL, 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);
	if (!instance.found)
		return NULL;

	/* Make the instance */
	icalcomp = icalcomponent_new_clone (icalcomp);
	icalcomponent_set_recurrenceid (icalcomp, rid);

	return icalcomp;
}
Exemple #2
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;
}
Exemple #3
0
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;
}
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);
}
Exemple #5
0
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;
}