Wed Jan 8 2020 09:50:18

Asterisk developer's documentation


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/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  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)
 
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PLUGIN, }
 
static 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
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.

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

static void __reg_module ( void  )
static

Definition at line 943 of file res_calendar_ews.c.

static void __unreg_module ( void  )
static

Definition at line 943 of file res_calendar_ews.c.

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

Definition at line 137 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().

138 {
139  struct ewscal_pvt *pvt = userdata;
140 
141  if (attempts > 1) {
142  ast_log(LOG_WARNING, "Invalid username or password for Exchange Web Service calendar '%s'\n", pvt->owner->name);
143  return -1;
144  }
145 
146  ne_strnzcpy(username, pvt->user, NE_ABUFSIZ);
147  ne_strnzcpy(secret, pvt->secret, NE_ABUFSIZ);
148 
149  return 0;
150 }
#define LOG_WARNING
Definition: logger.h:144
struct ast_calendar * owner
const ast_string_field name
Definition: calendar.h:127
const ast_string_field secret
const ast_string_field user
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static char secret[50]
Definition: chan_h323.c:148
static int cdata ( void *  userdata,
int  state,
const char *  cdata,
size_t  len 
)
static

Definition at line 326 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(), ast_calendar_event::start, XML_EVENT_BUSY, XML_EVENT_CATEGORY, XML_EVENT_END, XML_EVENT_START, and XML_OP_CREATE.

327 {
328  struct xml_context *ctx = userdata;
329  char data[len + 1];
330 
331  /* !!! DON'T USE AST_STRING_FIELD FUNCTIONS HERE, JUST COLLECT CTX->CDATA !!! */
333  return 0;
334  }
335 
336  if (!ctx->event) {
337  ast_log(LOG_ERROR, "Parsing event data, but event object does not exist!\n");
338  return 1;
339  }
340 
341  if (!ctx->cdata) {
342  ast_log(LOG_ERROR, "String for storing CDATA is unitialized!\n");
343  return 1;
344  }
345 
346  ast_copy_string(data, cdata, len + 1);
347 
348  switch (state) {
349  case XML_EVENT_START:
350  ctx->event->start = mstime_to_time_t(data);
351  break;
352  case XML_EVENT_END:
353  ctx->event->end = mstime_to_time_t(data);
354  break;
355  case XML_EVENT_BUSY:
356  if (!strcmp(data, "Busy") || !strcmp(data, "OOF")) {
357  ast_debug(3, "EWS: XML: Busy: yes\n");
359  }
360  else if (!strcmp(data, "Tentative")) {
361  ast_debug(3, "EWS: XML: Busy: tentative\n");
363  }
364  else {
365  ast_debug(3, "EWS: XML: Busy: no\n");
367  }
368  break;
369  case XML_EVENT_CATEGORY:
370  if (ast_str_strlen(ctx->cdata) == 0) {
371  ast_str_set(&ctx->cdata, 0, "%s", data);
372  } else {
373  ast_str_append(&ctx->cdata, 0, ",%s", data);
374  }
375  break;
376  default:
377  ast_str_append(&ctx->cdata, 0, "%s", data);
378  }
379 
380  ast_debug(5, "EWS: XML: CDATA: %s\n", ast_str_buffer(ctx->cdata));
381 
382  return 0;
383 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
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:900
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:874
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define LOG_ERROR
Definition: logger.h:155
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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:471
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_str * cdata
enum xml_op op
struct ast_calendar_event * event
static int endelm ( void *  userdata,
int  state,
const char *  nspace,
const char *  name 
)
static

Definition at line 385 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, 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, 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().

