Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Functions | Variables
res_calendar_icalendar.c File Reference

Resource for handling iCalendar calendars. More...

#include "asterisk.h"
#include <libical/ical.h>
#include <ne_session.h>
#include <ne_uri.h>
#include <ne_request.h>
#include <ne_auth.h>
#include <ne_redirect.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/calendar.h"
#include "asterisk/lock.h"
#include "asterisk/config.h"
#include "asterisk/astobj2.h"
Include dependency graph for res_calendar_icalendar.c:

Go to the source code of this file.

Data Structures

struct  icalendar_pvt
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int auth_credentials (void *userdata, const char *realm, int attempts, char *username, char *secret)
 
static icalcomponent * fetch_icalendar (struct icalendar_pvt *pvt)
 
static int fetch_response_reader (void *data, const char *block, size_t len)
 
static void * ical_load_calendar (void *data)
 
static void icalendar_add_event (icalcomponent *comp, struct icaltime_span *span, void *data)
 
static void icalendar_destructor (void *obj)
 
static void icalendar_update_events (struct icalendar_pvt *pvt)
 
static time_t icalfloat_to_timet (icaltimetype time)
 
static int load_module (void)
 
static int unload_module (void)
 
static void * unref_icalendar (void *obj)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk iCalendar .ics file integration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PLUGIN, .requires = "res_calendar", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_calendar_tech ical_tech
 

Detailed Description

Resource for handling iCalendar calendars.

Definition in file res_calendar_icalendar.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 547 of file res_calendar_icalendar.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 547 of file res_calendar_icalendar.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 547 of file res_calendar_icalendar.c.

◆ auth_credentials()

static int auth_credentials ( void *  userdata,
const char *  realm,
int  attempts,
char *  username,
char *  secret 
)
static

Definition at line 113 of file res_calendar_icalendar.c.

References ast_log, LOG_WARNING, ast_calendar::name, icalendar_pvt::owner, icalendar_pvt::secret, and icalendar_pvt::user.

Referenced by ical_load_calendar().

114 {
115  struct icalendar_pvt *pvt = userdata;
116 
117  if (attempts > 1) {
118  ast_log(LOG_WARNING, "Invalid username or password for iCalendar '%s'\n", pvt->owner->name);
119  return -1;
120  }
121 
122  ne_strnzcpy(username, pvt->user, NE_ABUFSIZ);
123  ne_strnzcpy(secret, pvt->secret, NE_ABUFSIZ);
124 
125  return 0;
126 }
struct ast_calendar * owner
const ast_string_field user
const ast_string_field secret
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
const ast_string_field name
Definition: calendar.h:127

◆ fetch_icalendar()

static icalcomponent* fetch_icalendar ( struct icalendar_pvt pvt)
static

Definition at line 128 of file res_calendar_icalendar.c.

References ast_free, ast_log, ast_str_buffer(), ast_str_create, ast_str_strlen(), ast_strlen_zero, fetch_response_reader(), LOG_ERROR, LOG_WARNING, ast_calendar::name, NULL, icalendar_pvt::owner, icalendar_pvt::session, icalendar_pvt::uri, and icalendar_pvt::url.

Referenced by ical_load_calendar().

