Example #1
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));
}
nsresult calIcalProperty::getDatetime_(calIcalComponent * parent,
                                       icalproperty * prop,
                                       calIDateTime ** dtp)
{
    icalvalue * const val = icalproperty_get_value(prop);
    icalvalue_kind const valkind = icalvalue_isa(val);
    if (valkind != ICAL_DATETIME_VALUE && valkind != ICAL_DATE_VALUE) {
        return NS_ERROR_UNEXPECTED;
    }
    icaltimetype itt = icalvalue_get_datetime(val);

    char const* tzid_ = nullptr;
    if (!itt.is_utc) {
        if (itt.zone) {
            tzid_ = icaltimezone_get_tzid(const_cast<icaltimezone *>(itt.zone));
        } else {
            // Need to get the tzid param. Unfortunatly, libical tends to return raw
            // ics strings, with quotes and everything. That's not what we want. Need
            // to work around.
            icalparameter * const tzparam = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
            if (tzparam) {
                tzid_ = icalparameter_get_xvalue(tzparam);
            }
        }
    }

    nsCOMPtr<calITimezone> tz;
    if (tzid_) {
        nsDependentCString const tzid(tzid_);
        calIcalComponent * comp = nullptr;
        if (parent) {
            comp = parent->getParentVCalendarOrThis();
        }
        // look up parent if timezone is already referenced:
        if (comp) {
            comp->mReferencedTimezones.Get(tzid, getter_AddRefs(tz));
        }
        if (!tz) {
            if (parent) {
                // passed tz provider has precedence over timezone service:
                calITimezoneProvider * const tzProvider = parent->getTzProvider();
                if (tzProvider) {
                    tzProvider->GetTimezone(tzid, getter_AddRefs(tz));
                    NS_ASSERTION(tz, tzid_);
                }
            }
            if (!tz) {
                // look up tz in tz service.
                // this hides errors from incorrect ics files, which could state
                // a TZID that is not present in the ics file.
                // The other way round, it makes this product more error tolerant.
                nsresult rv = cal::getTimezoneService()->GetTimezone(tzid, getter_AddRefs(tz));

                if (NS_FAILED(rv) || !tz) {
                    icaltimezone const* zone = itt.zone;
                    if (!zone && comp) {
                        // look up parent VCALENDAR for VTIMEZONE:
                        zone = icalcomponent_get_timezone(comp->mComponent, tzid_);
                        NS_ASSERTION(zone, tzid_);
                    }
                    if (zone) {
                        // We need to decouple this (inner) VTIMEZONE from the parent VCALENDAR to avoid
                        // running into circular references (referenced timezones):
                        icaltimezone * const clonedZone = icaltimezone_new();
                        CAL_ENSURE_MEMORY(clonedZone);
                        icalcomponent * const clonedZoneComp =
                            icalcomponent_new_clone(icaltimezone_get_component(const_cast<icaltimezone *>(zone)));
                        if (!clonedZoneComp) {
                            icaltimezone_free(clonedZone, 1 /* free struct */);
                            CAL_ENSURE_MEMORY(clonedZoneComp);
                        }
                        if (!icaltimezone_set_component(clonedZone, clonedZoneComp)) {
                            icaltimezone_free(clonedZone, 1 /* free struct */);
                            return NS_ERROR_INVALID_ARG;
                        }
                        nsCOMPtr<calIIcalComponent> const tzComp(new calIcalComponent(clonedZone, clonedZoneComp));
                        CAL_ENSURE_MEMORY(tzComp);
                        tz = new calTimezone(tzid, tzComp);
                        CAL_ENSURE_MEMORY(tz);
                    } else { // install phantom timezone, so the data could be repaired:
                        tz = new calTimezone(tzid, nullptr);
                        CAL_ENSURE_MEMORY(tz);
                    }
                }
            }
            if (comp && tz) {
                // assure timezone is known:
                comp->AddTimezoneReference(tz);
            }
        }
        if (tz) {
            // correct itt which would else appear floating:
            itt.zone = cal::getIcalTimezone(tz);
            itt.is_utc = 0;
        } else {
            cal::logMissingTimezone(tzid_);
        }
    }
    *dtp = new calDateTime(&itt, tz);
    CAL_ENSURE_MEMORY(*dtp);
    NS_ADDREF(*dtp);
    return NS_OK;
}
Example #3
0
icalerrorenum icaldirset_add_component(icalset* set, icalcomponent* comp)
{
    char clustername[ICAL_PATH_MAX];
    icalproperty *dt = 0;
    icalvalue *v;
    struct icaltimetype tm;
    icalerrorenum error = ICAL_NO_ERROR;
    icalcomponent *inner;
    icaldirset *dset = (icaldirset*) set;

    icalerror_check_arg_rz( (dset!=0), "dset");
    icalerror_check_arg_rz( (comp!=0), "comp");

    icaldirset_add_uid(comp);

    /* Determine which cluster this object belongs in. This is a HACK */

    for(inner = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT);
	inner != 0;
	inner = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){
  
	dt = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY);
 	
      if (dt != 0)
	    break; 
	}	

    if (dt == 0) {
	for(inner = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT);
	    inner != 0;
	    inner = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){
	    
	    dt = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY);
	    
	  if (dt != 0)
		break; 
	    }	
	}

    if (dt == 0){
	icalerror_warn("The component does not have a DTSTAMP or DTSTART property, so it cannot be added to the store");
	icalerror_set_errno(ICAL_BADARG_ERROR);
	return ICAL_BADARG_ERROR;
    }

    v = icalproperty_get_value(dt);
    tm = icalvalue_get_datetime(v);

    snprintf(clustername,ICAL_PATH_MAX,"%s/%04d%02d",dset->dir, tm.year, tm.month);

    /* Load the cluster and insert the object */
    if(dset->cluster != 0 && 
       strcmp(clustername,icalcluster_key(dset->cluster)) != 0 ){
      icalcluster_free(dset->cluster);
      dset->cluster = 0;
    }

    if (dset->cluster == 0){
      dset->cluster = icalfileset_produce_icalcluster(clustername);

      if (dset->cluster == 0){
	    error = icalerrno;
	}
    }
    
    if (error != ICAL_NO_ERROR){
	icalerror_set_errno(error);
	return error;
    }

    /* Add the component to the cluster */
    icalcluster_add_component(dset->cluster,comp);
    
    /* icalcluster_mark(impl->cluster); */

    return ICAL_NO_ERROR;    
}
Example #4
0
/*
 * Construct the proper JSON object for an iCalendar value.
 */
