Asterisk - The Open Source Telephony Project GIT-master-2de1a68
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 = AST_BUILDOPT_SUM, .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.

82 {
84 XML_EVENT_NAME = 10,
98};
@ XML_EVENT_EMAIL_ADDRESS
@ XML_EVENT_IMPORTANCE
@ XML_EVENT_BUSY
@ XML_EVENT_ATTENDEE_LIST
@ XML_EVENT_DESCRIPTION
@ XML_EVENT_END
@ XML_EVENT_CALENDAR_ITEM
@ XML_EVENT_CATEGORY
@ XML_EVENT_START
@ XML_EVENT_LOCATION
@ XML_EVENT_CATEGORIES
@ XML_EVENT_MAILBOX
@ XML_EVENT_NAME
@ XML_EVENT_ORGANIZER
@ XML_EVENT_ATTENDEE

◆ 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.

61 {
62 XML_OP_FIND = 100,
65};
@ XML_OP_GET
@ XML_OP_FIND
@ XML_OP_CREATE

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.

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 ast_log
Definition: astobj2.c:42
#define LOG_WARNING
const ast_string_field name
Definition: calendar.h:129
struct ast_calendar * owner
const ast_string_field user
const ast_string_field secret

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

Referenced by ewscal_load_calendar().

◆ 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.

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;
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}
@ AST_CALENDAR_BS_FREE
Definition: calendar.h:84
@ AST_CALENDAR_BS_BUSY_TENTATIVE
Definition: calendar.h:85
@ AST_CALENDAR_BS_BUSY
Definition: calendar.h:86
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
static int cdata(void *userdata, int state, const char *cdata, size_t len)
static time_t mstime_to_time_t(char *mstime)
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:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
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:1113
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
enum ast_calendar_busy_state busy_state
Definition: calendar.h:109
struct ast_calendar_event * event
enum xml_op op
struct ast_str * cdata

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, cdata(), ast_calendar_event::end, xml_context::event, len(), 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 cdata(), 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().

◆ 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.

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)))) {
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);
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}
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
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.
struct ast_calendar_event * ast_calendar_unref_event(struct ast_calendar_event *event)
Unreference an ast_calendar_event.
Definition: res_calendar.c:323
static const char name[]
Definition: format_mp3.c:68
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
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:693
struct ast_calendar_attendee * next
Definition: calendar.h:91
const ast_string_field location
Definition: calendar.h:103
const ast_string_field description
Definition: calendar.h:103
const ast_string_field categories
Definition: calendar.h:103
const ast_string_field organizer
Definition: calendar.h:103
struct ast_calendar_event::attendees attendees
const ast_string_field summary
Definition: calendar.h:103
struct ao2_container * events
unsigned int items
struct ewscal_pvt * pvt
struct association categories[]

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, name, ast_calendar_attendee::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().

◆ ewscal_destructor()

static void ewscal_destructor ( void *  obj)
static

Definition at line 113 of file res_calendar_ews.c.

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}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
#define NULL
Definition: resample.c:96
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
ne_session * session

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().

◆ ewscal_load_calendar()

static void * ewscal_load_calendar ( void *  data)
static

Definition at line 770 of file res_calendar_ews.c.

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
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")) {
822 } else if (!strcasecmp(v->name, "user")) {
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
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
887 while (!pvt->owner->unloading) {
888 if (ast_cond_timedwait(&pvt->owner->unload, &refreshlock, &ts) == ETIMEDOUT) {
889 break;
890 }
891 }
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}
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_trylock(a)
Definition: astobj2.h:739
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
void ast_calendar_config_release(void)
Release the calendar config.
Definition: res_calendar.c:272
struct ao2_container * ast_calendar_event_container_alloc(void)
Allocate an astobj2 container for ast_calendar_event objects.
Definition: res_calendar.c:691
const struct ast_config * ast_calendar_config_acquire(void)
Grab and lock pointer to the calendar config (read only)
Definition: res_calendar.c:260
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
static ast_mutex_t refreshlock
Definition: res_calendar.c:227
static void * unref_ewscal(void *obj)
static int update_ewscal(struct ewscal_pvt *pvt)
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)
static void ewscal_destructor(void *obj)
static char url[512]
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Asterisk calendar structure.
Definition: calendar.h:119
void * tech_pvt
Definition: calendar.h:121
ast_cond_t unload
Definition: calendar.h:137
unsigned int unloading
Definition: calendar.h:138
Structure for mutex and tracking information.
Definition: lock.h:135
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
const ast_string_field url
structure to hold users read from users.conf
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

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_calendar::name, ast_variable::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, ewscal_pvt::url, url, ewscal_pvt::user, and ast_variable::value.