129 {
130  int ret;
131  struct ast_str *response;
132  ne_request *req;
133  icalcomponent *comp = NULL;
134 
135  if (!pvt) {
136  ast_log(LOG_ERROR, "There is no private!\n");
137  return NULL;
138  }
139 
140  if (!(response = ast_str_create(512))) {
141  ast_log(LOG_ERROR, "Could not allocate memory for response.\n");
142  return NULL;
143  }
144 
145  req = ne_request_create(pvt->session, "GET", pvt->uri.path);
146  ne_add_response_body_reader(req, ne_accept_2xx, fetch_response_reader, &response);
147 
148  ret = ne_request_dispatch(req);
149  ne_request_destroy(req);
150  if (ret != NE_OK || !ast_str_strlen(response)) {
151  ast_log(LOG_WARNING, "Unable to retrieve iCalendar '%s' from '%s': %s\n", pvt->owner->name, pvt->url, ne_get_error(pvt->session));
152  ast_free(response);
153  return NULL;
154  }
155 
156  if (!ast_strlen_zero(ast_str_buffer(response))) {
157  comp = icalparser_parse_string(ast_str_buffer(response));
158  }
159  ast_free(response);
160 
161  return comp;
162 }
struct ast_calendar * owner
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
static int fetch_response_reader(void *data, const char *block, size_t len)
const ast_string_field name
Definition: calendar.h:127
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
const ast_string_field url
#define ast_free(a)
Definition: astmm.h:182
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ fetch_response_reader()

static int fetch_response_reader ( void *  data,
const char *  block,
size_t  len 
)
static

Definition at line 97 of file res_calendar_icalendar.c.

References ast_free, ast_malloc, ast_str_append(), icalendar_pvt::data, len(), and tmp().

Referenced by fetch_icalendar().

98 {
99  struct ast_str **response = data;
100  unsigned char *tmp;
101 
102  if (!(tmp = ast_malloc(len + 1))) {
103  return -1;
104  }
105  memcpy(tmp, block, len);
106  tmp[len] = '\0';
107  ast_str_append(response, 0, "%s", tmp);
108  ast_free(tmp);
109 
110  return 0;
111 }
static int tmp()
Definition: bt_open.c:389
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_free(a)
Definition: astmm.h:182

◆ ical_load_calendar()

static void * ical_load_calendar ( void *  data)
static

Definition at line 385 of file res_calendar_icalendar.c.

References ao2_alloc, ao2_trylock, ao2_unlock, ast_calendar_config_acquire(), ast_calendar_config_release(), ast_calendar_event_container_alloc(), ast_cond_timedwait, ast_debug, ast_log, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_string_field_init, ast_string_field_set, ast_strlen_zero, ast_tvnow(), ast_variable_browse(), auth_credentials(), icalendar_pvt::data, icalendar_pvt::events, fetch_icalendar(), icalendar_destructor(), icalendar_update_events(), LOG_ERROR, LOG_WARNING, ast_variable::name, ast_calendar::name, ast_variable::next, NULL, icalendar_pvt::owner, ast_calendar::refresh, refreshlock, icalendar_pvt::secret, icalendar_pvt::session, ast_calendar::tech_pvt, ast_calendar::unload, ast_calendar::unloading, unref_icalendar(), icalendar_pvt::uri, icalendar_pvt::url, and ast_variable::value.