static json_t *icalvalue_as_json_object(const icalvalue *value)
{
    const char *str = NULL;
    json_t *obj;

    switch (icalvalue_isa(value)) {
    case ICAL_BOOLEAN_VALUE:
        return json_boolean(icalvalue_get_integer(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);
        else
            str = icalperiodtype_as_json_string(dtp.period);
        break;
    }

    case ICAL_FLOAT_VALUE:
        return json_real(icalvalue_get_float(value));

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

        obj = json_array();
        json_array_append_new(obj, json_real(geo.lat));
        json_array_append_new(obj, json_real(geo.lon));
        return obj;
    }

    case ICAL_INTEGER_VALUE:
        return json_integer(icalvalue_get_integer(value));

    case ICAL_PERIOD_VALUE:
        str = icalperiodtype_as_json_string(icalvalue_get_period(value));
        break;

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

        obj = json_object();
        icalrecurrencetype_add_as_xxx(&recur, obj,
                                      &icalrecur_add_int_to_json_object,
                                      &icalrecur_add_string_to_json_object);
        return obj;
    }

    case ICAL_REQUESTSTATUS_VALUE:
        return
            icalreqstattype_as_json_array(icalvalue_get_requeststatus(value));

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

    return (str ? json_string(str) : NULL);
}
Example #5
0
void parse_iCal(icalcomponent* comp)
{
  icalcomponent * c;
  icalproperty * rrule;
  icalproperty * exdate;

  icalrecur_iterator * data;
  struct icaldurationtype offset;
  struct icaltimetype time_start;
  struct icaltimetype time_end;
  struct icaltimetype time_next;
  struct icaltimetype exdatetime;
  struct icaltimetype now;
  struct icalrecurrencetype recur;
  int i = 0;
  double duration;

  // Get offset:
  time_t t = time(NULL);
  struct tm lt = {0};
  localtime_r(&t, &lt);
  if (debug_flag)
  {
    printf("Offset to GMT is %lds.\n", lt.tm_gmtoff);
  }
  offset.days = 0;
  offset.weeks = 0;
  offset.hours = 0;
  offset.minutes = 0;
  offset.seconds = 0;
  offset.hours = lt.tm_gmtoff / 3600;
  if (lt.tm_gmtoff < 0) {
   offset.is_neg = 1;
  } else {
   offset.is_neg = 0;
  }

  // Get time now:
  now = icaltime_today();

  // Read each event:
  for (c = icalcomponent_get_first_component(comp,ICAL_VEVENT_COMPONENT) ;
       c != 0 ;
       c = icalcomponent_get_next_component(comp,ICAL_VEVENT_COMPONENT)
  )
  {
    // Get details about the event:
    const char * summary = icalcomponent_get_summary(c);
    const char * description = icalcomponent_get_description(c);

    // Help:
    if (debug_flag)
    {
      if (summary != NULL)
      {
        printf("summary: %s\n", summary);
      }
      if (description != NULL)
      {
        printf("description: %s\n", description);
      }
    }

    // Ranging time:
    time_start = icalcomponent_get_dtstart (c);
    time_end = icalcomponent_get_dtend (c);
    duration = difftime(icaltime_as_timet(time_end), icaltime_as_timet(time_start));

    // Rules:
    rrule = icalcomponent_get_first_property(c,ICAL_RRULE_PROPERTY);
    recur = icalproperty_get_rrule(rrule);
    data = icalrecur_iterator_new (recur, time_start);

    // Find next event:
    while (1)
    {
      time_next = icalrecur_iterator_next (data);

      if (icaltime_is_null_time(time_next) == 1) break;
      if (icaltime_compare(time_next, now) >= 0) break;
    }

    // Help:
    if (debug_flag)
    {
      dump_icaltimetype("time start", time_start);
      dump_icaltimetype("time end", time_end);
      dump_icaltimetype("until", recur.until);
      dump_icaltimetype("time next", time_next);
    }

    // One shot event:
    if (
      icaltime_is_null_time(time_next) == 1
      &&
      icaltime_compare(time_start, now) < 0
    )
    {
      if (debug_flag) printf ("event (one shot) is in the past\n");
      continue;
    }

    // Old event: discard recurent events finished before today...
    if (
      icaltime_is_null_time(recur.until) == 0
      &&
      icaltime_compare(recur.until, now) < 0
    )
    {
      if (debug_flag) printf ("event is recurent in the past ...\n");
      continue;
    }

    // Some help:
    if (debug_flag > 2)
    {
      dump_icalrecurrencetype(recur);
    }


    // Set time and hours:
    struct icaltimetype local_time_start = icaltime_add(time_start, offset);
    printf ("%d	%d	", local_time_start.minute, local_time_start.hour);

    // Set option depending of recurence:
    switch (recur.freq)
    {
      // Weekly: OK but need to remove days not needed... ?
      case ICAL_WEEKLY_RECURRENCE:
        printf ("%s", "*	*	");
        for (i = 0; recur.by_day[i] != 32639; i++)
        {
          printf ("%02d", icalrecurrencetype_day_day_of_week(recur.by_day[i]) -1);
          if (recur.by_day[i+1] != 32639)
          {
            printf ("%s", ",");
          }
        }
        printf ("%s", "	");
        break;

      // Happening each month:
      case ICAL_MONTHLY_RECURRENCE:
        // The Xth of the month:
        if (recur.by_month_day[0] != 32639)
        {
          printf ("%02d	*	*	", recur.by_month_day[0]);
        }

        // Day of the week:
        else
        {
            printf ("%d	%d	*	", time_next.day, time_next.month);
        }
        break;


      // Event happening each year ...  OK???
      // OK: one shoot.
      case ICAL_YEARLY_RECURRENCE:
      case ICAL_NO_RECURRENCE:
      default:
        printf ("%02d	%02d	*	", 
          local_time_start.day,
          local_time_start.month
        );
    }



    // How many valid exclude dates:
    exdate = icalcomponent_get_first_property(c, ICAL_EXDATE_PROPERTY);
    unsigned int num_ex = 0;
    if (exdate != NULL)
    {
      for (; exdate != NULL; exdate = icalcomponent_get_next_property(c, ICAL_EXDATE_PROPERTY) )
      {
        exdatetime = icalvalue_get_datetime(icalproperty_get_value(exdate));
        if (icaltime_compare(exdatetime, now) >= 0)
        {
          num_ex++;
        }
      }
    }
    if (num_ex > 0)
    {
      exdate = icalcomponent_get_first_property(c, ICAL_EXDATE_PROPERTY);
      for (; exdate != NULL; exdate = icalcomponent_get_next_property(c, ICAL_EXDATE_PROPERTY) )
      {
        exdatetime = icalvalue_get_datetime(icalproperty_get_value(exdate));
        if (icaltime_compare(exdatetime, now) >= 0)
        {
          struct icaltimetype local_exdatetime = icaltime_add(exdatetime, offset);
          printf ("%s", "[ \"$(date \"+\\\%Y\\\%m\\\%d\")\" = \"");
          printf ("%04d%02d%02d", local_exdatetime.year, local_exdatetime.month, local_exdatetime.day);
          printf ("%s", "\" ] || ");
        }
      }
    }

    // And the action:
    printf ("%s %.0f\n", 
      summary,
      duration
    );

    icalrecur_iterator_free (data);
  }
}