◆ ewscal_write_event()

static int ewscal_write_event ( struct ast_calendar_event event)
static

Definition at line 562 of file res_calendar_ews.c.

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
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
644
646
647 return ret;
648}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
static int request(void *obj)
Definition: chan_pjsip.c:2601
char * end
Definition: eagi_proxy.c:73
char * strsep(char **str, const char *delims)
static int send_ews_request_and_parse(struct ast_str *request, struct xml_context *ctx)
static const char * mstime(time_t t, char *buf, size_t buflen)
static const char * msstatus(enum ast_calendar_busy_state state)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
Support for dynamic strings.
Definition: strings.h:623
Definition: astman.c:222

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

◆ 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.

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
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 */
705 return NULL;
706 }
707
708 /* Cleanup */
710
711 return AST_LIST_FIRST(&ctx.ids);
712}
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
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
int timeframe
Definition: calendar.h:135
struct xml_context::ids ids

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().

◆ get_soap_action()

static const char * get_soap_action ( enum xml_op  op)
static

Definition at line 497 of file res_calendar_ews.c.

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}

References XML_OP_CREATE, XML_OP_FIND, and XML_OP_GET.

Referenced by send_ews_request_and_parse().

◆ load_module()

static int load_module ( void  )
static

Definition at line 907 of file res_calendar_ews.c.

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:551
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct ast_calendar_tech ewscal_tech

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

◆ msstatus()

static const char * msstatus ( enum ast_calendar_busy_state  state)
static

Definition at line 483 of file res_calendar_ews.c.

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

References AST_CALENDAR_BS_BUSY, AST_CALENDAR_BS_BUSY_TENTATIVE, and AST_CALENDAR_BS_FREE.

Referenced by ewscal_write_event().

◆ mstime()

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

Definition at line 470 of file res_calendar_ews.c.

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
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80

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

Referenced by ewscal_write_event(), and mstime_to_time_t().

◆ mstime_to_time_t()

static time_t mstime_to_time_t ( char *  mstime)
static

Definition at line 163 of file res_calendar_ews.c.

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}
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2357
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....
Definition: localtime.c:2550

References ast_mktime(), ast_strptime(), and mstime().

Referenced by cdata().

◆ 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.

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
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
744 return -1;
745 }
746
748
749 return 0;
750}

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().

◆ 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.

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)
static const char * get_soap_action(enum xml_op op)
static int endelm(void *userdata, int state, const char *nspace, const char *name)
ne_xml_parser * parser

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, request(), ewscal_pvt::session, startelm(), ewscal_pvt::uri, and ewscal_pvt::url.

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

◆ 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.

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}

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

Referenced by ewscal_load_calendar().

◆ 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.

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
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);
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);
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);
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}
enum queue_result id
Definition: app_queue.c:1638
struct ast_calendar_event * ast_calendar_event_alloc(struct ast_calendar *cal)
Allocate an astobj2 ast_calendar_event object.
Definition: res_calendar.c:669
struct calendar_id * next

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, id, xml_context::ids, ewscal_pvt::items, LOG_ERROR, name, 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().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 932 of file res_calendar_ews.c.

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

References ast_calendar_unregister(), and ewscal_tech.

◆ unref_ewscal()

static void * unref_ewscal ( void *  obj)
static

Definition at line 129 of file res_calendar_ews.c.

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}

References ao2_ref, ast_debug, and NULL.

Referenced by ewscal_load_calendar().

◆ update_ewscal()

static int update_ewscal ( struct ewscal_pvt pvt)
static

Definition at line 752 of file res_calendar_ews.c.

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}
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
static int parse_ewscal_id(struct ewscal_pvt *pvt, const char *id)
static struct calendar_id * get_ewscal_ids_for(struct ewscal_pvt *pvt)
struct ast_str * id

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().

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 = AST_BUILDOPT_SUM, .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.

Referenced by load_module(), and unload_module().