386 {
387  struct xml_context *ctx = userdata;
388 
389  ast_debug(5, "EWS: XML: End: %s\n", name);
390  if (ctx->op == XML_OP_FIND || ctx->op == XML_OP_CREATE) {
391  return NE_XML_DECLINE;
392  }
393 
394  if (!strcmp(name, "Subject")) {
395  /* Event name end*/
396  ast_string_field_set(ctx->event, summary, ast_str_buffer(ctx->cdata));
397  ast_debug(3, "EWS: XML: Summary: %s\n", ctx->event->summary);
398  ast_str_reset(ctx->cdata);
399  } else if (!strcmp(name, "Body") && state == XML_EVENT_DESCRIPTION) {
400  /* Event body/description end */
401  ast_string_field_set(ctx->event, description, ast_str_buffer(ctx->cdata));
402  ast_debug(3, "EWS: XML: Description: %s\n", ctx->event->description);
403  ast_str_reset(ctx->cdata);
404  } else if (!strcmp(name, "Organizer")) {
405  /* Event organizer end */
406  ast_string_field_set(ctx->event, organizer, ast_str_buffer(ctx->cdata));
407  ast_debug(3, "EWS: XML: Organizer: %s\n", ctx->event->organizer);
408  ast_str_reset(ctx->cdata);
409  } else if (!strcmp(name, "Location")) {
410  /* Event location end */
411  ast_string_field_set(ctx->event, location, ast_str_buffer(ctx->cdata));
412  ast_debug(3, "EWS: XML: Location: %s\n", ctx->event->location);
413  ast_str_reset(ctx->cdata);
414  } else if (!strcmp(name, "Categories")) {
415  /* Event categories end */
416  ast_string_field_set(ctx->event, categories, ast_str_buffer(ctx->cdata));
417  ast_debug(3, "EWS: XML: Categories: %s\n", ctx->event->categories);
418  ast_str_reset(ctx->cdata);
419  } else if (!strcmp(name, "Importance")) {
420  /* Event importance end */
421  if (!strcmp(ast_str_buffer(ctx->cdata), "Low")) {
422  ctx->event->priority = 9;
423  } else if (!strcmp(ast_str_buffer(ctx->cdata), "Normal")) {
424  ctx->event->priority = 5;
425  } else if (!strcmp(ast_str_buffer(ctx->cdata), "High")) {
426  ctx->event->priority = 1;
427  }
428  ast_debug(3, "EWS: XML: Importance: %s (%d)\n", ast_str_buffer(ctx->cdata), ctx->event->priority);
429  ast_str_reset(ctx->cdata);
430  } else if (state == XML_EVENT_EMAIL_ADDRESS) {
431  struct ast_calendar_attendee *attendee;
432 
433  if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
434  ctx->event = ast_calendar_unref_event(ctx->event);
435  return 1;
436  }
437 
438  if (ast_str_strlen(ctx->cdata)) {
439  attendee->data = ast_strdup(ast_str_buffer(ctx->cdata));
440  AST_LIST_INSERT_TAIL(&ctx->event->attendees, attendee, next);
441  } else {
442  ast_free(attendee);
443  }
444  ast_debug(3, "EWS: XML: attendee address '%s'\n", ast_str_buffer(ctx->cdata));
445  ast_str_reset(ctx->cdata);
446  } else if (!strcmp(name, "CalendarItem")) {
447  /* Event end */
448  ast_debug(3, "EWS: XML: </CalendarItem>\n");
449  ast_free(ctx->cdata);
450  if (ctx->event) {
451  ao2_link(ctx->pvt->events, ctx->event);
452  ctx->event = ast_calendar_unref_event(ctx->event);
453  } else {
454  ast_log(LOG_ERROR, "Event data ended in XML, but event object does not exist!\n");
455  return 1;
456  }
457  } else if (!strcmp(name, "Envelope")) {
458  /* Events end */
459  ast_debug(3, "EWS: XML: %d of %u event(s) has been parsed…\n", ao2_container_count(ctx->pvt->events), ctx->pvt->items);
460  if (ao2_container_count(ctx->pvt->events) >= ctx->pvt->items) {
461  ast_debug(3, "EWS: XML: All events has been parsed, merging…\n");
463  }
464  }
465 
466  return 0;
467 }
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
struct ao2_container * events
#define ast_strdup(a)
Definition: astmm.h:109
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
struct ast_calendar_attendee * next
Definition: calendar.h:89
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.
Definition: res_calendar.c:961
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
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:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static const char name[]
#define ast_free(a)
Definition: astmm.h:97
struct ast_calendar_event * ast_calendar_unref_event(struct ast_calendar_event *event)
Unreference an ast_calendar_event.
Definition: res_calendar.c:300
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:436
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
#define ast_calloc(a, b)
Definition: astmm.h:82
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:344
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, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and ewscal_pvt::session.

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  }
122 
123  ao2_callback(pvt->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
124 
125  ao2_ref(pvt->events, -1);
126 }
struct ao2_container * events
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:910
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
ne_session * session
static void * ewscal_load_calendar ( void *  data)
static