386 {
387  struct icalendar_pvt *pvt;
388  const struct ast_config *cfg;
389  struct ast_variable *v;
390  struct ast_calendar *cal = void_data;
392 
393  if (!(cal && (cfg = ast_calendar_config_acquire()))) {
394  ast_log(LOG_ERROR, "You must enable calendar support for res_icalendar to load\n");
395  return NULL;
396  }
397  if (ao2_trylock(cal)) {
398  if (cal->unloading) {
399  ast_log(LOG_WARNING, "Unloading module, load_calendar cancelled.\n");
400  } else {
401  ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
402  }
404  return NULL;
405  }
406 
407  if (!(pvt = ao2_alloc(sizeof(*pvt), icalendar_destructor))) {
408  ast_log(LOG_ERROR, "Could not allocate icalendar_pvt structure for calendar: %s\n", cal->name);
410  return NULL;
411  }
412 
413  pvt->owner = cal;
414 
415  if (!(pvt->events = ast_calendar_event_container_alloc())) {
416  ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
417  pvt = unref_icalendar(pvt);
418  ao2_unlock(cal);
420  return NULL;
421  }
422 
423  if (ast_string_field_init(pvt, 32)) {
424  ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
425  pvt = unref_icalendar(pvt);
426  ao2_unlock(cal);
428  return NULL;
429  }
430 
431  for (v = ast_variable_browse(cfg, cal->name); v; v = v->next) {
432  if (!strcasecmp(v->name, "url")) {
433  ast_string_field_set(pvt, url, v->value);
434  } else if (!strcasecmp(v->name, "user")) {
435  ast_string_field_set(pvt, user, v->value);
436  } else if (!strcasecmp(v->name, "secret")) {
437  ast_string_field_set(pvt, secret, v->value);
438  }
439  }
440 
442 
443  if (ast_strlen_zero(pvt->url)) {
444  ast_log(LOG_WARNING, "No URL was specified for iCalendar '%s' - skipping.\n", cal->name);
445  pvt = unref_icalendar(pvt);
446  ao2_unlock(cal);
447  return NULL;
448  }
449 
450  if (ne_uri_parse(pvt->url, &pvt->uri) || pvt->uri.host == NULL || pvt->uri.path == NULL) {
451  ast_log(LOG_WARNING, "Could not parse url '%s' for iCalendar '%s' - skipping.\n", pvt->url, cal->name);
452  pvt = unref_icalendar(pvt);
453  ao2_unlock(cal);
454  return NULL;
455  }
456 
457  if (pvt->uri.scheme == NULL) {
458  pvt->uri.scheme = "http";
459  }
460 
461  if (pvt->uri.port == 0) {
462  pvt->uri.port = ne_uri_defaultport(pvt->uri.scheme);
463  }
464 
465  pvt->session = ne_session_create(pvt->uri.scheme, pvt->uri.host, pvt->uri.port);
466  ne_redirect_register(pvt->session);
467  ne_set_server_auth(pvt->session, auth_credentials, pvt);
468  if (!strcasecmp(pvt->uri.scheme, "https")) {
469  ne_ssl_trust_default_ca(pvt->session);
470  }
471 
472  cal->tech_pvt = pvt;
473 
474  ast_mutex_init(&refreshlock);
475 
476  /* Load it the first time */
477  if (!(pvt->data = fetch_icalendar(pvt))) {
478  ast_log(LOG_WARNING, "Unable to parse iCalendar '%s'\n", cal->name);
479  }
480 
482 
483  ao2_unlock(cal);
484 
485  /* The only writing from another thread will be if unload is true */
486  for(;;) {
487  struct timeval tv = ast_tvnow();
488  struct timespec ts = {0,};
489 
490  ts.tv_sec = tv.tv_sec + (60 * pvt->owner->refresh);
491 
492  ast_mutex_lock(&refreshlock);
493  while (!pvt->owner->unloading) {
494  if (ast_cond_timedwait(&pvt->owner->unload, &refreshlock, &ts) == ETIMEDOUT) {
495  break;
496  }
497  }
498  ast_mutex_unlock(&refreshlock);
499 
500  if (pvt->owner->unloading) {
501  ast_debug(10, "Skipping refresh since we got a shutdown signal\n");
502  return NULL;
503  }
504 
505  ast_debug(10, "Refreshing after %d minute timeout\n", pvt->owner->refresh);
506 
507  /* Free the old calendar data */
508  if (pvt->data) {
509  icalcomponent_free(pvt->data);
510  pvt->data = NULL;
511  }
512  if (!(pvt->data = fetch_icalendar(pvt))) {
513  ast_log(LOG_WARNING, "Unable to parse iCalendar '%s'\n", pvt->owner->name);
514  continue;
515  }
516 
518  }
519 
520  return NULL;
521 }
struct ast_variable * next
static void * unref_icalendar(void *obj)
struct ast_calendar * owner
ast_cond_t unload
Definition: calendar.h:135
unsigned int unloading
Definition: calendar.h:136
static icalcomponent * fetch_icalendar(struct icalendar_pvt *pvt)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define LOG_WARNING
Definition: logger.h:274
Structure for variables, used for configurations and for channel variables.
struct ao2_container * events
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
static void icalendar_update_events(struct icalendar_pvt *pvt)
#define ast_strlen_zero(foo)
Definition: strings.h:52
void * tech_pvt
Definition: calendar.h:119
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int auth_credentials(void *userdata, const char *realm, int attempts, char *username, char *secret)
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
struct ao2_container * ast_calendar_event_container_alloc(void)
Allocate an astobj2 container for ast_calendar_event objects.
Definition: res_calendar.c:689
const ast_string_field name
Definition: calendar.h:127
#define LOG_ERROR
Definition: logger.h:285
#define ao2_trylock(a)
Definition: astobj2.h:740
static ast_mutex_t refreshlock
Definition: res_calendar.c:225
const ast_string_field url
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void icalendar_destructor(void *obj)
const struct ast_config * ast_calendar_config_acquire(void)
Grab and lock pointer to the calendar config (read only)
Definition: res_calendar.c:258
structure to hold users read from users.conf
icalcomponent * data
#define ast_mutex_init(pmutex)
Definition: lock.h:184
Asterisk calendar structure.
Definition: calendar.h:117
void ast_calendar_config_release(void)
Release the calendar config.
Definition: res_calendar.c:270
static char url[512]
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
Structure for mutex and tracking information.
Definition: lock.h:135
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ icalendar_add_event()

