Resource for handling CalDAV 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 <libxml/xmlmemory.h>#include <libxml/parser.h>#include "asterisk/module.h"#include "asterisk/calendar.h"#include "asterisk/lock.h"#include "asterisk/config.h"#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
| struct | caldav_pvt |
| struct | xmlstate |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | auth_credentials (void *userdata, const char *realm, int attempts, char *username, char *secret) |
| static void | caldav_add_event (icalcomponent *comp, struct icaltime_span *span, void *data) |
| static void | caldav_destructor (void *obj) |
| static struct ast_str * | caldav_get_events_between (struct caldav_pvt *pvt, time_t start_time, time_t end_time) |
| static void * | caldav_load_calendar (void *data) |
| static struct ast_str * | caldav_request (struct caldav_pvt *pvt, const char *method, struct ast_str *req_body, struct ast_str *subdir, const char *content_type) |
| static int | caldav_write_event (struct ast_calendar_event *event) |
| static int | fetch_response_reader (void *data, const char *block, size_t len) |
| static void | handle_characters (void *data, const xmlChar *ch, int len) |
| static void | handle_end_element (void *data, const xmlChar *name) |
| static void | handle_start_element (void *data, const xmlChar *fullname, const xmlChar **atts) |
| static time_t | icalfloat_to_timet (icaltimetype time) |
| static int | load_module (void) |
| static int | unload_module (void) |
| static void * | unref_caldav (void *obj) |
| static int | update_caldav (struct caldav_pvt *pvt) |
| static int | verify_cert (void *userdata, int failures, const ne_ssl_certificate *cert) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk CalDAV Calendar 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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PLUGIN, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_calendar_tech | caldav_tech |
Resource for handling CalDAV calendars.
Definition in file res_calendar_caldav.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 715 of file res_calendar_caldav.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 715 of file res_calendar_caldav.c.
| static int auth_credentials | ( | void * | userdata, |
| const char * | realm, | ||
| int | attempts, | ||
| char * | username, | ||
| char * | secret | ||
| ) | [static] |
Definition at line 113 of file res_calendar_caldav.c.
References ast_log(), LOG_WARNING, ast_calendar::name, caldav_pvt::owner, caldav_pvt::secret, and caldav_pvt::user.
Referenced by caldav_load_calendar().
{
struct caldav_pvt *pvt = userdata;
if (attempts > 1) {
ast_log(LOG_WARNING, "Invalid username or password for CalDAV calendar '%s'\n", pvt->owner->name);
return -1;
}
ne_strnzcpy(username, pvt->user, NE_ABUFSIZ);
ne_strnzcpy(secret, pvt->secret, NE_ABUFSIZ);
return 0;
}
| static void caldav_add_event | ( | icalcomponent * | comp, |
| struct icaltime_span * | span, | ||
| void * | data | ||
| ) | [static] |
Definition at line 334 of file res_calendar_caldav.c.
References ao2_link, AST_CALENDAR_BS_BUSY, AST_CALENDAR_BS_FREE, ast_calendar_event_alloc(), ast_calendar_unref_event(), ast_calloc, AST_LIST_INSERT_TAIL, ast_log(), ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_calendar_event::attendees, ast_calendar_attendee::data, ast_calendar_event::end, caldav_pvt::events, icalfloat_to_timet(), LOG_ERROR, LOG_WARNING, ast_calendar_attendee::next, caldav_pvt::owner, ast_calendar_event::start, and ast_calendar_event::summary.
Referenced by handle_end_element().
{
struct caldav_pvt *pvt = data;
struct ast_calendar_event *event;
icaltimezone *utc = icaltimezone_get_utc_timezone();
icaltimetype start, end, tmp;
icalcomponent *valarm;
icalproperty *prop;
struct icaltriggertype trigger;
if (!(pvt && pvt->owner)) {
ast_log(LOG_ERROR, "Require a private structure with an owner\n");
return;
}
if (!(event = ast_calendar_event_alloc(pvt->owner))) {
ast_log(LOG_ERROR, "Could not allocate an event!\n");
return;
}
start = icalcomponent_get_dtstart(comp);
end = icalcomponent_get_dtend(comp);
event->start = icaltime_get_tzid(start) ? span->start : icalfloat_to_timet(start);
event->end = icaltime_get_tzid(end) ? span->end : icalfloat_to_timet(end);
event->busy_state = span->is_busy ? AST_CALENDAR_BS_BUSY : AST_CALENDAR_BS_FREE;
if ((prop = icalcomponent_get_first_property(comp, ICAL_SUMMARY_PROPERTY))) {
ast_string_field_set(event, summary, icalproperty_get_value_as_string(prop));
}
if ((prop = icalcomponent_get_first_property(comp, ICAL_DESCRIPTION_PROPERTY))) {
ast_string_field_set(event, description, icalproperty_get_value_as_string(prop));
}
if ((prop = icalcomponent_get_first_property(comp, ICAL_ORGANIZER_PROPERTY))) {
ast_string_field_set(event, organizer, icalproperty_get_value_as_string(prop));
}
if ((prop = icalcomponent_get_first_property(comp, ICAL_LOCATION_PROPERTY))) {
ast_string_field_set(event, location, icalproperty_get_value_as_string(prop));
}
if ((prop = icalcomponent_get_first_property(comp, ICAL_CATEGORIES_PROPERTY))) {
ast_string_field_set(event, categories, icalproperty_get_value_as_string(prop));
}
if ((prop = icalcomponent_get_first_property(comp, ICAL_PRIORITY_PROPERTY))) {
event->priority = icalvalue_get_integer(icalproperty_get_value(prop));
}
if ((prop = icalcomponent_get_first_property(comp, ICAL_UID_PROPERTY))) {
ast_string_field_set(event, uid, icalproperty_get_value_as_string(prop));
} else {
ast_log(LOG_WARNING, "No UID found, but one is required. Generating, but updates may not be acurate\n");
if (!ast_strlen_zero(event->summary)) {
ast_string_field_set(event, uid, event->summary);
} else {
char tmp[100];
snprintf(tmp, sizeof(tmp), "%lu", event->start);
ast_string_field_set(event, uid, tmp);
}
}
/* Get the attendees */
for (prop = icalcomponent_get_first_property(comp, ICAL_ATTENDEE_PROPERTY);
prop; prop = icalcomponent_get_next_property(comp, ICAL_ATTENDEE_PROPERTY)) {
struct ast_calendar_attendee *attendee;
const char *data;
if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
event = ast_calendar_unref_event(event);
return;
}
data = icalproperty_get_attendee(prop);
if (!ast_strlen_zero(data)) {
attendee->data = ast_strdup(data);;
AST_LIST_INSERT_TAIL(&event->attendees, attendee, next);
}
}
/* Only set values for alarm based on VALARM. Can be overriden in main/calendar.c by autoreminder
* therefore, go ahead and add events even if their is no VALARM or it is malformed
* Currently we are only getting the first VALARM and are handling repitition in main/calendar.c from calendar.conf */
if (!(valarm = icalcomponent_get_first_component(comp, ICAL_VALARM_COMPONENT))) {
ao2_link(pvt->events, event);
event = ast_calendar_unref_event(event);
return;
}
if (!(prop = icalcomponent_get_first_property(valarm, ICAL_TRIGGER_PROPERTY))) {
ast_log(LOG_WARNING, "VALARM has no TRIGGER, skipping!\n");
ao2_link(pvt->events, event);
event = ast_calendar_unref_event(event);
return;
}
trigger = icalproperty_get_trigger(prop);
if (icaltriggertype_is_null_trigger(trigger)) {
ast_log(LOG_WARNING, "Bad TRIGGER for VALARM, skipping!\n");
ao2_link(pvt->events, event);
event = ast_calendar_unref_event(event);
return;
}
if (!icaltime_is_null_time(trigger.time)) { /* This is an absolute time */
tmp = icaltime_convert_to_zone(trigger.time, utc);
event->alarm = icaltime_as_timet_with_zone(tmp, utc);
} else { /* Offset from either dtstart or dtend */
/* XXX Technically you can check RELATED to see if the event fires from the END of the event
* But, I'm not sure I've ever seen anyone implement it in calendaring software, so I'm ignoring for now */
tmp = icaltime_add(start, trigger.duration);
event->alarm = icaltime_as_timet_with_zone(tmp, utc);
}
ao2_link(pvt->events, event);
event = ast_calendar_unref_event(event);
return;
}
| static void caldav_destructor | ( | void * | obj | ) | [static] |
Definition at line 74 of file res_calendar_caldav.c.
References ao2_callback, ao2_ref, ast_debug, ast_string_field_free_memory, caldav_pvt::events, ast_calendar::name, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, caldav_pvt::owner, and caldav_pvt::session.
Referenced by caldav_load_calendar().
{
struct caldav_pvt *pvt = obj;
ast_debug(1, "Destroying pvt for CalDAV calendar %s\n", pvt->owner->name);
if (pvt->session) {
ne_session_destroy(pvt->session);
}
ast_string_field_free_memory(pvt);
ao2_callback(pvt->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
ao2_ref(pvt->events, -1);
}
| static struct ast_str* caldav_get_events_between | ( | struct caldav_pvt * | pvt, |
| time_t | start_time, | ||
| time_t | end_time | ||
| ) | [static, read] |
Definition at line 265 of file res_calendar_caldav.c.
References ast_free, ast_log(), ast_str_append(), ast_str_create(), caldav_request(), and LOG_ERROR.
Referenced by update_caldav().
{
struct ast_str *body, *response;
icaltimezone *utc = icaltimezone_get_utc_timezone();
icaltimetype start, end;
const char *start_str, *end_str;
if (!(body = ast_str_create(512))) {
ast_log(LOG_ERROR, "Could not allocate memory for body of request!\n");
return NULL;
}
start = icaltime_from_timet_with_zone(start_time, 0, utc);
end = icaltime_from_timet_with_zone(end_time, 0, utc);
start_str = icaltime_as_ical_string(start);
end_str = icaltime_as_ical_string(end);
/* If I was really being efficient, I would store a collection of event URIs and etags,
* first doing a query of just the etag and seeing if anything had changed. If it had,
* then I would do a request for each of the events that had changed, and only bother
* updating those. Oh well. */
ast_str_append(&body, 0,
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
"<C:calendar-query xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">\n"
" <D:prop>\n"
" <C:calendar-data>\n"
" <C:expand start=\"%s\" end=\"%s\"/>\n"
" </C:calendar-data>\n"
" </D:prop>\n"
" <C:filter>\n"
" <C:comp-filter name=\"VCALENDAR\">\n"
" <C:comp-filter name=\"VEVENT\">\n"
" <C:time-range start=\"%s\" end=\"%s\"/>\n"
" </C:comp-filter>\n"
" </C:comp-filter>\n"
" </C:filter>\n"
"</C:calendar-query>\n", start_str, end_str, start_str, end_str);
response = caldav_request(pvt, "REPORT", body, NULL, NULL);
ast_free(body);
return response;
}
| static void * caldav_load_calendar | ( | void * | data | ) | [static] |
Definition at line 567 of file res_calendar_caldav.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(), caldav_destructor(), caldav_pvt::events, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_calendar::name, ast_variable::next, caldav_pvt::owner, ast_calendar::refresh, refreshlock, secret, caldav_pvt::session, ast_calendar::tech_pvt, ast_calendar::unload, ast_calendar::unloading, unref_caldav(), update_caldav(), caldav_pvt::uri, caldav_pvt::url, url, ast_variable::value, and verify_cert().
{
struct caldav_pvt *pvt;
const struct ast_config *cfg;
struct ast_variable *v;
struct ast_calendar *cal = void_data;
ast_mutex_t refreshlock;
if (!(cal && (cfg = ast_calendar_config_acquire()))) {
ast_log(LOG_ERROR, "You must enable calendar support for res_caldav to load\n");
return NULL;
}
if (ao2_trylock(cal)) {
if (cal->unloading) {
ast_log(LOG_WARNING, "Unloading module, load_calendar cancelled.\n");
} else {
ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
}
ast_calendar_config_release();
return NULL;
}
if (!(pvt = ao2_alloc(sizeof(*pvt), caldav_destructor))) {
ast_log(LOG_ERROR, "Could not allocate caldav_pvt structure for calendar: %s\n", cal->name);
ast_calendar_config_release();
return NULL;
}
pvt->owner = cal;
if (!(pvt->events = ast_calendar_event_container_alloc())) {
ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
pvt = unref_caldav(pvt);
ao2_unlock(cal);
ast_calendar_config_release();
return NULL;
}
if (ast_string_field_init(pvt, 32)) {
ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
pvt = unref_caldav(pvt);
ao2_unlock(cal);
ast_calendar_config_release();
return NULL;
}
for (v = ast_variable_browse(cfg, cal->name); v; v = v->next) {
if (!strcasecmp(v->name, "url")) {
ast_string_field_set(pvt, url, v->value);
} else if (!strcasecmp(v->name, "user")) {
ast_string_field_set(pvt, user, v->value);
} else if (!strcasecmp(v->name, "secret")) {
ast_string_field_set(pvt, secret, v->value);
}
}
ast_calendar_config_release();
if (ast_strlen_zero(pvt->url)) {
ast_log(LOG_WARNING, "No URL was specified for CalDAV calendar '%s' - skipping.\n", cal->name);
pvt = unref_caldav(pvt);
ao2_unlock(cal);
return NULL;
}
if (ne_uri_parse(pvt->url, &pvt->uri) || pvt->uri.host == NULL || pvt->uri.path == NULL) {
ast_log(LOG_WARNING, "Could not parse url '%s' for CalDAV calendar '%s' - skipping.\n", pvt->url, cal->name);
pvt = unref_caldav(pvt);
ao2_unlock(cal);
return NULL;
}
if (pvt->uri.scheme == NULL) {
pvt->uri.scheme = "http";
}
if (pvt->uri.port == 0) {
pvt->uri.port = ne_uri_defaultport(pvt->uri.scheme);
}
pvt->session = ne_session_create(pvt->uri.scheme, pvt->uri.host, pvt->uri.port);
ne_redirect_register(pvt->session);
ne_set_server_auth(pvt->session, auth_credentials, pvt);
if (!strcasecmp(pvt->uri.scheme, "https")) {
ne_ssl_trust_default_ca(pvt->session);
ne_ssl_set_verify(pvt->session, verify_cert, NULL);
}
cal->tech_pvt = pvt;
ast_mutex_init(&refreshlock);
/* Load it the first time */
update_caldav(pvt);
ao2_unlock(cal);
/* The only writing from another thread will be if unload is true */
for (;;) {
struct timeval tv = ast_tvnow();
struct timespec ts = {0,};
ts.tv_sec = tv.tv_sec + (60 * pvt->owner->refresh);
ast_mutex_lock(&refreshlock);
while (!pvt->owner->unloading) {
if (ast_cond_timedwait(&pvt->owner->unload, &refreshlock, &ts) == ETIMEDOUT) {
break;
}
}
ast_mutex_unlock(&refreshlock);
if (pvt->owner->unloading) {
ast_debug(10, "Skipping refresh since we got a shutdown signal\n");
return NULL;
}
ast_debug(10, "Refreshing after %d minute timeout\n", pvt->owner->refresh);
update_caldav(pvt);
}
return NULL;
}
| static struct ast_str* caldav_request | ( | struct caldav_pvt * | pvt, |
| const char * | method, | ||
| struct ast_str * | req_body, | ||
| struct ast_str * | subdir, | ||
| const char * | content_type | ||
| ) | [static, read] |
Definition at line 128 of file res_calendar_caldav.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, caldav_pvt::owner, caldav_pvt::session, and caldav_pvt::uri.
Referenced by caldav_get_events_between(), and caldav_write_event().
{
struct ast_str *response;
ne_request *req;
int ret;
char buf[1000];
if (!pvt) {
ast_log(LOG_ERROR, "There is no private!\n");
return NULL;
}
if (!(response = ast_str_create(512))) {
ast_log(LOG_ERROR, "Could not allocate memory for response.\n");
return NULL;
}
snprintf(buf, sizeof(buf), "%s%s", pvt->uri.path, subdir ? ast_str_buffer(subdir) : "");
req = ne_request_create(pvt->session, method, buf);
ne_add_response_body_reader(req, ne_accept_2xx, fetch_response_reader, &response);
ne_set_request_body_buffer(req, ast_str_buffer(req_body), ast_str_strlen(req_body));
ne_add_request_header(req, "Content-type", ast_strlen_zero(content_type) ? "text/xml" : content_type);
ret = ne_request_dispatch(req);
ne_request_destroy(req);
if (ret != NE_OK || !ast_str_strlen(response)) {
if (ret != NE_OK) {
ast_log(LOG_WARNING, "Unknown response to CalDAV calendar %s, request %s to %s: %s\n", pvt->owner->name, method, buf, ne_get_error(pvt->session));
}
ast_free(response);
return NULL;
}
return response;
}
| static int caldav_write_event | ( | struct ast_calendar_event * | event | ) | [static] |
Definition at line 166 of file res_calendar_caldav.c.
References AST_CALENDAR_BS_BUSY, AST_CALENDAR_BS_BUSY_TENTATIVE, ast_free, ast_log(), ast_random(), ast_str_append(), ast_str_create(), ast_str_set(), ast_string_field_build, ast_strlen_zero(), ast_calendar_event::busy_state, caldav_request(), ast_calendar_event::categories, ast_calendar_event::description, ast_calendar_event::end, ast_calendar_event::location, LOG_ERROR, LOG_WARNING, ast_calendar_event::organizer, caldav_pvt::owner, ast_calendar_event::priority, ast_calendar_event::start, ast_calendar_event::summary, ast_calendar::tech_pvt, ast_calendar_event::uid, and caldav_pvt::url.
{
struct caldav_pvt *pvt;
struct ast_str *body = NULL, *response = NULL, *subdir = NULL;
icalcomponent *calendar, *icalevent;
icaltimezone *utc = icaltimezone_get_utc_timezone();
int ret = -1;
if (!event) {
ast_log(LOG_WARNING, "No event passed!\n");
return -1;
}
if (!(event->start && event->end)) {
ast_log(LOG_WARNING, "The event must contain a start and an end\n");
return -1;
}
if (!(body = ast_str_create(512)) ||
!(subdir = ast_str_create(32)) ||
!(response = ast_str_create(512))) {
ast_log(LOG_ERROR, "Could not allocate memory for request and response!\n");
goto write_cleanup;
}
pvt = event->owner->tech_pvt;
if (ast_strlen_zero(event->uid)) {
unsigned short val[8];
int x;
for (x = 0; x < 8; x++) {
val[x] = ast_random();
}
ast_string_field_build(event, uid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
}
calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
icalcomponent_add_property(calendar, icalproperty_new_version("2.0"));
icalcomponent_add_property(calendar, icalproperty_new_prodid("-//Digium, Inc.//res_caldav//EN"));
icalevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
icalcomponent_add_property(icalevent, icalproperty_new_dtstamp(icaltime_current_time_with_zone(utc)));
icalcomponent_add_property(icalevent, icalproperty_new_uid(event->uid));
icalcomponent_add_property(icalevent, icalproperty_new_dtstart(icaltime_from_timet_with_zone(event->start, 0, utc)));
icalcomponent_add_property(icalevent, icalproperty_new_dtend(icaltime_from_timet_with_zone(event->end, 0, utc)));
if (!ast_strlen_zero(event->organizer)) {
icalcomponent_add_property(icalevent, icalproperty_new_organizer(event->organizer));
}
if (!ast_strlen_zero(event->summary)) {
icalcomponent_add_property(icalevent, icalproperty_new_summary(event->summary));
}
if (!ast_strlen_zero(event->description)) {
icalcomponent_add_property(icalevent, icalproperty_new_description(event->description));
}
if (!ast_strlen_zero(event->location)) {
icalcomponent_add_property(icalevent, icalproperty_new_location(event->location));
}
if (!ast_strlen_zero(event->categories)) {
icalcomponent_add_property(icalevent, icalproperty_new_categories(event->categories));
}
if (event->priority > 0) {
icalcomponent_add_property(icalevent, icalproperty_new_priority(event->priority));
}
switch (event->busy_state) {
case AST_CALENDAR_BS_BUSY:
icalcomponent_add_property(icalevent, icalproperty_new_status(ICAL_STATUS_CONFIRMED));
break;
case AST_CALENDAR_BS_BUSY_TENTATIVE:
icalcomponent_add_property(icalevent, icalproperty_new_status(ICAL_STATUS_TENTATIVE));
break;
default:
icalcomponent_add_property(icalevent, icalproperty_new_status(ICAL_STATUS_NONE));
}
icalcomponent_add_component(calendar, icalevent);
ast_str_append(&body, 0, "%s", icalcomponent_as_ical_string(calendar));
ast_str_set(&subdir, 0, "%s%s.ics", pvt->url[strlen(pvt->url) - 1] == '/' ? "" : "/", event->uid);
response = caldav_request(pvt, "PUT", body, subdir, "text/calendar");
ret = 0;
write_cleanup:
if (body) {
ast_free(body);
}
if (response) {
ast_free(response);
}
if (subdir) {
ast_free(subdir);
}
return ret;
}
| static int fetch_response_reader | ( | void * | data, |
| const char * | block, | ||
| size_t | len | ||
| ) | [static] |
Definition at line 97 of file res_calendar_caldav.c.
References ast_free, ast_malloc, ast_str_append(), and len().
Referenced by caldav_request().
{
struct ast_str **response = data;
unsigned char *tmp;
if (!(tmp = ast_malloc(len + 1))) {
return -1;
}
memcpy(tmp, block, len);
tmp[len] = '\0';
ast_str_append(response, 0, "%s", tmp);
ast_free(tmp);
return 0;
}
| static void handle_characters | ( | void * | data, |
| const xmlChar * | ch, | ||
| int | len | ||
| ) | [static] |
Definition at line 507 of file res_calendar_caldav.c.
References ast_str_append(), xmlstate::cdata, and xmlstate::in_caldata.
Referenced by update_caldav().
{
struct xmlstate *state = data;
xmlChar *tmp;
if (!state->in_caldata) {
return;
}
tmp = xmlStrndup(ch, len);
ast_str_append(&state->cdata, 0, "%s", (char *)tmp);
xmlFree(tmp);
}
| static void handle_end_element | ( | void * | data, |
| const xmlChar * | name | ||
| ) | [static] |
Definition at line 475 of file res_calendar_caldav.c.
References ast_str_buffer(), ast_str_strlen(), caldav_add_event(), xmlstate::cdata, xmlstate::end, xmlstate::in_caldata, xmlstate::pvt, and xmlstate::start.
Referenced by update_caldav().
{
struct xmlstate *state = data;
struct icaltimetype start, end;
icaltimezone *utc = icaltimezone_get_utc_timezone();
icalcomponent *iter;
icalcomponent *comp;
if (xmlStrcasecmp(name, BAD_CAST "C:calendar-data")) {
return;
}
state->in_caldata = 0;
if (!(state->cdata && ast_str_strlen(state->cdata))) {
return;
}
/* XXX Parse the calendar blurb for recurrence events in the time range,
* create an event, and add it to pvt->events */
start = icaltime_from_timet_with_zone(state->start, 0, utc);
end = icaltime_from_timet_with_zone(state->end, 0, utc);
comp = icalparser_parse_string(ast_str_buffer(state->cdata));
for (iter = icalcomponent_get_first_component(comp, ICAL_VEVENT_COMPONENT);
iter;
iter = icalcomponent_get_next_component(comp, ICAL_VEVENT_COMPONENT))
{
icalcomponent_foreach_recurrence(iter, start, end, caldav_add_event, state->pvt);
}
icalcomponent_free(comp);
}
| static void handle_start_element | ( | void * | data, |
| const xmlChar * | fullname, | ||
| const xmlChar ** | atts | ||
| ) | [static] |
Definition at line 465 of file res_calendar_caldav.c.
References ast_str_reset(), xmlstate::cdata, and xmlstate::in_caldata.
Referenced by update_caldav().
{
struct xmlstate *state = data;
if (!xmlStrcasecmp(fullname, BAD_CAST "C:calendar-data")) {
state->in_caldata = 1;
ast_str_reset(state->cdata);
}
}
| static time_t icalfloat_to_timet | ( | icaltimetype | time | ) | [static] |
Definition at line 309 of file res_calendar_caldav.c.
References ast_mktime(), 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 caldav_add_event().
| static int load_module | ( | void | ) | [static] |
Definition at line 693 of file res_calendar_caldav.c.
References ast_calendar_register(), AST_MODULE_LOAD_DECLINE, and AST_MODULE_LOAD_SUCCESS.
{
ne_sock_init();
if (ast_calendar_register(&caldav_tech)) {
ne_sock_exit();
return AST_MODULE_LOAD_DECLINE;
}
return AST_MODULE_LOAD_SUCCESS;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 704 of file res_calendar_caldav.c.
References ast_calendar_unregister().
{
ast_calendar_unregister(&caldav_tech);
ne_sock_exit();
return 0;
}
| static void * unref_caldav | ( | void * | obj | ) | [static] |
Definition at line 89 of file res_calendar_caldav.c.
References ao2_ref.
Referenced by caldav_load_calendar().
{
struct caldav_pvt *pvt = obj;
ao2_ref(pvt, -1);
return NULL;
}
| static int update_caldav | ( | struct caldav_pvt * | pvt | ) | [static] |
Definition at line 521 of file res_calendar_caldav.c.
References ast_calendar_merge_events(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_strlen(), ast_tvnow(), caldav_get_events_between(), xmlstate::cdata, xmlstate::end, caldav_pvt::events, handle_characters(), handle_end_element(), handle_start_element(), xmlstate::in_caldata, caldav_pvt::owner, xmlstate::start, and ast_calendar::timeframe.
Referenced by caldav_load_calendar().
{
struct timeval now = ast_tvnow();
time_t start, end;
struct ast_str *response;
xmlSAXHandler saxHandler;
struct xmlstate state = {
.in_caldata = 0,
.pvt = pvt
};
start = now.tv_sec;
end = now.tv_sec + 60 * pvt->owner->timeframe;
if (!(response = caldav_get_events_between(pvt, start, end))) {
return -1;
}
if (!(state.cdata = ast_str_create(512))) {
ast_free(response);
return -1;
}
state.start = start;
state.end = end;
memset(&saxHandler, 0, sizeof(saxHandler));
saxHandler.startElement = handle_start_element;
saxHandler.endElement = handle_end_element;
saxHandler.characters = handle_characters;
xmlSAXUserParseMemory(&saxHandler, &state, ast_str_buffer(response), ast_str_strlen(response));
ast_calendar_merge_events(pvt->owner, pvt->events);
ast_free(response);
ast_free(state.cdata);
return 0;
}
| static int verify_cert | ( | void * | userdata, |
| int | failures, | ||
| const ne_ssl_certificate * | cert | ||
| ) | [static] |
Definition at line 561 of file res_calendar_caldav.c.
Referenced by caldav_load_calendar().
{
/* Verify all certs */
return 0;
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk CalDAV Calendar 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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PLUGIN, } [static] |
Definition at line 715 of file res_calendar_caldav.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 715 of file res_calendar_caldav.c.
struct ast_calendar_tech caldav_tech [static] |
Definition at line 53 of file res_calendar_caldav.c.