NS_IMETHODIMP calIcalComponent::GetNextProperty(const nsACString &kind, calIIcalProperty **prop) { NS_ENSURE_ARG_POINTER(prop); icalproperty_kind propkind = icalproperty_string_to_kind(PromiseFlatCString(kind).get()); if (propkind == ICAL_NO_PROPERTY) return NS_ERROR_INVALID_ARG; icalproperty *icalprop = nullptr; if (propkind == ICAL_X_PROPERTY) { for (icalprop = icalcomponent_get_next_property(mComponent, ICAL_X_PROPERTY); icalprop; icalprop = icalcomponent_get_next_property(mComponent, ICAL_X_PROPERTY)) { if (kind.Equals(icalproperty_get_x_name(icalprop))) break; } } else { icalprop = icalcomponent_get_next_property(mComponent, propkind); } if (!icalprop) { *prop = nullptr; return NS_OK; } *prop = new calIcalProperty(icalprop, this); CAL_ENSURE_MEMORY(*prop); NS_ADDREF(*prop); return NS_OK; }
NS_IMETHODIMP calIcalComponent::GetNextSubcomponent(const nsACString& kind, calIIcalComponent **subcomp) { NS_ENSURE_ARG_POINTER(subcomp); icalcomponent_kind compkind = icalcomponent_string_to_kind(PromiseFlatCString(kind).get()); // Maybe someday I'll support X-COMPONENTs if (compkind == ICAL_NO_COMPONENT || compkind == ICAL_X_COMPONENT) return NS_ERROR_INVALID_ARG; icalcomponent *ical = icalcomponent_get_next_component(mComponent, compkind); if (!ical) { *subcomp = nullptr; return NS_OK; } *subcomp = new calIcalComponent(ical, this); CAL_ENSURE_MEMORY(*subcomp); NS_ADDREF(*subcomp); return NS_OK; }
NS_IMETHODIMP calIcalComponent::GetReferencedTimezones(uint32_t * aCount, calITimezone *** aTimezones) { NS_ENSURE_ARG_POINTER(aCount); NS_ENSURE_ARG_POINTER(aTimezones); uint32_t const count = mReferencedTimezones.Count(); if (count == 0) { *aCount = 0; *aTimezones = nullptr; return NS_OK; } calITimezone ** const timezones = static_cast<calITimezone **>( moz_xmalloc(sizeof(calITimezone *) * count)); CAL_ENSURE_MEMORY(timezones); // tzptr will get used as an iterator by the enumerator function calITimezone ** tzptr = timezones; for (auto iter = mReferencedTimezones.ConstIter(); !iter.Done(); iter.Next() ) { NS_ADDREF(*tzptr = iter.Data()); ++tzptr; } *aTimezones = timezones; *aCount = count; return NS_OK; }
/* readonly attribute string className; */ NS_IMETHODIMP calDateTime::GetClassName(char ** aClassName) { NS_ENSURE_ARG_POINTER(aClassName); *aClassName = static_cast<char *>(nsMemory::Clone(CAL_STRLEN_ARGS("calDateTime") +1)); CAL_ENSURE_MEMORY(*aClassName); return NS_OK; }
NS_IMETHODIMP calDateTime::Clone(calIDateTime **aResult) { NS_ENSURE_ARG_POINTER(aResult); icaltimetype itt; ToIcalTime(&itt); calDateTime * const cdt = new calDateTime(&itt, mTimezone); CAL_ENSURE_MEMORY(cdt); NS_ADDREF(*aResult = cdt); return NS_OK; }
NS_IMETHODIMP calDateTime::GetIcalString(nsACString& aResult) { icaltimetype t; ToIcalTime(&t); // note that ics is owned by libical, so we don't need to free char const * const ics = icaltime_as_ical_string(t); CAL_ENSURE_MEMORY(ics); aResult.Assign(ics); return NS_OK; }
NS_IMETHODIMP calICSService::CreateIcalPropertyFromString(const nsACString &str, calIIcalProperty **prop) { NS_ENSURE_ARG_POINTER(prop); icalproperty *icalprop = icalproperty_new_from_string(PromiseFlatCString(str).get()); *prop = new calIcalProperty(icalprop, nullptr); CAL_ENSURE_MEMORY(*prop); NS_ADDREF(*prop); return NS_OK; }
nsresult calIcalProperty::setDatetime_(calIcalComponent * parent, icalproperty * prop, calIDateTime * dt) { NS_ENSURE_ARG_POINTER(prop); NS_ENSURE_ARG_POINTER(dt); nsresult rv; nsCOMPtr<calIDateTimeLibical> icaldt = do_QueryInterface(dt, &rv); NS_ENSURE_SUCCESS(rv, rv); icaltimetype itt; icaldt->ToIcalTime(&itt); if (parent) { if (!itt.is_utc) { nsCOMPtr<calITimezone> tz; rv = dt->GetTimezone(getter_AddRefs(tz)); NS_ENSURE_SUCCESS(rv, rv); if (itt.zone) { rv = parent->getParentVCalendarOrThis()->AddTimezoneReference(tz); NS_ENSURE_SUCCESS(rv, rv); icalparameter * const param = icalparameter_new_from_value_string( ICAL_TZID_PARAMETER, icaltimezone_get_tzid(const_cast<icaltimezone *>(itt.zone))); icalproperty_set_parameter(prop, param); } else { // either floating or phantom: bool b = false; if (NS_FAILED(tz->GetIsFloating(&b)) || !b) { // restore the same phantom TZID: nsAutoCString tzid; rv = tz->GetTzid(tzid); NS_ENSURE_SUCCESS(rv, rv); icalparameter * const param = icalparameter_new_from_value_string(ICAL_TZID_PARAMETER, tzid.get()); icalproperty_set_parameter(prop, param); } } } } else if (!itt.is_date && !itt.is_utc && itt.zone) { // no parent to add the CTIMEZONE to: coerce DATETIMEs to UTC, DATEs to floating icaltimezone_convert_time(&itt, const_cast<icaltimezone *>(itt.zone), icaltimezone_get_utc_timezone()); itt.zone = icaltimezone_get_utc_timezone(); itt.is_utc = 1; } icalvalue * const val = icalvalue_new_datetime(itt); CAL_ENSURE_MEMORY(val); icalproperty_set_value(prop, val); return NS_OK; }
NS_IMETHODIMP calRecurrenceRule::Clone(calIRecurrenceItem **aResult) { calRecurrenceRule * const crc = new calRecurrenceRule(); CAL_ENSURE_MEMORY(crc); crc->mIsNegative = mIsNegative; crc->mIsByCount = mIsByCount; crc->mIcalRecur = mIcalRecur; NS_ADDREF(*aResult = crc); return NS_OK; }
NS_IMETHODIMP calDateTime::GetEndOfMonth(calIDateTime ** aResult) { NS_ENSURE_ARG_POINTER(aResult); icaltimetype icalt; ToIcalTime(&icalt); icalt.day = icaltime_days_in_month(icalt.month, icalt.year); icalt.is_date = 1; calDateTime * const cdt = new calDateTime(&icalt, mTimezone); CAL_ENSURE_MEMORY(cdt); NS_ADDREF(*aResult = cdt); return NS_OK; }
NS_IMETHODIMP calDateTime::GetStartOfMonth(calIDateTime ** aResult) { NS_ENSURE_ARG_POINTER(aResult); ensureTimezone(); icaltimetype icalt; ToIcalTime(&icalt); icalt.day = 1; icalt.is_date = 1; calDateTime * const cdt = new calDateTime(&icalt, mTimezone); CAL_ENSURE_MEMORY(cdt); NS_ADDREF(*aResult = cdt); return NS_OK; }
NS_IMETHODIMP calDateTime::GetEndOfWeek(calIDateTime ** aResult) { NS_ENSURE_ARG_POINTER(aResult); icaltimetype icalt; ToIcalTime(&icalt); int day_of_week = icaltime_day_of_week(icalt); if (day_of_week < 7) icaltime_adjust(&icalt, 7 - day_of_week, 0, 0, 0); icalt.is_date = 1; calDateTime * const cdt = new calDateTime(&icalt, mTimezone); CAL_ENSURE_MEMORY(cdt); NS_ADDREF(*aResult = cdt); return NS_OK; }
nsresult calIcalComponent::SetDateTimeAttribute(icalproperty_kind kind, calIDateTime * dt) { ClearAllProperties(kind); bool isValid; if (!dt || NS_FAILED(dt->GetIsValid(&isValid)) || !isValid) { return NS_OK; } icalproperty *prop = icalproperty_new(kind); CAL_ENSURE_MEMORY(prop); nsresult rc = calIcalProperty::setDatetime_(this, prop, dt); if (NS_SUCCEEDED(rc)) icalcomponent_add_property(mComponent, prop); else icalproperty_free(prop); return rc; }
NS_IMETHODIMP calDateTime::SubtractDate(calIDateTime *aDate, calIDuration **aDuration) { NS_ENSURE_ARG_POINTER(aDate); NS_ENSURE_ARG_POINTER(aDuration); // same as icaltime_subtract(), but minding timezones: PRTime t2t; aDate->GetNativeTime(&t2t); // for a duration, need to convert the difference in microseconds (prtime) // to seconds (libical), so divide by one million. icaldurationtype const idt = icaldurationtype_from_int( static_cast<int>((mNativeTime - t2t) / int64_t(PR_USEC_PER_SEC))); calDuration * const dur = new calDuration(&idt); CAL_ENSURE_MEMORY(dur); NS_ADDREF(*aDuration = dur); return NS_OK; }
NS_IMETHODIMP calICSService::CreateIcalProperty(const nsACString &kind, calIIcalProperty **prop) { NS_ENSURE_ARG_POINTER(prop); icalproperty_kind propkind = icalproperty_string_to_kind(PromiseFlatCString(kind).get()); if (propkind == ICAL_NO_PROPERTY) return NS_ERROR_INVALID_ARG; icalproperty *icalprop = icalproperty_new(propkind); if (!icalprop) return NS_ERROR_OUT_OF_MEMORY; // XXX translate if (propkind == ICAL_X_PROPERTY) icalproperty_set_x_name(icalprop, PromiseFlatCString(kind).get()); *prop = new calIcalProperty(icalprop, nullptr); CAL_ENSURE_MEMORY(*prop); NS_ADDREF(*prop); return NS_OK; }
NS_IMETHODIMP calDateTime::GetInTimezone(calITimezone * aTimezone, calIDateTime ** aResult) { NS_ENSURE_ARG_POINTER(aTimezone); NS_ENSURE_ARG_POINTER(aResult); if (mIsDate) { // if it's a date, we really just want to make a copy of this // and set the timezone. nsresult rv = Clone(aResult); if (NS_SUCCEEDED(rv)) { rv = (*aResult)->SetTimezone(aTimezone); } return rv; } else { icaltimetype icalt; ToIcalTime(&icalt); icaltimezone * tz = cal::getIcalTimezone(aTimezone); if (icalt.zone == tz) { return Clone(aResult); } /* If there's a zone, we need to convert; otherwise, we just * assign, since this item is floating */ if (icalt.zone && tz) { icaltimezone_convert_time(&icalt, const_cast<icaltimezone *>(icalt.zone), tz); } icalt.zone = tz; icalt.is_utc = (tz && tz == icaltimezone_get_utc_timezone()); calDateTime * cdt = new calDateTime(&icalt, aTimezone); CAL_ENSURE_MEMORY(cdt); NS_ADDREF (*aResult = cdt); return NS_OK; } }
NS_IMETHODIMP calIcalComponent::GetReferencedTimezones(uint32_t * aCount, calITimezone *** aTimezones) { NS_ENSURE_ARG_POINTER(aCount); NS_ENSURE_ARG_POINTER(aTimezones); uint32_t const count = mReferencedTimezones.Count(); if (count == 0) { *aCount = 0; *aTimezones = nullptr; return NS_OK; } calITimezone ** const timezones = static_cast<calITimezone **>( nsMemory::Alloc(sizeof(calITimezone *) * count)); CAL_ENSURE_MEMORY(timezones); // tzptr will get used as an iterator by the enumerator function calITimezone ** tzptr = timezones; mReferencedTimezones.EnumerateRead(TimezoneHashToTimezoneArray, &tzptr); *aTimezones = timezones; *aCount = count; return NS_OK; }
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; }