static void icalendar_add_event ( icalcomponent *  comp,
struct icaltime_span *  span,
void *  data 
)
static

Definition at line 190 of file res_calendar_icalendar.c.

References ao2_link, AST_CALENDAR_BS_BUSY, AST_CALENDAR_BS_FREE, ast_calendar_event_alloc(), ast_calendar_unref_event(), ast_calloc, ast_free, AST_LIST_INSERT_TAIL, ast_log, ast_strdup, ast_string_field_set, ast_strlen_zero, ast_calendar_event::attendees, categories, icalendar_pvt::data, ast_calendar_attendee::data, end, icalendar_pvt::events, icalfloat_to_timet(), LOG_ERROR, LOG_WARNING, ast_calendar_attendee::next, icalendar_pvt::owner, ast_calendar_event::start, ast_calendar_event::summary, tmp(), and ast_calendar_event::uid.

Referenced by icalendar_update_events().

191 {
192  struct icalendar_pvt *pvt = data;
193  struct ast_calendar_event *event;
194  icaltimezone *utc = icaltimezone_get_utc_timezone();
195  icaltimetype start, end, tmp;
196  icalcomponent *valarm;
197  icalproperty *prop;
198  struct icaltriggertype trigger;
199 
200  if (!(pvt && pvt->owner)) {
201  ast_log(LOG_ERROR, "Require a private structure with an ownenr\n");
202  return;
203  }
204 
205  if (!(event = ast_calendar_event_alloc(pvt->owner))) {
206  ast_log(LOG_ERROR, "Could not allocate an event!\n");
207  return;
208  }
209 
210  start = icalcomponent_get_dtstart(comp);
211  end = icalcomponent_get_dtend(comp);
212 
213  event->start = icaltime_get_tzid(start) ? span->start : icalfloat_to_timet(start);
214  event->end = icaltime_get_tzid(end) ? span->end : icalfloat_to_timet(end);
215  event->busy_state = span->is_busy ? AST_CALENDAR_BS_BUSY : AST_CALENDAR_BS_FREE;
216 
217  if ((prop = icalcomponent_get_first_property(comp, ICAL_SUMMARY_PROPERTY))) {
218  ast_string_field_set(event, summary, icalproperty_get_value_as_string(prop));
219  }
220 
221  if ((prop = icalcomponent_get_first_property(comp, ICAL_DESCRIPTION_PROPERTY))) {
222  ast_string_field_set(event, description, icalproperty_get_value_as_string(prop));
223  }
224 
225  if ((prop = icalcomponent_get_first_property(comp, ICAL_ORGANIZER_PROPERTY))) {
226  ast_string_field_set(event, organizer, icalproperty_get_value_as_string(prop));
227  }
228 
229  if ((prop = icalcomponent_get_first_property(comp, ICAL_LOCATION_PROPERTY))) {
230  ast_string_field_set(event, location, icalproperty_get_value_as_string(prop));
231  }
232 
233  if ((prop = icalcomponent_get_first_property(comp, ICAL_CATEGORIES_PROPERTY))) {
234  ast_string_field_set(event, categories, icalproperty_get_value_as_string(prop));
235  }
236 
237  if ((prop = icalcomponent_get_first_property(comp, ICAL_PRIORITY_PROPERTY))) {
238  event->priority = icalvalue_get_integer(icalproperty_get_value(prop));
239  }
240 
241  if ((prop = icalcomponent_get_first_property(comp, ICAL_UID_PROPERTY))) {
242  ast_string_field_set(event, uid, icalproperty_get_value_as_string(prop));
243  } else {
244  ast_log(LOG_WARNING, "No UID found, but one is required. Generating, but updates may not be acurate\n");
245  if (!ast_strlen_zero(event->summary)) {
246  ast_string_field_set(event, uid, event->summary);
247  } else {
248  char tmp[100];
249  snprintf(tmp, sizeof(tmp), "%ld", event->start);
250  ast_string_field_set(event, uid, tmp);
251  }
252  }
253 
254  /*
255  * If comp has an RRULE and/or RDATE property, we need to check whether
256  * another vevent component supercedes this span. Such a component would
257  * have two characteristics:
258  * - its UID is the same as comp
259  * - its RECURRENCE-ID property is the same time as span->start
260  */
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));
266 
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);
273 
274  if (uid && !strcmp(icalproperty_get_value_as_string(uid), event->uid)) {
275  icaltimetype recurrence_id = icalcomponent_get_recurrenceid(vevent);
276 
277  /* Set the same timezone that we want to compare against */
278  icaltime_set_timezone(&recurrence_id, icaltime_get_timezone(start));
279 
280  if (!icaltime_compare(recurrence_id, span_start)
281  && icaltime_is_date(span_start) == icaltime_is_date(recurrence_id)) {
282  event = ast_calendar_unref_event(event);
283  return;
284  }
285  }
286  }
287  }
288 
289  /* Get the attendees */
290  for (prop = icalcomponent_get_first_property(comp, ICAL_ATTENDEE_PROPERTY);
291  prop; prop = icalcomponent_get_next_property(comp, ICAL_ATTENDEE_PROPERTY)) {
292  struct ast_calendar_attendee *attendee;
293  const char *data;
294 
295  if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
296  event = ast_calendar_unref_event(event);
297  return;
298  }
299  data = icalproperty_get_attendee(prop);
300  if (ast_strlen_zero(data)) {
301  ast_free(attendee);
302  continue;
303  }
304  attendee->data = ast_strdup(data);;
305  AST_LIST_INSERT_TAIL(&event->attendees, attendee, next);
306  }
307 
308 
309  /* Only set values for alarm based on VALARM. Can be overriden in main/calendar.c by autoreminder
310  * therefore, go ahead and add events even if their is no VALARM or it is malformed
311  * Currently we are only getting the first VALARM and are handling repitition in main/calendar.c from calendar.conf */
312  if (!(valarm = icalcomponent_get_first_component(comp, ICAL_VALARM_COMPONENT))) {
313  ao2_link(pvt->events, event);
314  event = ast_calendar_unref_event(event);
315  return;
316  }
317 
318  if (!(prop = icalcomponent_get_first_property(valarm, ICAL_TRIGGER_PROPERTY))) {
319  ast_log(LOG_WARNING, "VALARM has no TRIGGER, skipping!\n");
320  ao2_link(pvt->events, event);
321  event = ast_calendar_unref_event(event);
322  return;
323  }
324 
325  trigger = icalproperty_get_trigger(prop);
326 
327  if (icaltriggertype_is_null_trigger(trigger)) {
328  ast_log(LOG_WARNING, "Bad TRIGGER for VALARM, skipping!\n");
329  ao2_link(pvt->events, event);
330  event = ast_calendar_unref_event(event);
331  return;
332  }
333 
334  if (!icaltime_is_null_time(trigger.time)) { /* This is an absolute time */
335  tmp = icaltime_convert_to_zone(trigger.time, utc);
336  event->alarm = icaltime_as_timet_with_zone(tmp, utc);
337  } else { /* Offset from either dtstart or dtend */
338  /* XXX Technically you can check RELATED to see if the event fires from the END of the event
339  * But, I'm not sure I've ever seen anyone implement it in calendaring software, so I'm ignoring for now */
340  tmp = icaltime_add(start, trigger.duration);
341  event->alarm = icaltime_as_timet_with_zone(tmp, icaltime_get_timezone(start));
342  }
343 
344  ao2_link(pvt->events, event);
345  event = ast_calendar_unref_event(event);
346 
347  return;
348 }
struct ast_calendar * owner
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
struct ast_calendar_attendee * next
Definition: calendar.h:89
static time_t icalfloat_to_timet(icaltimetype time)
struct ao2_container * events
Definition: astman.c:222
const ast_string_field uid
Definition: calendar.h:101
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
char * end
Definition: eagi_proxy.c:73
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
struct ast_calendar_event * ast_calendar_event_alloc(struct ast_calendar *cal)
Allocate an astobj2 ast_calendar_event object.
Definition: res_calendar.c:667
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
struct association categories[]
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_calendar_event * ast_calendar_unref_event(struct ast_calendar_event *event)
Unreference an ast_calendar_event.
Definition: res_calendar.c:321
struct ast_calendar_event::attendees attendees
icalcomponent * data
const ast_string_field summary
Definition: calendar.h:101
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ icalendar_destructor()