Definition at line 769 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, ewscal_pvt::owner, ast_calendar::refresh, refreshlock, ewscal_pvt::secret, 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.

770 {
771  struct ewscal_pvt *pvt;
772  const struct ast_config *cfg;
773  struct ast_variable *v;
774  struct ast_calendar *cal = void_data;
776 
777  ast_debug(5, "EWS: ewscal_load_calendar()\n");
778 
779  if (!(cal && (cfg = ast_calendar_config_acquire()))) {
780  ast_log(LOG_ERROR, "You must enable calendar support for res_ewscal to load\n");
781  return NULL;
782  }
783 
784  if (ao2_trylock(cal)) {
785  if (cal->unloading) {
786  ast_log(LOG_WARNING, "Unloading module, load_calendar cancelled.\n");
787  } else {
788  ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
789  }
791  return NULL;
792  }
793 
794  if (!(pvt = ao2_alloc(sizeof(*pvt), ewscal_destructor))) {
795  ast_log(LOG_ERROR, "Could not allocate ewscal_pvt structure for calendar: %s\n", cal->name);
797  return NULL;
798  }
799 
800  pvt->owner = cal;
801 
802  if (!(pvt->events = ast_calendar_event_container_alloc())) {
803  ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
804  pvt = unref_ewscal(pvt);
805  ao2_unlock(cal);
807  return NULL;
808  }
809 
810  if (ast_string_field_init(pvt, 32)) {
811  ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
812  pvt = unref_ewscal(pvt);
813  ao2_unlock(cal);
815  return NULL;
816  }
817 
818  for (v = ast_variable_browse(cfg, cal->name); v; v = v->next) {
819  if (!strcasecmp(v->name, "url")) {
820  ast_string_field_set(pvt, url, v->value);
821  } else if (!strcasecmp(v->name, "user")) {
822  ast_string_field_set(pvt, user, v->value);
823  } else if (!strcasecmp(v->name, "secret")) {
825  }
826  }
827 
829 
830  if (ast_strlen_zero(pvt->url)) {
831  ast_log(LOG_WARNING, "No URL was specified for Exchange Web Service calendar '%s' - skipping.\n", cal->name);
832  pvt = unref_ewscal(pvt);
833  ao2_unlock(cal);
834  return NULL;
835  }
836 
837  if (ne_uri_parse(pvt->url, &pvt->uri) || pvt->uri.host == NULL || pvt->uri.path == NULL) {
838  ast_log(LOG_WARNING, "Could not parse url '%s' for Exchange Web Service calendar '%s' - skipping.\n", pvt->url, cal->name);
839  pvt = unref_ewscal(pvt);
840  ao2_unlock(cal);
841  return NULL;
842  }
843 
844  if (pvt->uri.scheme == NULL) {
845  pvt->uri.scheme = "http";
846  }
847 
848  if (pvt->uri.port == 0) {
849  pvt->uri.port = ne_uri_defaultport(pvt->uri.scheme);
850  }
851 
852  ast_debug(3, "ne_uri.scheme = %s\n", pvt->uri.scheme);
853  ast_debug(3, "ne_uri.host = %s\n", pvt->uri.host);
854  ast_debug(3, "ne_uri.port = %u\n", pvt->uri.port);
855  ast_debug(3, "ne_uri.path = %s\n", pvt->uri.path);
856  ast_debug(3, "user = %s\n", pvt->user);
857  ast_debug(3, "secret = %s\n", pvt->secret);
858 
859  pvt->session = ne_session_create(pvt->uri.scheme, pvt->uri.host, pvt->uri.port);
860  ne_redirect_register(pvt->session);
861  ne_set_server_auth(pvt->session, auth_credentials, pvt);
862  ne_set_useragent(pvt->session, "Asterisk");
863 
864  if (!strcasecmp(pvt->uri.scheme, "https")) {
865  ne_ssl_trust_default_ca(pvt->session);
866  ne_ssl_set_verify(pvt->session, ssl_verify, pvt);
867  }
868 
869  cal->tech_pvt = pvt;
870 
871  ast_mutex_init(&refreshlock);
872 
873  /* Load it the first time */
874  update_ewscal(pvt);
875 
876  ao2_unlock(cal);
877 
878  /* The only writing from another thread will be if unload is true */
879  for (;;) {
880  struct timeval tv = ast_tvnow();
881  struct timespec ts = {0,};
882 
883  ts.tv_sec = tv.tv_sec + (60 * pvt->owner->refresh);
884 
885  ast_mutex_lock(&refreshlock);
886  while (!pvt->owner->unloading) {
887  if (ast_cond_timedwait(&pvt->owner->unload, &refreshlock, &ts) == ETIMEDOUT) {
888  break;
889  }
890  }
891  ast_mutex_unlock(&refreshlock);
892 
893  if (pvt->owner->unloading) {
894  ast_debug(10, "Skipping refresh since we got a shutdown signal\n");
895  return NULL;
896  }
897 
898  ast_debug(10, "Refreshing after %d minute timeout\n", pvt->owner->refresh);
899 
900  update_ewscal(pvt);
901  }
902 
903  return NULL;
904 }
ast_cond_t unload
Definition: calendar.h:133
static int ssl_verify(void *userdata, int failures, const ne_ssl_certificate *cert)
static int auth_credentials(void *userdata, const char *realm, int attempts, char *username, char *secret)
int unloading
Definition: calendar.h:134
struct ao2_container * events
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
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:142
#define ast_mutex_lock(a)
Definition: lock.h:155
#define ao2_unlock(a)
Definition: astobj2.h:497
static void ewscal_destructor(void *obj)
struct ast_config * ast_calendar_config_acquire(void)
Grab and lock pointer to the calendar config (read only)
Definition: res_calendar.c:237
void * tech_pvt
Definition: calendar.h:119
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * value
Definition: config.h:79
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
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:625
const char * name
Definition: config.h:77
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:155
#define ao2_trylock(a)
Definition: astobj2.h:506
static ast_mutex_t refreshlock
Definition: res_calendar.c:204
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
structure to hold users read from users.conf
static char secret[50]
Definition: chan_h323.c:148
struct timeval tv
struct ast_variable * next
Definition: config.h:82
#define ast_mutex_init(pmutex)
Definition: lock.h:152
Asterisk calendar structure.
Definition: calendar.h:117
void ast_calendar_config_release(void)
Release the calendar config.
Definition: res_calendar.c:249
static char url[512]
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:172
ne_session * session
Structure for mutex and tracking information.
Definition: lock.h:121
static void * unref_ewscal(void *obj)
const ast_string_field url
#define ast_mutex_unlock(a)
Definition: lock.h:156
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static int ewscal_write_event ( struct ast_calendar_event event)
static

