/** * get parameters from the icalendar property and store them in the internal * struct if the parameter describes a hidden or inline attachment. */ static void add_e_attachment_parameters(icalproperty *prop, I_common *i_common, gboolean inln) { gboolean binary = FALSE; gchar* mime_type = NULL; gchar* label = NULL; /* iterate over all parameters of the attachment property */ int i, pc = icalproperty_count_parameters(prop); icalparameter *para; for (i = 0; i < pc; i++) { icalparameter_kind kind; icalparameter_value xvalue; para = i == 0 ? icalproperty_get_first_parameter(prop, ICAL_ANY_PARAMETER) : icalproperty_get_next_parameter(prop, ICAL_ANY_PARAMETER); kind = icalparameter_isa(para); xvalue = icalparameter_get_value(para); if (kind == ICAL_VALUE_PARAMETER && xvalue == ICAL_VALUE_BINARY) binary = TRUE; /* not a link attachment */ else if (kind == ICAL_FMTTYPE_PARAMETER) /* found mime type */ mime_type = (gchar*) icalparameter_get_xvalue(para); else if (xvalue == ICAL_VALUE_X) { /* found attachment name */ const char* name = icalparameter_get_xname(para); const char* value = icalparameter_get_xvalue(para); if (name && strcmp(name, ICONTACT_KOLAB_STORE_ATTACHMENT_NAME) == 0) label = (gchar*) value; } } if (binary) { /* if not a linked attachment add data to struct */ Kolab_conv_mail_part *mpart = g_new0(Kolab_conv_mail_part, 1); gchar* pname = NULL; if (label != NULL) { if (inln) i_common->inline_attachment_names = g_list_append( i_common->inline_attachment_names, strdup(label)); mpart->name = strdup(label); } if (mime_type != NULL) mpart->mime_type = strdup(mime_type); /* add data and length */ pname = (gchar*) icalproperty_get_value_as_string(prop); if (pname) { gsize outlen; mpart->data = (gchar*) g_base64_decode (pname, &outlen); mpart->length = outlen; /* add created mail part to the attachment list */ i_common->kolab_attachment_store = g_list_append(i_common->kolab_attachment_store, mpart); } } }
NS_IMETHODIMP calIcalProperty::GetParameter(const nsACString ¶m, nsACString &value) { // More ridiculous parameter/X-PARAMETER handling. icalparameter_kind paramkind = icalparameter_string_to_kind(PromiseFlatCString(param).get()); if (paramkind == ICAL_NO_PARAMETER) return NS_ERROR_INVALID_ARG; const char *icalstr = nullptr; if (paramkind == ICAL_X_PARAMETER) { icalparameter *icalparam = FindParameter(mProperty, param, ICAL_X_PARAMETER); if (icalparam) icalstr = icalparameter_get_xvalue(icalparam); } else if (paramkind == ICAL_IANA_PARAMETER) { icalparameter *icalparam = FindParameter(mProperty, param, ICAL_IANA_PARAMETER); if (icalparam) icalstr = icalparameter_get_iana_value(icalparam); } else { icalstr = icalproperty_get_parameter_as_string(mProperty, PromiseFlatCString(param).get()); } if (!icalstr) { value.Truncate(); value.SetIsVoid(true); } else { value.Assign(icalstr); } return NS_OK; }
/* * Add an iCalendar parameter to an existing JSON object. */ static void icalparameter_as_json_object_member(icalparameter *param, json_t *jparams) { icalparameter_kind kind; const char *kind_string, *value_string; kind = icalparameter_isa(param); switch (kind) { case ICAL_X_PARAMETER: kind_string = icalparameter_get_xname(param); break; #ifdef HAVE_IANA_PARAMS case ICAL_IANA_PARAMETER: kind_string = icalparameter_get_iana_name(param); break; #endif default: kind_string = icalparameter_kind_to_string(kind); if (kind_string) break; case ICAL_NO_PARAMETER: case ICAL_ANY_PARAMETER: icalerror_set_errno(ICAL_BADARG_ERROR); return; } /* XXX Need to handle multi-valued parameters */ value_string = icalparameter_get_xvalue(param); if (!value_string) { icalparameter_value value = icalparameter_get_value(param); if (value) value_string = icalparameter_enum_to_string(value); } if (!value_string) return; json_object_set_new(jparams, lcase(icalmemory_tmp_copy(kind_string)), json_string(value_string)); }
/* * Construct an XML element for an iCalendar parameter. */ static xmlNodePtr icalparameter_as_xml_element(icalparameter *param) { icalparameter_kind kind; icalparameter_value value; const char *kind_string, *type_string, *value_string; xmlNodePtr xparam; kind = icalparameter_isa(param); switch (kind) { case ICAL_X_PARAMETER: kind_string = icalparameter_get_xname(param); break; #ifdef HAVE_IANA_PARAMS case ICAL_IANA_PARAMETER: kind_string = icalparameter_get_iana_name(param); break; #endif default: kind_string = icalparameter_kind_to_string(kind); if (kind_string) break; case ICAL_NO_PARAMETER: case ICAL_ANY_PARAMETER: icalerror_set_errno(ICAL_BADARG_ERROR); return NULL; } /* Get value type */ switch (kind) { case ICAL_ALTREP_PARAMETER: case ICAL_DIR_PARAMETER: type_string = "uri"; break; case ICAL_DELEGATEDFROM_PARAMETER: case ICAL_DELEGATEDTO_PARAMETER: case ICAL_MEMBER_PARAMETER: case ICAL_SENTBY_PARAMETER: type_string = "cal-address"; break; case ICAL_RSVP_PARAMETER: type_string = "boolean"; break; default: type_string = "text"; break; } /* XXX Need to handle multi-valued parameters */ value = icalparameter_get_value(param); if (value == ICAL_VALUE_X) value_string = icalparameter_get_xvalue(param); else value_string = icalparameter_enum_to_string(value); if (!value_string) return NULL; xparam = xmlNewNode(NULL, BAD_CAST lcase(icalmemory_tmp_copy(kind_string))); xmlNewTextChild(xparam, NULL, BAD_CAST type_string, BAD_CAST value_string); return xparam; }
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; }