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

Resource for handling MS Exchange Web Service calendars. More...

#include "asterisk.h"
#include <ne_request.h>
#include <ne_session.h>
#include <ne_uri.h>
#include <ne_socket.h>
#include <ne_auth.h>
#include <ne_xml.h>
#include <ne_xmlreq.h>
#include <ne_utils.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_ews.c:

Go to the source code of this file.

Data Structures

struct  calendar_id
 
struct  ewscal_pvt
 
struct  xml_context::ids
 
struct  xml_context
 

Enumerations

enum  {
  XML_EVENT_CALENDAR_ITEM = 9, XML_EVENT_NAME = 10, XML_EVENT_DESCRIPTION, XML_EVENT_START,
  XML_EVENT_END, XML_EVENT_BUSY, XML_EVENT_ORGANIZER, XML_EVENT_LOCATION,
  XML_EVENT_ATTENDEE_LIST, XML_EVENT_ATTENDEE, XML_EVENT_MAILBOX, XML_EVENT_EMAIL_ADDRESS,
  XML_EVENT_CATEGORIES, XML_EVENT_CATEGORY, XML_EVENT_IMPORTANCE
}
 
enum  xml_op { XML_OP_FIND = 100, XML_OP_GET, XML_OP_CREATE }
 

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 int cdata (void *userdata, int state, const char *cdata, size_t len)
 
static int endelm (void *userdata, int state, const char *nspace, const char *name)
 
static void ewscal_destructor (void *obj)
 
static void * ewscal_load_calendar (void *data)
 
static int ewscal_write_event (struct ast_calendar_event *event)
 
static struct calendar_idget_ewscal_ids_for (struct ewscal_pvt *pvt)
 
static const char * get_soap_action (enum xml_op op)
 
static int load_module (void)
 
static const char * msstatus (enum ast_calendar_busy_state state)
 
static const char * mstime (time_t t, char *buf, size_t buflen)
 
static time_t mstime_to_time_t (char *mstime)
 
static int parse_ewscal_id (struct ewscal_pvt *pvt, const char *id)
 
static int send_ews_request_and_parse (struct ast_str *request, struct xml_context *ctx)
 
static int ssl_verify (void *userdata, int failures, const ne_ssl_certificate *cert)
 
static int startelm (void *userdata, int parent, const char *nspace, const char *name, const char **atts)
 
static int unload_module (void)
 
static void * unref_ewscal (void *obj)
 
static int update_ewscal (struct ewscal_pvt *pvt)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk MS Exchange Web Service 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 = "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 ewscal_tech
 

Detailed Description

Resource for handling MS Exchange Web Service calendars.

Definition in file res_calendar_ews.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
XML_EVENT_CALENDAR_ITEM 
XML_EVENT_NAME 
XML_EVENT_DESCRIPTION 
XML_EVENT_START 
XML_EVENT_END 
XML_EVENT_BUSY 
XML_EVENT_ORGANIZER 
XML_EVENT_LOCATION 
XML_EVENT_ATTENDEE_LIST 
XML_EVENT_ATTENDEE 
XML_EVENT_MAILBOX 
XML_EVENT_EMAIL_ADDRESS 
XML_EVENT_CATEGORIES 
XML_EVENT_CATEGORY 
XML_EVENT_IMPORTANCE 

Definition at line 82 of file res_calendar_ews.c.

◆ xml_op

enum xml_op
Enumerator
XML_OP_FIND 
XML_OP_GET 
XML_OP_CREATE 

Definition at line 61 of file res_calendar_ews.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 946 of file res_calendar_ews.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 946 of file res_calendar_ews.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 946 of file res_calendar_ews.c.

◆ auth_credentials()

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

Definition at line 138 of file res_calendar_ews.c.

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

Referenced by ewscal_load_calendar().