Definition at line 561 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, ast_calendar_event::description, ast_calendar_event::end, ast_calendar_event::location, msstatus(), mstime(), xml_context::op, ewscal_pvt::owner, ast_calendar_event::priority, xml_context::pvt, send_ews_request_and_parse(), ast_calendar_event::start, strsep(), ast_calendar_event::summary, ast_calendar::tech_pvt, and XML_OP_CREATE.

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

Definition at line 649 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(), xml_context::ids, LOG_ERROR, xml_context::op, ewscal_pvt::owner, xml_context::pvt, send_ews_request_and_parse(), ast_calendar::timeframe, and XML_OP_FIND.

Referenced by update_ewscal().

650 {
651  char start[21], end[21];
652  struct ast_tm tm;
653  struct timeval tv;
654  struct ast_str *request;
655  struct xml_context ctx = {
656  .op = XML_OP_FIND,
657  .pvt = pvt,
658  };
659 
660  ast_debug(5, "EWS: get_ewscal_ids_for()\n");
661 
662  if (!pvt) {
663  ast_log(LOG_ERROR, "There is no private!\n");
664  return NULL;
665  }
666 
667  /* Prepare timeframe strings */
668  tv = ast_tvnow();
669  ast_localtime(&tv, &tm, "UTC");
670  ast_strftime(start, sizeof(start), "%FT%TZ", &tm);
671  tv.tv_sec += 60 * pvt->owner->timeframe;
672  ast_localtime(&tv, &tm, "UTC");
673  ast_strftime(end, sizeof(end), "%FT%TZ", &tm);
674 
675  /* Prepare SOAP request */
676  if (!(request = ast_str_create(512))) {
677  return NULL;
678  }
679 
680  ast_str_set(&request, 0,
681  "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
682  "xmlns:ns1=\"http://schemas.microsoft.com/exchange/services/2006/types\" "
683  "xmlns:ns2=\"http://schemas.microsoft.com/exchange/services/2006/messages\">"
684  "<SOAP-ENV:Body>"
685  "<ns2:FindItem Traversal=\"Shallow\">"
686  "<ns2:ItemShape>"
687  "<ns1:BaseShape>IdOnly</ns1:BaseShape>"
688  "</ns2:ItemShape>"
689  "<ns2:CalendarView StartDate=\"%s\" EndDate=\"%s\"/>" /* Timeframe */
690  "<ns2:ParentFolderIds>"
691  "<ns1:DistinguishedFolderId Id=\"calendar\"/>"
692  "</ns2:ParentFolderIds>"
693  "</ns2:FindItem>"
694  "</SOAP-ENV:Body>"
695  "</SOAP-ENV:Envelope>",
696  start, end /* Timeframe */
697  );
698 
700 
701  /* Dispatch request and parse response as XML */
702  if (send_ews_request_and_parse(request, &ctx)) {
703  ast_free(request);
704  return NULL;
705  }
706 
707  /* Cleanup */
708  ast_free(request);
709 
710  return AST_LIST_FIRST(&ctx.ids);
711 }
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:1570
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
int timeframe
Definition: calendar.h:131
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:874
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_calendar * owner
struct ewscal_pvt * pvt
#define LOG_ERROR
Definition: logger.h:155
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
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:2351
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:666
struct timeval tv
enum xml_op op
static const char* get_soap_action ( enum xml_op  op)
static