static void icalendar_destructor ( void *  obj)
static

Definition at line 70 of file res_calendar_icalendar.c.

References ao2_callback, ao2_ref, ast_debug, ast_string_field_free_memory, icalendar_pvt::data, icalendar_pvt::events, ast_calendar::name, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, icalendar_pvt::owner, icalendar_pvt::session, and icalendar_pvt::uri.

Referenced by ical_load_calendar().

71 {
72  struct icalendar_pvt *pvt = obj;
73 
74  ast_debug(1, "Destroying pvt for iCalendar %s\n", pvt->owner->name);
75  if (pvt->session) {
76  ne_session_destroy(pvt->session);
77  }
78  if (pvt->data) {
79  icalcomponent_free(pvt->data);
80  }
81  ne_uri_free(&pvt->uri);
83 
85 
86  ao2_ref(pvt->events, -1);
87 }
struct ast_calendar * owner
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
struct ao2_container * events
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const ast_string_field name
Definition: calendar.h:127
icalcomponent * data
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ icalendar_update_events()

static void icalendar_update_events ( struct icalendar_pvt pvt)
static

Definition at line 350 of file res_calendar_icalendar.c.

References ast_calendar_merge_events(), ast_log, icalendar_pvt::data, icalendar_pvt::events, icalendar_add_event(), LOG_ERROR, icalendar_pvt::owner, and ast_calendar::timeframe.

