32 #include <libical/ical.h> 33 #include <ne_session.h> 35 #include <ne_request.h> 37 #include <ne_redirect.h> 52 .description =
"iCalendar .ics calendars",
76 ne_session_destroy(pvt->
session);
79 icalcomponent_free(pvt->
data);
81 ne_uri_free(&pvt->
uri);
105 memcpy(tmp, block, len);
122 ne_strnzcpy(username, pvt->
user, NE_ABUFSIZ);
123 ne_strnzcpy(secret, pvt->
secret, NE_ABUFSIZ);
133 icalcomponent *comp =
NULL;
145 req = ne_request_create(pvt->
session,
"GET", pvt->
uri.path);
148 ret = ne_request_dispatch(req);
149 ne_request_destroy(req);
170 tm.
tm_mon = time.month - 1;
194 icaltimezone *utc = icaltimezone_get_utc_timezone();
196 icalcomponent *valarm;
198 struct icaltriggertype trigger;
200 if (!(pvt && pvt->
owner)) {
210 start = icalcomponent_get_dtstart(comp);
211 end = icalcomponent_get_dtend(comp);
217 if ((prop = icalcomponent_get_first_property(comp, ICAL_SUMMARY_PROPERTY))) {
221 if ((prop = icalcomponent_get_first_property(comp, ICAL_DESCRIPTION_PROPERTY))) {
225 if ((prop = icalcomponent_get_first_property(comp, ICAL_ORGANIZER_PROPERTY))) {
229 if ((prop = icalcomponent_get_first_property(comp, ICAL_LOCATION_PROPERTY))) {
233 if ((prop = icalcomponent_get_first_property(comp, ICAL_CATEGORIES_PROPERTY))) {
237 if ((prop = icalcomponent_get_first_property(comp, ICAL_PRIORITY_PROPERTY))) {
238 event->priority = icalvalue_get_integer(icalproperty_get_value(prop));
241 if ((prop = icalcomponent_get_first_property(comp, ICAL_UID_PROPERTY))) {
244 ast_log(
LOG_WARNING,
"No UID found, but one is required. Generating, but updates may not be acurate\n");
249 snprintf(tmp,
sizeof(tmp),
"%ld", event->
start);
261 if (icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY)
262 || icalcomponent_get_first_property(comp, ICAL_RDATE_PROPERTY)) {
263 icalcompiter comp_iter;
264 icaltimetype span_start = icaltime_from_timet_with_zone(
265 event->
start, icaltime_is_date(start), icaltime_get_timezone(start));
267 icaltime_set_timezone(&span_start, icaltime_get_timezone(start));
268 for (comp_iter = icalcomponent_begin_component(pvt->
data, ICAL_VEVENT_COMPONENT);
269 icalcompiter_deref(&comp_iter);
270 icalcompiter_next(&comp_iter)) {
271 icalcomponent *vevent = icalcompiter_deref(&comp_iter);
272 icalproperty *uid = icalcomponent_get_first_property(vevent, ICAL_UID_PROPERTY);
274 if (uid && !strcmp(icalproperty_get_value_as_string(uid), event->
uid)) {
275 icaltimetype recurrence_id = icalcomponent_get_recurrenceid(vevent);
278 icaltime_set_timezone(&recurrence_id, icaltime_get_timezone(start));
280 if (!icaltime_compare(recurrence_id, span_start)
281 && icaltime_is_date(span_start) == icaltime_is_date(recurrence_id)) {
290 for (prop = icalcomponent_get_first_property(comp, ICAL_ATTENDEE_PROPERTY);
291 prop; prop = icalcomponent_get_next_property(comp, ICAL_ATTENDEE_PROPERTY)) {
295 if (!(attendee =
ast_calloc(1,
sizeof(*attendee)))) {
299 data = icalproperty_get_attendee(prop);
312 if (!(valarm = icalcomponent_get_first_component(comp, ICAL_VALARM_COMPONENT))) {
318 if (!(prop = icalcomponent_get_first_property(valarm, ICAL_TRIGGER_PROPERTY))) {
325 trigger = icalproperty_get_trigger(prop);
327 if (icaltriggertype_is_null_trigger(trigger)) {
334 if (!icaltime_is_null_time(trigger.time)) {
335 tmp = icaltime_convert_to_zone(trigger.time, utc);
336 event->alarm = icaltime_as_timet_with_zone(tmp, utc);
340 tmp = icaltime_add(start, trigger.duration);
341 event->alarm = icaltime_as_timet_with_zone(tmp, icaltime_get_timezone(start));
352 struct icaltimetype start_time, end_time;
370 start_time = icaltime_current_time_with_zone(icaltimezone_get_utc_timezone());
371 end_time = icaltime_current_time_with_zone(icaltimezone_get_utc_timezone());
373 end_time = icaltime_normalize(end_time);
375 for (iter = icalcomponent_get_first_component(pvt->
data, ICAL_VEVENT_COMPONENT);
377 iter = icalcomponent_get_next_component(pvt->
data, ICAL_VEVENT_COMPONENT))
394 ast_log(
LOG_ERROR,
"You must enable calendar support for res_icalendar to load\n");
416 ast_log(
LOG_ERROR,
"Could not allocate space for fetching events for calendar: %s\n", cal->
name);
432 if (!strcasecmp(v->
name,
"url")) {
434 }
else if (!strcasecmp(v->
name,
"user")) {
436 }
else if (!strcasecmp(v->
name,
"secret")) {
458 pvt->
uri.scheme =
"http";
461 if (pvt->
uri.port == 0) {
462 pvt->
uri.port = ne_uri_defaultport(pvt->
uri.scheme);
465 pvt->
session = ne_session_create(pvt->
uri.scheme, pvt->
uri.host, pvt->
uri.port);
466 ne_redirect_register(pvt->
session);
468 if (!strcasecmp(pvt->
uri.scheme,
"https")) {
469 ne_ssl_trust_default_ca(pvt->
session);
488 struct timespec ts = {0,};
501 ast_debug(10,
"Skipping refresh since we got a shutdown signal\n");
509 icalcomponent_free(pvt->
data);
546 .requires =
"res_calendar",
struct ast_variable * next
static void * unref_icalendar(void *obj)
struct ast_calendar * owner
Asterisk locking-related definitions:
int ast_calendar_register(struct ast_calendar_tech *tech)
Register a new calendar technology.
Asterisk main include file. File version handling, generic pbx functions.
static icalcomponent * fetch_icalendar(struct icalendar_pvt *pvt)
const ast_string_field user
const ast_string_field secret
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static void * ical_load_calendar(void *data)
#define ao2_callback(c, flags, cb_fn, arg)
struct ast_calendar_attendee * next
static time_t icalfloat_to_timet(icaltimetype time)
Structure for variables, used for configurations and for channel variables.
static void icalendar_add_event(icalcomponent *comp, struct icaltime_span *span, void *data)
struct ao2_container * events
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
const ast_string_field uid
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define ast_mutex_lock(a)
#define ast_strdup(str)
A wrapper for strdup()
static struct ast_calendar_tech ical_tech
static void icalendar_update_events(struct icalendar_pvt *pvt)
#define ast_strlen_zero(foo)
void ast_calendar_merge_events(struct ast_calendar *cal, struct ao2_container *new_events)
Add an event to the list of events for a calendar.
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
static int fetch_response_reader(void *data, const char *block, size_t len)
static int auth_credentials(void *userdata, const char *realm, int attempts, char *username, char *secret)
static int load_module(void)
General Asterisk PBX channel definitions.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
struct ao2_container * ast_calendar_event_container_alloc(void)
Allocate an astobj2 container for ast_calendar_event objects.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ao2_ref(o, delta)
A general API for managing calendar events with Asterisk.
#define ast_malloc(len)
A wrapper for malloc()
const ast_string_field name
struct ast_calendar_event * ast_calendar_event_alloc(struct ast_calendar *cal)
Allocate an astobj2 ast_calendar_event object.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
struct association categories[]
static ast_mutex_t refreshlock
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field url
#define ao2_alloc(data_size, destructor_fn)
static void icalendar_destructor(void *obj)
#define ast_calloc(num, len)
A wrapper for calloc()
const struct ast_config * ast_calendar_config_acquire(void)
Grab and lock pointer to the calendar config (read only)
Module has failed to load, may be in an inconsistent state.
struct ast_calendar_event * ast_calendar_unref_event(struct ast_calendar_event *event)
Unreference an ast_calendar_event.
structure to hold users read from users.conf
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct ast_calendar_event::attendees attendees
void ast_calendar_unregister(struct ast_calendar_tech *tech)
Unregister a new calendar technology.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Individual calendaring technology data.
#define ast_mutex_init(pmutex)
Asterisk calendar structure.
void ast_calendar_config_release(void)
Release the calendar config.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
const ast_string_field summary
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
#define ast_cond_timedwait(cond, mutex, time)
Structure for mutex and tracking information.
static int unload_module(void)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
#define ast_mutex_unlock(a)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ao2_link(container, obj)