Definition at line 496 of file res_calendar_ews.c.

References XML_OP_CREATE, XML_OP_FIND, and XML_OP_GET.

Referenced by send_ews_request_and_parse().

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

Definition at line 906 of file res_calendar_ews.c.

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

907 {
908  /* Actualy, 0.29.1 is required (because of NTLM authentication), but this
909  * function does not support matching patch version.
910  *
911  * The ne_version_match function returns non-zero if the library
912  * version is not of major version major, or the minor version
913  * is less than minor. For neon versions 0.x, every minor
914  * version is assumed to be incompatible with every other minor
915  * version.
916  *
917  * I.e. for version 1.2..1.9 we would do ne_version_match(1, 2)
918  * but for version 0.29 and 0.30 we need two checks. */
919  if (ne_version_match(0, 29) && ne_version_match(0, 30)) {
920  ast_log(LOG_ERROR, "Exchange Web Service calendar module require neon >= 0.29.1, but %s is installed.\n", ne_version_string());
922  }
923 
924  if (ast_calendar_register(&ewscal_tech) && (ne_sock_init() == 0)) {
926  }
927 
929 }
int ast_calendar_register(struct ast_calendar_tech *tech)
Register a new calendar technology.
Definition: res_calendar.c:490
static struct ast_calendar_tech ewscal_tech
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static const char* msstatus ( enum ast_calendar_busy_state  state)
static