Referenced by ical_load_calendar().

351 {
352  struct icaltimetype start_time, end_time;
353  icalcomponent *iter;
354 
355  if (!pvt) {
356  ast_log(LOG_ERROR, "iCalendar is NULL\n");
357  return;
358  }
359 
360  if (!pvt->owner) {
361  ast_log(LOG_ERROR, "iCalendar is an orphan!\n");
362  return;
363  }
364 
365  if (!pvt->data) {
366  ast_log(LOG_ERROR, "The iCalendar has not been parsed!\n");
367  return;
368  }
369 
370  start_time = icaltime_current_time_with_zone(icaltimezone_get_utc_timezone());
371  end_time = icaltime_current_time_with_zone(icaltimezone_get_utc_timezone());
372  end_time.second += pvt->owner->timeframe * 60;
373  end_time = icaltime_normalize(end_time);
374 
375  for (iter = icalcomponent_get_first_component(pvt->data, ICAL_VEVENT_COMPONENT);
376  iter;
377  iter = icalcomponent_get_next_component(pvt->data, ICAL_VEVENT_COMPONENT))
378  {
379  icalcomponent_foreach_recurrence(iter, start_time, end_time, icalendar_add_event, pvt);
380  }
381 
383 }
struct ast_calendar * owner
static void icalendar_add_event(icalcomponent *comp, struct icaltime_span *span, void *data)
struct ao2_container * events
int timeframe
Definition: calendar.h:133
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.
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
icalcomponent * data