139 {
140  struct ewscal_pvt *pvt = userdata;
141 
142  if (attempts > 1) {
143  ast_log(LOG_WARNING, "Invalid username or password for Exchange Web Service calendar '%s'\n", pvt->owner->name);
144  return -1;
145  }
146 
147  ne_strnzcpy(username, pvt->user, NE_ABUFSIZ);
148  ne_strnzcpy(secret, pvt->secret, NE_ABUFSIZ);
149 
150  return 0;
151 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
struct ast_calendar * owner
const ast_string_field name
Definition: calendar.h:127
const ast_string_field secret
const ast_string_field user

◆ cdata()

static int cdata ( void *  userdata,
int  state,
const char *  cdata,
size_t  len 
)
static

Definition at line 327 of file res_calendar_ews.c.

References AST_CALENDAR_BS_BUSY, AST_CALENDAR_BS_BUSY_TENTATIVE, AST_CALENDAR_BS_FREE, ast_copy_string(), ast_debug, ast_log, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_strlen(), ast_calendar_event::busy_state, xml_context::cdata, ast_calendar_event::end, xml_context::event, LOG_ERROR, mstime_to_time_t(), xml_context::op, ast_calendar_event::start, XML_EVENT_BUSY, XML_EVENT_CATEGORY, XML_EVENT_END, XML_EVENT_START, and XML_OP_CREATE.

Referenced by chan_pjsip_set_rtp_peer(), rtp_direct_media_data_create(), rtp_direct_media_data_destroy(), send_direct_media_request(), and send_ews_request_and_parse().

328 {
329  struct xml_context *ctx = userdata;
330  char data[len + 1];
331 
332  /* !!! DON'T USE AST_STRING_FIELD FUNCTIONS HERE, JUST COLLECT CTX->CDATA !!! */
334  return 0;
335  }
336 
337  if (!ctx->event) {
338  ast_log(LOG_ERROR, "Parsing event data, but event object does not exist!\n");
339  return 1;
340  }
341 
342  if (!ctx->cdata) {
343  ast_log(LOG_ERROR, "String for storing CDATA is unitialized!\n");
344  return 1;
345  }
346 
347  ast_copy_string(data, cdata, len + 1);
348 
349  switch (state) {
350  case XML_EVENT_START:
351  ctx->event->start = mstime_to_time_t(data);
352  break;
353  case XML_EVENT_END:
354  ctx->event->end = mstime_to_time_t(data);
355  break;
356  case XML_EVENT_BUSY:
357  if (!strcmp(data, "Busy") || !strcmp(data, "OOF")) {
358  ast_debug(3, "EWS: XML: Busy: yes\n");
360  }
361  else if (!strcmp(data, "Tentative")) {
362  ast_debug(3, "EWS: XML: Busy: tentative\n");
364  }
365  else {
366  ast_debug(3, "EWS: XML: Busy: no\n");
368  }
369  break;
370  case XML_EVENT_CATEGORY:
371  if (ast_str_strlen(ctx->cdata) == 0) {
372  ast_str_set(&ctx->cdata, 0, "%s", data);
373  } else {
374  ast_str_append(&ctx->cdata, 0, ",%s", data);
375  }
376  break;
377  default:
378  ast_str_append(&ctx->cdata, 0, "%s", data);
379  }
380 
381  ast_debug(5, "EWS: XML: CDATA: %s\n", ast_str_buffer(ctx->cdata));
382 
383  return 0;
384 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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
static time_t mstime_to_time_t(char *mstime)
enum ast_calendar_busy_state busy_state
Definition: calendar.h:107
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int cdata(void *userdata, int state, const char *cdata, size_t len)
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct ast_str * cdata
enum xml_op op
struct ast_calendar_event * event

◆ endelm()

static int endelm ( void *  userdata,
int  state,
const char *  nspace,
const char *  name 
)
static

Definition at line 386 of file res_calendar_ews.c.

References ao2_container_count(), ao2_link, ast_calendar_merge_events(), ast_calendar_unref_event(), ast_calloc, ast_debug, ast_free, AST_LIST_INSERT_TAIL, ast_log, ast_str_buffer(), ast_str_reset(), ast_str_strlen(), ast_strdup, ast_string_field_set, ast_calendar_event::attendees, ast_calendar_event::categories, categories, xml_context::cdata, ast_calendar_attendee::data, ast_calendar_event::description, xml_context::event, ewscal_pvt::events, ewscal_pvt::items, ast_calendar_event::location, LOG_ERROR, calendar_id::next, xml_context::op, ast_calendar_event::organizer, ewscal_pvt::owner, ast_calendar_event::priority, xml_context::pvt, ast_calendar_event::summary, XML_EVENT_DESCRIPTION, XML_EVENT_EMAIL_ADDRESS, XML_OP_CREATE, and XML_OP_FIND.

Referenced by send_ews_request_and_parse().

387 {
388  struct xml_context *ctx = userdata;
389 
390  ast_debug(5, "EWS: XML: End: %s\n", name);
391  if (ctx->op == XML_OP_FIND || ctx->op == XML_OP_CREATE) {
392  return NE_XML_DECLINE;
393  }
394 
395  if (!strcmp(name, "Subject")) {
396  /* Event name end*/
397  ast_string_field_set(ctx->event, summary, ast_str_buffer(ctx->cdata));
398  ast_debug(3, "EWS: XML: Summary: %s\n", ctx->event->summary);
399  ast_str_reset(ctx->cdata);
400  } else if (!strcmp(name, "Body") && state == XML_EVENT_DESCRIPTION) {
401  /* Event body/description end */
402  ast_string_field_set(ctx->event, description, ast_str_buffer(ctx->cdata));
403  ast_debug(3, "EWS: XML: Description: %s\n", ctx->event->description);
404  ast_str_reset(ctx->cdata);
405  } else if (!strcmp(name, "Organizer")) {
406  /* Event organizer end */
407  ast_string_field_set(ctx->event, organizer, ast_str_buffer(ctx->cdata));
408  ast_debug(3, "EWS: XML: Organizer: %s\n", ctx->event->organizer);
409  ast_str_reset(ctx->cdata);
410  } else if (!strcmp(name, "Location")) {
411  /* Event location end */
412  ast_string_field_set(ctx->event, location, ast_str_buffer(ctx->cdata));
413  ast_debug(3, "EWS: XML: Location: %s\n", ctx->event->location);
414  ast_str_reset(ctx->cdata);
415  } else if (!strcmp(name, "Categories")) {
416  /* Event categories end */
418  ast_debug(3, "EWS: XML: Categories: %s\n", ctx->event->categories);
419  ast_str_reset(ctx->cdata);
420  } else if (!strcmp(name, "Importance")) {
421  /* Event importance end */
422  if (!strcmp(ast_str_buffer(ctx->cdata), "Low")) {
423  ctx->event->priority = 9;
424  } else if (!strcmp(ast_str_buffer(ctx->cdata), "Normal")) {
425  ctx->event->priority = 5;
426  } else if (!strcmp(ast_str_buffer(ctx->cdata), "High")) {
427  ctx->event->priority = 1;
428  }
429  ast_debug(3, "EWS: XML: Importance: %s (%d)\n", ast_str_buffer(ctx->cdata), ctx->event->priority);
430  ast_str_reset(ctx->cdata);
431  } else if (state == XML_EVENT_EMAIL_ADDRESS) {
432  struct ast_calendar_attendee *attendee;
433 
434  if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
435  ctx->event = ast_calendar_unref_event(ctx->event);
436  return 1;
437  }
438 
439  if (ast_str_strlen(ctx->cdata)) {
440  attendee->data = ast_strdup(ast_str_buffer(ctx->cdata));
441  AST_LIST_INSERT_TAIL(&ctx->event->attendees, attendee, next);
442  } else {
443  ast_free(attendee);
444  }
445  ast_debug(3, "EWS: XML: attendee address '%s'\n", ast_str_buffer(ctx->cdata));
446  ast_str_reset(ctx->cdata);
447  } else if (!strcmp(name, "CalendarItem")) {
448  /* Event end */
449  ast_debug(3, "EWS: XML: </CalendarItem>\n");
450  ast_free(ctx->cdata);
451  if (ctx->event) {
452  ao2_link(ctx->pvt->events, ctx->event);
453  ctx->event = ast_calendar_unref_event(ctx->event);
454  } else {
455  ast_log(LOG_ERROR, "Event data ended in XML, but event object does not exist!\n");
456  return 1;
457  }
458  } else if (!strcmp(name, "Envelope")) {
459  /* Events end */
460  ast_debug(3, "EWS: XML: %d of %u event(s) has been parsed…\n", ao2_container_count(ctx->pvt->events), ctx->pvt->items);
461  if (ao2_container_count(ctx->pvt->events) >= ctx->pvt->items) {
462  ast_debug(3, "EWS: XML: All events has been parsed, merging…\n");
464  }
465  }
466 
467  return 0;
468 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ao2_container * events
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
struct ast_calendar_attendee * next
Definition: calendar.h:89
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
const ast_string_field description
Definition: calendar.h:101
const ast_string_field organizer
Definition: calendar.h:101
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_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
const ast_string_field location
Definition: calendar.h:101
struct ast_calendar * owner
struct ewscal_pvt * pvt
unsigned int items
#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[]
static const char name[]
Definition: cdr_mysql.c:74
#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
const ast_string_field categories
Definition: calendar.h:101
struct ast_calendar_event::attendees attendees
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
struct ast_str * cdata
const ast_string_field summary
Definition: calendar.h:101
enum xml_op op
struct ast_calendar_event * event
#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

◆ ewscal_destructor()

static void ewscal_destructor ( void *  obj)
static

Definition at line 113 of file res_calendar_ews.c.

References ao2_callback, ao2_ref, ast_debug, ast_string_field_free_memory, ewscal_pvt::events, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ewscal_pvt::session, and ewscal_pvt::uri.

Referenced by ewscal_load_calendar().

114 {
115  struct ewscal_pvt *pvt = obj;
116 
117  ast_debug(1, "Destroying pvt for Exchange Web Service calendar %s\n", "pvt->owner->name");
118  if (pvt->session) {
119  ne_session_destroy(pvt->session);
120  }
121  ne_uri_free(&pvt->uri);
123 
125 
126  ao2_ref(pvt->events, -1);
127 }
struct ao2_container * events
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#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
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
ne_session * session

◆ ewscal_load_calendar()

static void * ewscal_load_calendar ( void *  data)
static

Definition at line 770 of file res_calendar_ews.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(), ewscal_pvt::events, ewscal_destructor(), LOG_ERROR, LOG_WARNING, ast_variable::name, ast_calendar::name, ast_variable::next, NULL, ewscal_pvt::owner, ast_calendar::refresh, refreshlock, ewscal_pvt::secret, ewscal_pvt::session, ssl_verify(), ast_calendar::tech_pvt, ast_calendar::unload, ast_calendar::unloading, unref_ewscal(), update_ewscal(), ewscal_pvt::uri, url, ewscal_pvt::url, ewscal_pvt::user, and ast_variable::value.

771 {
772  struct ewscal_pvt *pvt;
773  const struct ast_config *cfg;
774  struct ast_variable *v;
775  struct ast_calendar *cal = void_data;
777 
778  ast_debug(5, "EWS: ewscal_load_calendar()\n");
779 
780  if (!(cal && (cfg = ast_calendar_config_acquire()))) {
781  ast_log(LOG_ERROR, "You must enable calendar support for res_ewscal to load\n");
782  return NULL;
783  }
784 
785  if (ao2_trylock(cal)) {
786  if (cal->unloading) {
787  ast_log(LOG_WARNING, "Unloading module, load_calendar cancelled.\n");
788  } else {
789  ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
790  }
792  return NULL;
793  }
794 
795  if (!(pvt = ao2_alloc(sizeof(*pvt), ewscal_destructor))) {
796  ast_log(LOG_ERROR, "Could not allocate ewscal_pvt structure for calendar: %s\n", cal->name);
798  return NULL;
799  }
800 
801  pvt->owner = cal;
802 
803  if (!(pvt->events = ast_calendar_event_container_alloc())) {
804  ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
805  pvt = unref_ewscal(pvt);
806  ao2_unlock(cal);
808  return NULL;
809  }
810 
811  if (ast_string_field_init(pvt, 32)) {
812  ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
813  pvt = unref_ewscal(pvt);
814  ao2_unlock(cal);
816  return NULL;
817  }
818 
819  for (v = ast_variable_browse(cfg, cal->name); v; v = v->next) {
820  if (!strcasecmp(v->name, "url")) {
821  ast_string_field_set(pvt, url, v->value);
822  } else if (!strcasecmp(v->name, "user")) {
823  ast_string_field_set(pvt, user, v->value);
824  } else if (!strcasecmp(v->name, "secret")) {
825  ast_string_field_set(pvt, secret, v->value);
826  }
827  }
828 
830 
831  if (ast_strlen_zero(pvt->url)) {
832  ast_log(LOG_WARNING, "No URL was specified for Exchange Web Service calendar '%s' - skipping.\n", cal->name);
833  pvt = unref_ewscal(pvt);
834  ao2_unlock(cal);
835  return NULL;
836  }
837 
838  if (ne_uri_parse(pvt->url, &pvt->uri) || pvt->uri.host == NULL || pvt->uri.path == NULL) {
839  ast_log(LOG_WARNING, "Could not parse url '%s' for Exchange Web Service calendar '%s' - skipping.\n", pvt->url, cal->name);
840  pvt = unref_ewscal(pvt);
841  ao2_unlock(cal);
842  return NULL;
843  }
844 
845  if (pvt->uri.scheme == NULL) {
846  pvt->uri.scheme = "http";
847  }
848 
849  if (pvt->uri.port == 0) {
850  pvt->uri.port = ne_uri_defaultport(pvt->uri.scheme);
851  }
852 
853  ast_debug(3, "ne_uri.scheme = %s\n", pvt->uri.scheme);
854  ast_debug(3, "ne_uri.host = %s\n", pvt->uri.host);
855  ast_debug(3, "ne_uri.port = %u\n", pvt->uri.port);
856  ast_debug(3, "ne_uri.path = %s\n", pvt->uri.path);
857  ast_debug(3, "user = %s\n", pvt->user);
858  ast_debug(3, "secret = %s\n", pvt->secret);
859 
860  pvt->session = ne_session_create(pvt->uri.scheme, pvt->uri.host, pvt->uri.port);
861  ne_redirect_register(pvt->session);
862  ne_set_server_auth(pvt->session, auth_credentials, pvt);
863  ne_set_useragent(pvt->session, "Asterisk");
864 
865  if (!strcasecmp(pvt->uri.scheme, "https")) {
866  ne_ssl_trust_default_ca(pvt->session);
867  ne_ssl_set_verify(pvt->session, ssl_verify, pvt);
868  }
869 
870  cal->tech_pvt = pvt;
871 
872  ast_mutex_init(&refreshlock);
873 
874  /* Load it the first time */
875  update_ewscal(pvt);
876 
877  ao2_unlock(cal);
878 
879  /* The only writing from another thread will be if unload is true */
880  for (;;) {
881  struct timeval tv = ast_tvnow();
882  struct timespec ts = {0,};
883 
884  ts.tv_sec = tv.tv_sec + (60 * pvt->owner->refresh);
885 
886  ast_mutex_lock(&refreshlock);
887  while (!pvt->owner->unloading) {
888  if (ast_cond_timedwait(&pvt->owner->unload, &refreshlock, &ts) == ETIMEDOUT) {
889  break;
890  }
891  }
892  ast_mutex_unlock(&refreshlock);
893 
894  if (pvt->owner->unloading) {
895  ast_debug(10, "Skipping refresh since we got a shutdown signal\n");
896  return NULL;
897  }
898 
899  ast_debug(10, "Refreshing after %d minute timeout\n", pvt->owner->refresh);
900 
901  update_ewscal(pvt);
902  }
903 
904  return NULL;
905 }
struct ast_variable * next
ast_cond_t unload
Definition: calendar.h:135
static int ssl_verify(void *userdata, int failures, const ne_ssl_certificate *cert)
unsigned int unloading
Definition: calendar.h:136
static int auth_credentials(void *userdata, const char *realm, int attempts, char *username, char *secret)
struct ao2_container * events
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.
static int update_ewscal(struct ewscal_pvt *pvt)
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
static void ewscal_destructor(void *obj)
#define NULL
Definition: resample.c:96
#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
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
struct ast_calendar * owner
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
const ast_string_field secret
const ast_string_field user
#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
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
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
#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
ne_session * session
Structure for mutex and tracking information.
Definition: lock.h:135
static void * unref_ewscal(void *obj)
const ast_string_field url
#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

◆ ewscal_write_event()

static int ewscal_write_event ( struct ast_calendar_event event)
static

Definition at line 562 of file res_calendar_ews.c.

References ast_free, ast_str_append(), ast_str_create, ast_str_set(), ast_strdupa, ast_calendar_event::busy_state, ast_calendar_event::categories, categories, ast_calendar_event::description, end, ast_calendar_event::end, ast_calendar_event::location, msstatus(), mstime(), NULL, xml_context::op, ewscal_pvt::owner, ast_calendar_event::priority, xml_context::pvt, request(), send_ews_request_and_parse(), ast_calendar_event::start, strsep(), ast_calendar_event::summary, ast_calendar::tech_pvt, and XML_OP_CREATE.

563 {
564  struct ast_str *request;
565  struct ewscal_pvt *pvt = event->owner->tech_pvt;
566  char start[21], end[21];
567  struct xml_context ctx = {
568  .op = XML_OP_CREATE,
569  .pvt = pvt,
570  };
571  int ret;
572  char *category, *categories;
573 
574  if (!pvt) {
575  return -1;
576  }
577 
578  if (!(request = ast_str_create(1024))) {
579  return -1;
580  }
581 
582  ast_str_set(&request, 0,
583  "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
584  "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
585  "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "
586  "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">"
587  "<soap:Body>"
588  "<CreateItem xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" "
589  "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\" "
590  "SendMeetingInvitations=\"SendToNone\" >"
591  "<SavedItemFolderId>"
592  "<t:DistinguishedFolderId Id=\"calendar\"/>"
593  "</SavedItemFolderId>"
594  "<Items>"
595  "<t:CalendarItem xmlns=\"http://schemas.microsoft.com/exchange/services/2006/types\">"
596  "<Subject>%s</Subject>"
597  "<Body BodyType=\"Text\">%s</Body>"
598  "<ReminderIsSet>false</ReminderIsSet>"
599  "<Start>%s</Start>"
600  "<End>%s</End>"
601  "<IsAllDayEvent>false</IsAllDayEvent>"
602  "<LegacyFreeBusyStatus>%s</LegacyFreeBusyStatus>"
603  "<Location>%s</Location>",
604  event->summary,
605  event->description,
606  mstime(event->start, start, sizeof(start)),
607  mstime(event->end, end, sizeof(end)),
608  msstatus(event->busy_state),
609  event->location
610  );
611  /* Event priority */
612  switch (event->priority) {
613  case 1:
614  case 2:
615  case 3:
616  case 4:
617  ast_str_append(&request, 0, "<Importance>High</Importance>");
618  break;
619  case 5:
620  ast_str_append(&request, 0, "<Importance>Normal</Importance>");
621  break;
622  case 6:
623  case 7:
624  case 8:
625  case 9:
626  ast_str_append(&request, 0, "<Importance>Low</Importance>");
627  break;
628  }
629  /* Event categories*/
630  if (strlen(event->categories) > 0) {
631  ast_str_append(&request, 0, "<Categories>");
632  categories = ast_strdupa(event->categories); /* Duplicate string, since strsep() is destructive */
633  category = strsep(&categories, ",");
634  while (category != NULL) {
635  ast_str_append(&request, 0, "<String>%s</String>", category);
636  category = strsep(&categories, ",");
637  }
638  ast_str_append(&request, 0, "</Categories>");
639  }
640  /* Finish request */
641  ast_str_append(&request, 0, "</t:CalendarItem></Items></CreateItem></soap:Body></soap:Envelope>");
642 
643  ret = send_ews_request_and_parse(request, &ctx);
644 
645  ast_free(request);
646 
647  return ret;
648 }
static int send_ews_request_and_parse(struct ast_str *request, struct xml_context *ctx)
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
enum ast_calendar_busy_state busy_state
Definition: calendar.h:107
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
const ast_string_field description
Definition: calendar.h:101
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
void * tech_pvt
Definition: calendar.h:119
const ast_string_field location
Definition: calendar.h:101
struct ast_calendar * owner
struct ewscal_pvt * pvt
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
struct association categories[]
#define ast_free(a)
Definition: astmm.h:182
static const char * mstime(time_t t, char *buf, size_t buflen)
static int request(void *obj)
Definition: chan_pjsip.c:2559
const ast_string_field categories
Definition: calendar.h:101
char * strsep(char **str, const char *delims)
static const char * msstatus(enum ast_calendar_busy_state state)
const ast_string_field summary
Definition: calendar.h:101
enum xml_op op
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ get_ewscal_ids_for()

static struct calendar_id* get_ewscal_ids_for ( struct ewscal_pvt pvt)
static

Definition at line 650 of file res_calendar_ews.c.

References ast_debug, ast_free, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, ast_localtime(), ast_log, ast_str_create, ast_str_set(), ast_strftime(), ast_tvnow(), end, xml_context::ids, LOG_ERROR, NULL, xml_context::op, ewscal_pvt::owner, xml_context::pvt, request(), send_ews_request_and_parse(), ast_calendar::timeframe, and XML_OP_FIND.

Referenced by update_ewscal().

651 {
652  char start[21], end[21];
653  struct ast_tm tm;
654  struct timeval tv;
655  struct ast_str *request;
656  struct xml_context ctx = {
657  .op = XML_OP_FIND,
658  .pvt = pvt,
659  };
660 
661  ast_debug(5, "EWS: get_ewscal_ids_for()\n");
662 
663  if (!pvt) {
664  ast_log(LOG_ERROR, "There is no private!\n");
665  return NULL;
666  }
667 
668  /* Prepare timeframe strings */
669  tv = ast_tvnow();
670  ast_localtime(&tv, &tm, "UTC");
671  ast_strftime(start, sizeof(start), "%FT%TZ", &tm);
672  tv.tv_sec += 60 * pvt->owner->timeframe;
673  ast_localtime(&tv, &tm, "UTC");
674  ast_strftime(end, sizeof(end), "%FT%TZ", &tm);
675 
676  /* Prepare SOAP request */
677  if (!(request = ast_str_create(512))) {
678  return NULL;
679  }
680 
681  ast_str_set(&request, 0,
682  "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
683  "xmlns:ns1=\"http://schemas.microsoft.com/exchange/services/2006/types\" "
684  "xmlns:ns2=\"http://schemas.microsoft.com/exchange/services/2006/messages\">"
685  "<SOAP-ENV:Body>"
686  "<ns2:FindItem Traversal=\"Shallow\">"
687  "<ns2:ItemShape>"
688  "<ns1:BaseShape>IdOnly</ns1:BaseShape>"
689  "</ns2:ItemShape>"
690  "<ns2:CalendarView StartDate=\"%s\" EndDate=\"%s\"/>" /* Timeframe */
691  "<ns2:ParentFolderIds>"
692  "<ns1:DistinguishedFolderId Id=\"calendar\"/>"
693  "</ns2:ParentFolderIds>"
694  "</ns2:FindItem>"
695  "</SOAP-ENV:Body>"
696  "</SOAP-ENV:Envelope>",
697  start, end /* Timeframe */
698  );
699 
701 
702  /* Dispatch request and parse response as XML */
703  if (send_ews_request_and_parse(request, &ctx)) {
704  ast_free(request);
705  return NULL;
706  }
707 
708  /* Cleanup */
709  ast_free(request);
710 
711  return AST_LIST_FIRST(&ctx.ids);
712 }
struct xml_context::ids ids
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
static int send_ews_request_and_parse(struct ast_str *request, struct xml_context *ctx)
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int timeframe
Definition: calendar.h:133
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_calendar * owner
struct ewscal_pvt * pvt
#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
#define ast_free(a)
Definition: astmm.h:182
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
static int request(void *obj)
Definition: chan_pjsip.c:2559
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
enum xml_op op
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ get_soap_action()

static const char* get_soap_action ( enum xml_op  op)
static

Definition at line 497 of file res_calendar_ews.c.

References XML_OP_CREATE, XML_OP_FIND, and XML_OP_GET.

Referenced by send_ews_request_and_parse().

498 {
499  switch (op) {
500  case XML_OP_FIND:
501  return "\"http://schemas.microsoft.com/exchange/services/2006/messages/FindItem\"";
502  case XML_OP_GET:
503  return "\"http://schemas.microsoft.com/exchange/services/2006/messages/GetItem\"";
504  case XML_OP_CREATE:
505  return "\"http://schemas.microsoft.com/exchange/services/2006/messages/CreateItem\"";
506  }
507 
508  return "";
509 }
enum xml_op op

◆ load_module()

static int load_module ( void  )
static

Definition at line 907 of file res_calendar_ews.c.

References ast_calendar_register(), ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and LOG_ERROR.

Referenced by unload_module().

908 {
909  /* Actualy, 0.29.1 is required (because of NTLM authentication), but this
910  * function does not support matching patch version.
911  *
912  * The ne_version_match function returns non-zero if the library
913  * version is not of major version major, or the minor version
914  * is less than minor. For neon versions 0.x, every minor
915  * version is assumed to be incompatible with every other minor
916  * version.
917  *
918  * I.e. for version 1.2..1.9 we would do ne_version_match(1, 2)
919  * but for version 0.29 and 0.30 we need two checks. */
920  if (ne_version_match(0, 29) && ne_version_match(0, 30)) {
921  ast_log(LOG_ERROR, "Exchange Web Service calendar module require neon >= 0.29.1, but %s is installed.\n", ne_version_string());
923  }
924 
925  if (ast_calendar_register(&ewscal_tech) && (ne_sock_init() == 0)) {
927  }
928 
930 }
int ast_calendar_register(struct ast_calendar_tech *tech)
Register a new calendar technology.
Definition: res_calendar.c:549
static struct ast_calendar_tech ewscal_tech
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78

◆ msstatus()

static const char* msstatus ( enum ast_calendar_busy_state  state)
static

Definition at line 483 of file res_calendar_ews.c.

References AST_CALENDAR_BS_BUSY, AST_CALENDAR_BS_BUSY_TENTATIVE, and AST_CALENDAR_BS_FREE.

Referenced by ewscal_write_event().

484 {
485  switch (state) {
487  return "Tentative";
489  return "Busy";
491  return "Free";
492  default:
493  return "";
494  }
495 }

◆ mstime()

static const char* mstime ( time_t  t,
char *  buf,
size_t  buflen 
)
static

Definition at line 470 of file res_calendar_ews.c.

References ast_localtime(), ast_strftime(), and S_OR.

Referenced by ewscal_write_event().

471 {
472  struct timeval tv = {
473  .tv_sec = t,
474  };
475  struct ast_tm tm;
476 
477  ast_localtime(&tv, &tm, "utc");
478  ast_strftime(buf, buflen, "%FT%TZ", &tm);
479 
480  return S_OR(buf, "");
481 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79

◆ mstime_to_time_t()

static time_t mstime_to_time_t ( char *  mstime)
static

Definition at line 163 of file res_calendar_ews.c.

References ast_mktime(), and ast_strptime().

Referenced by cdata().

164 {
165  struct ast_tm tm;
166  struct timeval tv;
167 
168  if (ast_strptime(mstime, "%FT%TZ", &tm)) {
169  tv = ast_mktime(&tm, "UTC");
170  return tv.tv_sec;
171  }
172  return 0;
173 }
char * ast_strptime(const char *s, const char *format, struct ast_tm *tm)
Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use.
Definition: localtime.c:2550
static const char * mstime(time_t t, char *buf, size_t buflen)
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2357

◆ parse_ewscal_id()

static int parse_ewscal_id ( struct ewscal_pvt pvt,
const char *  id 
)
static

Definition at line 714 of file res_calendar_ews.c.

References ast_free, ast_str_create, ast_str_set(), xml_context::pvt, request(), send_ews_request_and_parse(), and XML_OP_GET.

Referenced by update_ewscal().

714  {
715  struct ast_str *request;
716  struct xml_context ctx = {
717  .pvt = pvt,
718  .op = XML_OP_GET,
719  };
720 
721  if (!(request = ast_str_create(512))) {
722  return -1;
723  }
724 
725  ast_str_set(&request, 0,
726  "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
727  "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "
728  "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">"
729  "<soap:Body>"
730  "<GetItem xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\">"
731  "<ItemShape>"
732  "<t:BaseShape>AllProperties</t:BaseShape>"
733  "</ItemShape>"
734  "<ItemIds>"
735  "<t:ItemId Id=\"%s\"/>"
736  "</ItemIds>"
737  "</GetItem>"
738  "</soap:Body>"
739  "</soap:Envelope>", id
740  );
741 
742  if (send_ews_request_and_parse(request, &ctx)) {
743  ast_free(request);
744  return -1;
745  }
746 
747  ast_free(request);
748 
749  return 0;
750 }
static int send_ews_request_and_parse(struct ast_str *request, struct xml_context *ctx)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
struct ewscal_pvt * pvt
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_free(a)
Definition: astmm.h:182
static int request(void *obj)
Definition: chan_pjsip.c:2559
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ send_ews_request_and_parse()

static int send_ews_request_and_parse ( struct ast_str request,
struct xml_context ctx 
)
static

Definition at line 511 of file res_calendar_ews.c.

References ast_debug, ast_log, ast_str_buffer(), ast_str_strlen(), cdata(), endelm(), get_soap_action(), LOG_ERROR, LOG_WARNING, xml_context::op, xml_context::parser, xml_context::pvt, ewscal_pvt::session, startelm(), ewscal_pvt::uri, and ewscal_pvt::url.

Referenced by ewscal_write_event(), get_ewscal_ids_for(), and parse_ewscal_id().

512 {
513  int ret;
514  ne_request *req;
515  ne_xml_parser *parser;
516 
517  ast_debug(3, "EWS: HTTP request...\n");
518  if (!(ctx && ctx->pvt)) {
519  ast_log(LOG_ERROR, "There is no private!\n");
520  return -1;
521  }
522 
523  if (!ast_str_strlen(request)) {
524  ast_log(LOG_ERROR, "No request to send!\n");
525  return -1;
526  }
527 
528  ast_debug(3, "%s\n", ast_str_buffer(request));
529 
530  /* Prepare HTTP POST request */
531  req = ne_request_create(ctx->pvt->session, "POST", ctx->pvt->uri.path);
532  ne_set_request_flag(req, NE_REQFLAG_IDEMPOTENT, 0);
533 
534  /* Set headers--should be application/soap+xml, but MS… :/ */
535  ne_add_request_header(req, "Content-Type", "text/xml; charset=utf-8");
536  ne_add_request_header(req, "SOAPAction", get_soap_action(ctx->op));
537 
538  /* Set body to SOAP request */
539  ne_set_request_body_buffer(req, ast_str_buffer(request), ast_str_strlen(request));
540 
541  /* Prepare XML parser */
542  parser = ne_xml_create();
543  ctx->parser = parser;
544  ne_xml_push_handler(parser, startelm, cdata, endelm, ctx); /* Callbacks */
545 
546  /* Dispatch request and parse response as XML */
547  ret = ne_xml_dispatch_request(req, parser);
548  if (ret != NE_OK) { /* Error handling */
549  ast_log(LOG_WARNING, "Unable to communicate with Exchange Web Service at '%s': %s\n", ctx->pvt->url, ne_get_error(ctx->pvt->session));
550  ne_request_destroy(req);
551  ne_xml_destroy(parser);
552  return -1;
553  }
554 
555  /* Cleanup */
556  ne_request_destroy(req);
557  ne_xml_destroy(parser);
558 
559  return 0;
560 }
static int startelm(void *userdata, int parent, const char *nspace, const char *name, const char **atts)
#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 ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static const char * get_soap_action(enum xml_op op)
struct ewscal_pvt * pvt
ne_xml_parser * parser
#define LOG_ERROR
Definition: logger.h:285
static int cdata(void *userdata, int state, const char *cdata, size_t len)
static int endelm(void *userdata, int state, const char *nspace, const char *name)
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
enum xml_op op
ne_session * session
const ast_string_field url

◆ ssl_verify()

static int ssl_verify ( void *  userdata,
int  failures,
const ne_ssl_certificate *  cert 
)
static

Definition at line 153 of file res_calendar_ews.c.

References ast_log, LOG_WARNING, ast_calendar::name, and ewscal_pvt::owner.

Referenced by ewscal_load_calendar().

154 {
155  struct ewscal_pvt *pvt = userdata;
156  if (failures & NE_SSL_UNTRUSTED) {
157  ast_log(LOG_WARNING, "Untrusted SSL certificate for calendar %s!\n", pvt->owner->name);
158  return 0;
159  }
160  return 1; /* NE_SSL_NOTYETVALID, NE_SSL_EXPIRED, NE_SSL_IDMISMATCH */
161 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
struct ast_calendar * owner
const ast_string_field name
Definition: calendar.h:127

◆ startelm()

static int startelm ( void *  userdata,
int  parent,
const char *  nspace,
const char *  name,
const char **  atts 
)
static

Definition at line 175 of file res_calendar_ews.c.

References ast_calendar_event_alloc(), ast_calendar_merge_events(), ast_calloc, ast_debug, ast_free, AST_LIST_INSERT_TAIL, ast_log, ast_str_buffer(), ast_str_create, ast_str_reset(), ast_str_set(), ast_string_field_set, xml_context::cdata, xml_context::event, ewscal_pvt::events, calendar_id::id, xml_context::ids, ewscal_pvt::items, LOG_ERROR, calendar_id::next, NULL, xml_context::op, ewscal_pvt::owner, xml_context::parser, xml_context::pvt, XML_EVENT_ATTENDEE, XML_EVENT_ATTENDEE_LIST, XML_EVENT_BUSY, XML_EVENT_CALENDAR_ITEM, XML_EVENT_CATEGORIES, XML_EVENT_CATEGORY, XML_EVENT_DESCRIPTION, XML_EVENT_EMAIL_ADDRESS, XML_EVENT_END, XML_EVENT_IMPORTANCE, XML_EVENT_LOCATION, XML_EVENT_MAILBOX, XML_EVENT_NAME, XML_EVENT_ORGANIZER, XML_EVENT_START, XML_OP_CREATE, and XML_OP_FIND.

Referenced by send_ews_request_and_parse().

176 {
177  struct xml_context *ctx = userdata;
178 
179  ast_debug(5, "EWS: XML: Start: %s\n", name);
180  if (ctx->op == XML_OP_CREATE) {
181  return NE_XML_DECLINE;
182  }
183 
184  /* Nodes needed for traversing until CalendarItem is found */
185  if (!strcmp(name, "Envelope") ||
186  (!strcmp(name, "Body") && parent != XML_EVENT_CALENDAR_ITEM) ||
187  !strcmp(name, "FindItemResponse") ||
188  !strcmp(name, "GetItemResponse") ||
189  !strcmp(name, "CreateItemResponse") ||
190  !strcmp(name, "ResponseMessages") ||
191  !strcmp(name, "FindItemResponseMessage") || !strcmp(name, "GetItemResponseMessage") ||
192  !strcmp(name, "Items")
193  ) {
194  return 1;
195  } else if (!strcmp(name, "RootFolder")) {
196  /* Get number of events */
197  unsigned int items;
198 
199  ast_debug(3, "EWS: XML: <RootFolder>\n");
200  if (sscanf(ne_xml_get_attr(ctx->parser, atts, NULL, "TotalItemsInView"), "%u", &items) != 1) {
201  /* Couldn't read enything */
202  ne_xml_set_error(ctx->parser, "Could't read number of events.");
203  return NE_XML_ABORT;
204  }
205 
206  ast_debug(3, "EWS: %u calendar items to load\n", items);
207  ctx->pvt->items = items;
208  if (items < 1) {
209  /* Stop processing XML if there are no events */
211  return NE_XML_DECLINE;
212  }
213  return 1;
214  } else if (!strcmp(name, "CalendarItem")) {
215  /* Event start */
216  ast_debug(3, "EWS: XML: <CalendarItem>\n");
217  if (!(ctx->pvt && ctx->pvt->owner)) {
218  ast_log(LOG_ERROR, "Require a private structure with an owner\n");
219  return NE_XML_ABORT;
220  }
221 
222  ctx->event = ast_calendar_event_alloc(ctx->pvt->owner);
223  if (!ctx->event) {
224  ast_log(LOG_ERROR, "Could not allocate an event!\n");
225  return NE_XML_ABORT;
226  }
227 
228  ctx->cdata = ast_str_create(64);
229  if (!ctx->cdata) {
230  ast_log(LOG_ERROR, "Could not allocate CDATA!\n");
231  return NE_XML_ABORT;
232  }
233 
235  } else if (!strcmp(name, "ItemId")) {
236  /* Event UID */
237  if (ctx->op == XML_OP_FIND) {
238  struct calendar_id *id;
239  if (!(id = ast_calloc(1, sizeof(*id)))) {
240  return NE_XML_ABORT;
241  }
242  if (!(id->id = ast_str_create(256))) {
243  ast_free(id);
244  return NE_XML_ABORT;
245  }
246  ast_str_set(&id->id, 0, "%s", ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
247  AST_LIST_INSERT_TAIL(&ctx->ids, id, next);
248  ast_debug(3, "EWS_FIND: XML: UID: %s\n", ast_str_buffer(id->id));
249  } else {
250  ast_debug(3, "EWS_GET: XML: UID: %s\n", ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
251  ast_string_field_set(ctx->event, uid, ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
252  }
253  return XML_EVENT_NAME;
254  } else if (!strcmp(name, "Subject")) {
255  /* Event name */
256  if (!ctx->cdata) {
257  return NE_XML_ABORT;
258  }
259  ast_str_reset(ctx->cdata);
260  return XML_EVENT_NAME;
261  } else if (!strcmp(name, "Body") && parent == XML_EVENT_CALENDAR_ITEM) {
262  /* Event body/description */
263  if (!ctx->cdata) {
264  return NE_XML_ABORT;
265  }
266  ast_str_reset(ctx->cdata);
267  return XML_EVENT_DESCRIPTION;
268  } else if (!strcmp(name, "Start")) {
269  /* Event start time */
270  return XML_EVENT_START;
271  } else if (!strcmp(name, "End")) {
272  /* Event end time */
273  return XML_EVENT_END;
274  } else if (!strcmp(name, "LegacyFreeBusyStatus")) {
275  /* Event busy state */
276  return XML_EVENT_BUSY;
277  } else if (!strcmp(name, "Organizer") ||
278  (parent == XML_EVENT_ORGANIZER && (!strcmp(name, "Mailbox") ||
279  !strcmp(name, "Name")))) {
280  /* Event organizer */
281  if (!ctx->cdata) {
282  return NE_XML_ABORT;
283  }
284  ast_str_reset(ctx->cdata);
285  return XML_EVENT_ORGANIZER;
286  } else if (!strcmp(name, "Location")) {
287  /* Event location */
288  if (!ctx->cdata) {
289  return NE_XML_ABORT;
290  }
291  ast_str_reset(ctx->cdata);
292  return XML_EVENT_LOCATION;
293  } else if (!strcmp(name, "Categories")) {
294  /* Event categories */
295  if (!ctx->cdata) {
296  return NE_XML_ABORT;
297  }
298  ast_str_reset(ctx->cdata);
299  return XML_EVENT_CATEGORIES;
300  } else if (parent == XML_EVENT_CATEGORIES && !strcmp(name, "String")) {
301  /* Event category */
302  return XML_EVENT_CATEGORY;
303  } else if (!strcmp(name, "Importance")) {
304  /* Event importance (priority) */
305  if (!ctx->cdata) {
306  return NE_XML_ABORT;
307  }
308  ast_str_reset(ctx->cdata);
309  return XML_EVENT_IMPORTANCE;
310  } else if (!strcmp(name, "RequiredAttendees") || !strcmp(name, "OptionalAttendees")) {
312  } else if (!strcmp(name, "Attendee") && parent == XML_EVENT_ATTENDEE_LIST) {
313  return XML_EVENT_ATTENDEE;
314  } else if (!strcmp(name, "Mailbox") && parent == XML_EVENT_ATTENDEE) {
315  return XML_EVENT_MAILBOX;
316  } else if (!strcmp(name, "EmailAddress") && parent == XML_EVENT_MAILBOX) {
317  if (!ctx->cdata) {
318  return NE_XML_ABORT;
319  }
320  ast_str_reset(ctx->cdata);
322  }
323 
324  return NE_XML_DECLINE;
325 }
struct xml_context::ids ids
struct ao2_container * events
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
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
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_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_str * id
struct ast_calendar * owner
struct ewscal_pvt * pvt
ne_xml_parser * parser
struct calendar_id * next
unsigned int items
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
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
enum queue_result id
Definition: app_queue.c:1507
struct ast_str * cdata
enum xml_op op
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
struct ast_calendar_event * event
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 932 of file res_calendar_ews.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().

933 {
934  ne_sock_exit();
936 
937  return 0;
938 }
static struct ast_calendar_tech ewscal_tech
void ast_calendar_unregister(struct ast_calendar_tech *tech)
Unregister a new calendar technology.
Definition: res_calendar.c:587

◆ unref_ewscal()

static void * unref_ewscal ( void *  obj)
static

Definition at line 129 of file res_calendar_ews.c.

References ao2_ref, ast_debug, and NULL.

Referenced by ewscal_load_calendar().

130 {
131  struct ewscal_pvt *pvt = obj;
132 
133  ast_debug(5, "EWS: unref_ewscal()\n");
134  ao2_ref(pvt, -1);
135  return NULL;
136 }
#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

◆ update_ewscal()

static int update_ewscal ( struct ewscal_pvt pvt)
static

Definition at line 752 of file res_calendar_ews.c.

References ast_free, AST_LIST_NEXT, ast_str_buffer(), get_ewscal_ids_for(), calendar_id::id, calendar_id::next, and parse_ewscal_id().

Referenced by ewscal_load_calendar().

753 {
754  struct calendar_id *id_head;
755  struct calendar_id *iter;
756 
757  if (!(id_head = get_ewscal_ids_for(pvt))) {
758  return 0;
759  }
760 
761  for (iter = id_head; iter; iter = AST_LIST_NEXT(iter, next)) {
762  parse_ewscal_id(pvt, ast_str_buffer(iter->id));
763  ast_free(iter->id);
764  ast_free(iter);
765  }
766 
767  return 0;
768 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
struct ast_str * id
static struct calendar_id * get_ewscal_ids_for(struct ewscal_pvt *pvt)
struct calendar_id * next
#define ast_free(a)
Definition: astmm.h:182
static int parse_ewscal_id(struct ewscal_pvt *pvt, const char *id)

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk MS Exchange Web Service 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 = "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 946 of file res_calendar_ews.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 946 of file res_calendar_ews.c.

◆ ewscal_tech

struct ast_calendar_tech ewscal_tech
static

Definition at line 52 of file res_calendar_ews.c.