Definition at line 482 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().

483 {
484  switch (state) {
486  return "Tentative";
488  return "Busy";
490  return "Free";
491  default:
492  return "";
493  }
494 }
static const char* mstime ( time_t  t,
char *  buf,
size_t  buflen 
)
static

Definition at line 469 of file res_calendar_ews.c.

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

Referenced by ewscal_write_event().

470 {
471  struct timeval tv = {
472  .tv_sec = t,
473  };
474  struct ast_tm tm;
475 
476  ast_localtime(&tv, &tm, "utc");
477  ast_strftime(buf, buflen, "%FT%TZ", &tm);
478 
479  return S_OR(buf, "");
480 }
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:1570
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:2351
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
struct timeval tv
static time_t mstime_to_time_t ( char *  mstime)
static

Definition at line 162 of file res_calendar_ews.c.

References ast_mktime(), and ast_strptime().

Referenced by cdata().

163 {
164  struct ast_tm tm;
165  struct timeval tv;
166 
167  if (ast_strptime(mstime, "%FT%TZ", &tm)) {
168  tv = ast_mktime(&tm, "UTC");
169  return tv.tv_sec;
170  }
171  return 0;
172 }
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:2377
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:2185
struct timeval tv
static int parse_ewscal_id ( struct ewscal_pvt pvt,
const char *  id 
)
static

Definition at line 713 of file res_calendar_ews.c.

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

Referenced by update_ewscal().

713  {
714  struct ast_str *request;
715  struct xml_context ctx = {
716  .pvt = pvt,
717  .op = XML_OP_GET,
718  };
719 
720  if (!(request = ast_str_create(512))) {
721  return -1;
722  }
723 
724  ast_str_set(&request, 0,
725  "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
726  "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "
727  "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">"
728  "<soap:Body>"
729  "<GetItem xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\">"
730  "<ItemShape>"
731  "<t:BaseShape>AllProperties</t:BaseShape>"
732  "</ItemShape>"
733  "<ItemIds>"
734  "<t:ItemId Id=\"%s\"/>"
735  "</ItemIds>"
736  "</GetItem>"
737  "</soap:Body>"
738  "</soap:Envelope>", id
739  );
740 
741  if (send_ews_request_and_parse(request, &ctx)) {
742  ast_free(request);
743  return -1;
744  }
745 
746  ast_free(request);
747 
748  return 0;
749 }
static int send_ews_request_and_parse(struct ast_str *request, struct xml_context *ctx)
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
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:874
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:364
#define ast_free(a)
Definition: astmm.h:97
static int send_ews_request_and_parse ( struct ast_str request,
struct xml_context ctx 
)
static

Definition at line 510 of file res_calendar_ews.c.

References ast_debug, ast_log(), ast_str_buffer(), ast_str_strlen(), 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().

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

Definition at line 152 of file res_calendar_ews.c.

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

Referenced by ewscal_load_calendar().

153 {
154  struct ewscal_pvt *pvt = userdata;
155  if (failures & NE_SSL_UNTRUSTED) {
156  ast_log(LOG_WARNING, "Untrusted SSL certificate for calendar %s!\n", pvt->owner->name);
157  return 0;
158  }
159  return 1; /* NE_SSL_NOTYETVALID, NE_SSL_EXPIRED, NE_SSL_IDMISMATCH */
160 }
#define LOG_WARNING
Definition: logger.h:144
struct ast_calendar * owner
const ast_string_field name
Definition: calendar.h:127
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int startelm ( void *  userdata,
int  parent,
const char *  nspace,
const char *  name,
const char **  atts 
)
static

Definition at line 174 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, 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().