◆ icalfloat_to_timet()

static time_t icalfloat_to_timet ( icaltimetype  time)
static

Definition at line 164 of file res_calendar_icalendar.c.

References ast_mktime(), NULL, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, and ast_tm::tm_year.

Referenced by icalendar_add_event().

165 {
166  struct ast_tm tm = {0,};
167  struct timeval tv;
168 
169  tm.tm_mday = time.day;
170  tm.tm_mon = time.month - 1;
171  tm.tm_year = time.year - 1900;
172  tm.tm_hour = time.hour;
173  tm.tm_min = time.minute;
174  tm.tm_sec = time.second;
175  tm.tm_isdst = -1;
176  tv = ast_mktime(&tm, NULL);
177 
178  return tv.tv_sec;
179 }
#define NULL
Definition: resample.c:96
int tm_year
Definition: localtime.h:41
int tm_mon
Definition: localtime.h:40
int tm_mday
Definition: localtime.h:39
int tm_hour
Definition: localtime.h:38
int tm_sec
Definition: localtime.h:36
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2357
int tm_isdst
Definition: localtime.h:44
int tm_min
Definition: localtime.h:37

◆ load_module()

static int load_module ( void  )
static

Definition at line 523 of file res_calendar_icalendar.c.

References ast_calendar_register(), AST_MODULE_LOAD_DECLINE, and AST_MODULE_LOAD_SUCCESS.

Referenced by unload_module().

524 {
525  ne_sock_init();
527  ne_sock_exit();
529  }
530 
532 }
int ast_calendar_register(struct ast_calendar_tech *tech)
Register a new calendar technology.
Definition: res_calendar.c:549
static struct ast_calendar_tech ical_tech
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 534 of file res_calendar_icalendar.c.

References ast_calendar_unregister(), AST_MODFLAG_LOAD_ORDER, AST_MODPRI_DEVSTATE_PLUGIN, AST_MODULE_INFO(), AST_MODULE_SUPPORT_EXTENDED, ASTERISK_GPL_KEY, and load_module().

535 {
537  ne_sock_exit();
538  return 0;
539 }
static struct ast_calendar_tech ical_tech
void ast_calendar_unregister(struct ast_calendar_tech *tech)
Unregister a new calendar technology.
Definition: res_calendar.c:587

◆ unref_icalendar()

static void * unref_icalendar ( void *  obj)
static

Definition at line 89 of file res_calendar_icalendar.c.

References ao2_ref, and NULL.

Referenced by ical_load_calendar().

90 {
91  struct icalendar_pvt *pvt = obj;
92 
93  ao2_ref(pvt, -1);
94  return NULL;
95 }
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk iCalendar .ics file integration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PLUGIN, .requires = "res_calendar", }
static

Definition at line 547 of file res_calendar_icalendar.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 547 of file res_calendar_icalendar.c.

◆ ical_tech

struct ast_calendar_tech ical_tech
static

Definition at line 49 of file res_calendar_icalendar.c.