175 {
176  struct xml_context *ctx = userdata;
177 
178  ast_debug(5, "EWS: XML: Start: %s\n", name);
179  if (ctx->op == XML_OP_CREATE) {
180  return NE_XML_DECLINE;
181  }
182 
183  /* Nodes needed for traversing until CalendarItem is found */
184  if (!strcmp(name, "Envelope") ||
185  (!strcmp(name, "Body") && parent != XML_EVENT_CALENDAR_ITEM) ||
186  !strcmp(name, "FindItemResponse") ||
187  !strcmp(name, "GetItemResponse") ||
188  !strcmp(name, "CreateItemResponse") ||
189  !strcmp(name, "ResponseMessages") ||
190  !strcmp(name, "FindItemResponseMessage") || !strcmp(name, "GetItemResponseMessage") ||
191  !strcmp(name, "Items")
192  ) {
193  return 1;
194  } else if (!strcmp(name, "RootFolder")) {
195  /* Get number of events */
196  unsigned int items;
197 
198  ast_debug(3, "EWS: XML: <RootFolder>\n");
199  if (sscanf(ne_xml_get_attr(ctx->parser, atts, NULL, "TotalItemsInView"), "%u", &items) != 1) {
200  /* Couldn't read enything */
201  ne_xml_set_error(ctx->parser, "Could't read number of events.");
202  return NE_XML_ABORT;
203  }
204 
205  ast_debug(3, "EWS: %u calendar items to load\n", items);
206  ctx->pvt->items = items;
207  if (items < 1) {
208  /* Stop processing XML if there are no events */
210  return NE_XML_DECLINE;
211  }
212  return 1;
213  } else if (!strcmp(name, "CalendarItem")) {
214  /* Event start */
215  ast_debug(3, "EWS: XML: <CalendarItem>\n");
216  if (!(ctx->pvt && ctx->pvt->owner)) {
217  ast_log(LOG_ERROR, "Require a private structure with an owner\n");
218  return NE_XML_ABORT;
219  }
220 
221  ctx->event = ast_calendar_event_alloc(ctx->pvt->owner);
222  if (!ctx->event) {
223  ast_log(LOG_ERROR, "Could not allocate an event!\n");
224  return NE_XML_ABORT;
225  }
226 
227  ctx->cdata = ast_str_create(64);
228  if (!ctx->cdata) {
229  ast_log(LOG_ERROR, "Could not allocate CDATA!\n");
230  return NE_XML_ABORT;
231  }
232 
234  } else if (!strcmp(name, "ItemId")) {
235  /* Event UID */
236  if (ctx->op == XML_OP_FIND) {
237  struct calendar_id *id;
238  if (!(id = ast_calloc(1, sizeof(*id)))) {
239  return NE_XML_ABORT;
240  }
241  if (!(id->id = ast_str_create(256))) {
242  ast_free(id);
243  return NE_XML_ABORT;
244  }
245  ast_str_set(&id->id, 0, "%s", ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
246  AST_LIST_INSERT_TAIL(&ctx->ids, id, next);
247  ast_debug(3, "EWS_FIND: XML: UID: %s\n", ast_str_buffer(id->id));
248  } else {
249  ast_debug(3, "EWS_GET: XML: UID: %s\n", ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
250  ast_string_field_set(ctx->event, uid, ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
251  }
252  return XML_EVENT_NAME;
253  } else if (!strcmp(name, "Subject")) {
254  /* Event name */
255  if (!ctx->cdata) {
256  return NE_XML_ABORT;
257  }
258  ast_str_reset(ctx->cdata);
259  return XML_EVENT_NAME;
260  } else if (!strcmp(name, "Body") && parent == XML_EVENT_CALENDAR_ITEM) {
261  /* Event body/description */
262  if (!ctx->cdata) {
263  return NE_XML_ABORT;
264  }
265  ast_str_reset(ctx->cdata);
266  return XML_EVENT_DESCRIPTION;
267  } else if (!strcmp(name, "Start")) {
268  /* Event start time */
269  return XML_EVENT_START;
270  } else if (!strcmp(name, "End")) {
271  /* Event end time */
272  return XML_EVENT_END;
273  } else if (!strcmp(name, "LegacyFreeBusyStatus")) {
274  /* Event busy state */
275  return XML_EVENT_BUSY;
276  } else if (!strcmp(name, "Organizer") ||
277  (parent == XML_EVENT_ORGANIZER && (!strcmp(name, "Mailbox") ||
278  !strcmp(name, "Name")))) {
279  /* Event organizer */
280  if (!ctx->cdata) {
281  return NE_XML_ABORT;
282  }
283  ast_str_reset(ctx->cdata);
284  return XML_EVENT_ORGANIZER;
285  } else if (!strcmp(name, "Location")) {
286  /* Event location */
287  if (!ctx->cdata) {
288  return NE_XML_ABORT;
289  }
290  ast_str_reset(ctx->cdata);
291  return XML_EVENT_LOCATION;
292  } else if (!strcmp(name, "Categories")) {
293  /* Event categories */
294  if (!ctx->cdata) {
295  return NE_XML_ABORT;
296  }
297  ast_str_reset(ctx->cdata);
298  return XML_EVENT_CATEGORIES;
299  } else if (parent == XML_EVENT_CATEGORIES && !strcmp(name, "String")) {
300  /* Event category */
301  return XML_EVENT_CATEGORY;
302  } else if (!strcmp(name, "Importance")) {
303  /* Event importance (priority) */
304  if (!ctx->cdata) {
305  return NE_XML_ABORT;
306  }
307  ast_str_reset(ctx->cdata);
308  return XML_EVENT_IMPORTANCE;
309  } else if (!strcmp(name, "RequiredAttendees") || !strcmp(name, "OptionalAttendees")) {
311  } else if (!strcmp(name, "Attendee") && parent == XML_EVENT_ATTENDEE_LIST) {
312  return XML_EVENT_ATTENDEE;
313  } else if (!strcmp(name, "Mailbox") && parent == XML_EVENT_ATTENDEE) {
314  return XML_EVENT_MAILBOX;
315  } else if (!strcmp(name, "EmailAddress") && parent == XML_EVENT_MAILBOX) {
316  if (!ctx->cdata) {
317  return NE_XML_ABORT;
318  }
319  ast_str_reset(ctx->cdata);
321  }
322 
323  return NE_XML_DECLINE;
324 }
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:497
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
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:874
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.
Definition: res_calendar.c:961
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
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:603
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static const char name[]
#define ast_free(a)
Definition: astmm.h:97
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:436
#define ast_calloc(a, b)
Definition: astmm.h:82
enum queue_result id
Definition: app_queue.c:1090
struct ast_str * cdata
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:344
static int unload_module ( void  )
static

Definition at line 931 of file res_calendar_ews.c.

References ast_calendar_unregister().

932 {
933  ne_sock_exit();
935 
936  return 0;
937 }
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:523
static void * unref_ewscal ( void *  obj)
static

Definition at line 128 of file res_calendar_ews.c.

References ao2_ref, and ast_debug.

Referenced by ewscal_load_calendar().

129 {
130  struct ewscal_pvt *pvt = obj;
131 
132  ast_debug(5, "EWS: unref_ewscal()\n");
133  ao2_ref(pvt, -1);
134  return NULL;
135 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static int update_ewscal ( struct ewscal_pvt pvt)
static

Definition at line 751 of file res_calendar_ews.c.

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

Referenced by ewscal_load_calendar().

752 {
753  struct calendar_id *id_head;
754  struct calendar_id *iter;
755 
756  if (!(id_head = get_ewscal_ids_for(pvt))) {
757  return 0;
758  }
759 
760  for (iter = id_head; iter; iter = AST_LIST_NEXT(iter, next)) {
761  parse_ewscal_id(pvt, ast_str_buffer(iter->id));
762  ast_free(iter->id);
763  ast_free(iter);
764  }
765 
766  return 0;
767 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
#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:97
static int parse_ewscal_id(struct ewscal_pvt *pvt, const char *id)

Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PLUGIN, }
static

Definition at line 943 of file res_calendar_ews.c.

Definition at line 943 of file res_calendar_ews.c.

struct ast_calendar_tech ewscal_tech
static

Definition at line 52 of file res_calendar_ews.c.