[asterisk-commits] twilson: branch group/calendaring_ews r263903 - /team/group/calendaring_ews/res/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue May 18 17:22:30 CDT 2010
Author: twilson
Date: Tue May 18 17:22:27 2010
New Revision: 263903
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=263903
Log:
Add write support for res_calendar_ews
This commit was done at 1.4 mph.
Modified:
team/group/calendaring_ews/res/res_calendar.c
team/group/calendaring_ews/res/res_calendar_ews.c
Modified: team/group/calendaring_ews/res/res_calendar.c
URL: http://svnview.digium.com/svn/asterisk/team/group/calendaring_ews/res/res_calendar.c?view=diff&rev=263903&r1=263902&r2=263903
==============================================================================
--- team/group/calendaring_ews/res/res_calendar.c (original)
+++ team/group/calendaring_ews/res/res_calendar.c Tue May 18 17:22:27 2010
@@ -1260,6 +1260,7 @@
char *val_dup = NULL;
struct ast_calendar *cal = NULL;
struct ast_calendar_event *event = NULL;
+ struct timeval tv = ast_tvnow();
AST_DECLARE_APP_ARGS(fields,
AST_APP_ARG(field)[10];
);
@@ -1323,6 +1324,14 @@
} else {
ast_log(LOG_WARNING, "Unknown calendar event field '%s'\n", fields.field[i]);
}
+ }
+
+ if (!event->start) {
+ event->start = tv.tv_sec;
+ }
+
+ if (!event->end) {
+ event->end = tv.tv_sec;
}
if((ret = cal->tech->write_event(event))) {
Modified: team/group/calendaring_ews/res/res_calendar_ews.c
URL: http://svnview.digium.com/svn/asterisk/team/group/calendaring_ews/res/res_calendar_ews.c?view=diff&rev=263903&r1=263902&r2=263903
==============================================================================
--- team/group/calendaring_ews/res/res_calendar_ews.c (original)
+++ team/group/calendaring_ews/res/res_calendar_ews.c Tue May 18 17:22:27 2010
@@ -44,6 +44,7 @@
static void *ewscal_load_calendar(void *data);
static void *unref_ewscal(void *obj);
+static int ewscal_write_event(struct ast_calendar_event *event);
static struct ast_calendar_tech ewscal_tech = {
.type = "ews",
@@ -51,11 +52,13 @@
.module = AST_MODULE,
.load_calendar = ewscal_load_calendar,
.unref_calendar = unref_ewscal,
+ .write_event = ewscal_write_event,
};
enum xml_op {
XML_OP_FIND = 100,
XML_OP_GET,
+ XML_OP_CREATE,
};
struct calendar_id {
@@ -165,10 +168,16 @@
/* ast_debug(1, "EWS: XML: Start: %s\n", name); */
struct xml_context *ctx = userdata;
+ if (ctx->op == XML_OP_CREATE) {
+ return NE_XML_DECLINE;
+ }
+
/* Nodes needed for traversing until CalendarItem is found */
if (!strcmp(name, "Envelope") ||
!strcmp(name, "Body") ||
- !strcmp(name, "FindItemResponse") || !strcmp(name, "GetItemResponse") ||
+ !strcmp(name, "FindItemResponse") ||
+ !strcmp(name, "GetItemResponse") ||
+ !strcmp(name, "CreateItemResponse") ||
!strcmp(name, "ResponseMessages") ||
!strcmp(name, "FindItemResponseMessage") || !strcmp(name, "GetItemResponseMessage") ||
!strcmp(name, "Items")
@@ -295,50 +304,52 @@
static int cdata(void *userdata, int state, const char *cdata, size_t len)
{
+ struct xml_context *ctx = userdata;
+ char data[len + 1];
+
/* !!! DON'T USE AST_STRING_FIELD FUNCTIONS HERE, JUST COLLECT CTX->CDATA !!! */
- if (state >= XML_EVENT_NAME) { /* We've got some interesting CDATA */
- struct xml_context *ctx = userdata;
- char data[len + 1];
-
- if (!ctx->event) {
- ast_log(LOG_ERROR, "Parsing event data, but event object does not exist!\n");
- return 1;
- }
-
- if (!ctx->cdata) {
- ast_log(LOG_ERROR, "String for storing CDATA is unitialized!\n");
- return 1;
- }
-
- ast_copy_string(data, cdata, len + 1);
-
- switch (state) {
- case XML_EVENT_START:
- ctx->event->start = mstime_to_time_t(data);
- break;
- case XML_EVENT_END:
- ctx->event->end = mstime_to_time_t(data);
- break;
- case XML_EVENT_BUSY:
- if (!strcmp(data, "Busy") || !strcmp(data, "OOF")) {
- ast_debug(1, "EWS: XML: Busy: yes\n");
- ctx->event->busy_state = AST_CALENDAR_BS_BUSY;
- }
- else if (!strcmp(data, "Tentative")) {
- ast_debug(1, "EWS: XML: Busy: tentative\n");
- ctx->event->busy_state = AST_CALENDAR_BS_BUSY_TENTATIVE;
- }
- else {
- ast_debug(1, "EWS: XML: Busy: no\n");
- ctx->event->busy_state = AST_CALENDAR_BS_FREE;
- }
- break;
- default:
- ast_str_append(&ctx->cdata, 0, "%s", data);
- }
-
- ast_debug(1, "EWS: XML: CDATA: %s\n", ast_str_buffer(ctx->cdata));
- }
+ if (state < XML_EVENT_NAME || ctx->op == XML_OP_CREATE) {
+ return 0;
+ }
+
+ if (!ctx->event) {
+ ast_log(LOG_ERROR, "Parsing event data, but event object does not exist!\n");
+ return 1;
+ }
+
+ if (!ctx->cdata) {
+ ast_log(LOG_ERROR, "String for storing CDATA is unitialized!\n");
+ return 1;
+ }
+
+ ast_copy_string(data, cdata, len + 1);
+
+ switch (state) {
+ case XML_EVENT_START:
+ ctx->event->start = mstime_to_time_t(data);
+ break;
+ case XML_EVENT_END:
+ ctx->event->end = mstime_to_time_t(data);
+ break;
+ case XML_EVENT_BUSY:
+ if (!strcmp(data, "Busy") || !strcmp(data, "OOF")) {
+ ast_debug(1, "EWS: XML: Busy: yes\n");
+ ctx->event->busy_state = AST_CALENDAR_BS_BUSY;
+ }
+ else if (!strcmp(data, "Tentative")) {
+ ast_debug(1, "EWS: XML: Busy: tentative\n");
+ ctx->event->busy_state = AST_CALENDAR_BS_BUSY_TENTATIVE;
+ }
+ else {
+ ast_debug(1, "EWS: XML: Busy: no\n");
+ ctx->event->busy_state = AST_CALENDAR_BS_FREE;
+ }
+ break;
+ default:
+ ast_str_append(&ctx->cdata, 0, "%s", data);
+ }
+
+ ast_debug(1, "EWS: XML: CDATA: %s\n", ast_str_buffer(ctx->cdata));
return 0;
}
@@ -348,8 +359,8 @@
/* ast_debug(1, "EWS: XML: End: %s\n", name); */
struct xml_context *ctx = userdata;
- if (ctx->op == XML_OP_FIND) {
- return 0;
+ if (ctx->op == XML_OP_FIND || ctx->op == XML_OP_CREATE) {
+ return NE_XML_DECLINE;
}
/* Event name end*/
@@ -408,18 +419,169 @@
return 0;
}
+static const char *mstime(time_t t, char *buf, size_t buflen)
+{
+ struct timeval tv = {
+ .tv_sec = t,
+ };
+ struct ast_tm tm;
+
+ ast_localtime(&tv, &tm, "utc");
+ ast_strftime(buf, buflen, "%FT%TZ", &tm);
+
+ return S_OR(buf, "");
+}
+
+static const char *msstatus(enum ast_calendar_busy_state state)
+{
+ switch (state) {
+ case AST_CALENDAR_BS_BUSY_TENTATIVE:
+ return "Tentative";
+ case AST_CALENDAR_BS_BUSY:
+ return "Busy";
+ case AST_CALENDAR_BS_FREE:
+ return "Free";
+ default:
+ return "";
+ }
+}
+
+static const char *get_soap_action(enum xml_op op)
+{
+ switch (op) {
+ case XML_OP_FIND:
+ return "\"http://schemas.microsoft.com/exchange/services/2006/messages/FindItem\"";
+ case XML_OP_GET:
+ return "\"http://schemas.microsoft.com/exchange/services/2006/messages/GetItem\"";
+ case XML_OP_CREATE:
+ return "\"http://schemas.microsoft.com/exchange/services/2006/messages/CreateItem\"";
+ }
+
+ return "";
+}
+
+static int send_ews_request_and_parse(struct ast_str *request, struct xml_context *ctx)
+{
+ int ret;
+ ne_request *req;
+ ne_xml_parser *parser;
+
+ ast_debug(1, "EWS: HTTP request...\n");
+ if (!(ctx && ctx->pvt)) {
+ ast_log(LOG_ERROR, "There is no private!\n");
+ return -1;
+ }
+
+ if (!ast_str_strlen(request)) {
+ ast_log(LOG_ERROR, "No request to send!\n");
+ return -1;
+ }
+
+ ast_debug(3, "%s\n", ast_str_buffer(request));
+
+ /* Prepare HTTP POST request */
+ req = ne_request_create(ctx->pvt->session, "POST", ctx->pvt->uri.path);
+ ne_set_request_flag(req, NE_REQFLAG_IDEMPOTENT, 0);
+
+ /* Set headers */
+ ne_add_request_header(req, "Content-Type", "text/xml; charset=utf-8"); /* should be application/soap+xml, but MS⦠:/ */
+ ne_add_request_header(req, "SOAPAction", get_soap_action(ctx->op));
+
+ /* Set body to SOAP request */
+ ne_set_request_body_buffer(req, ast_str_buffer(request), ast_str_strlen(request));
+
+ /* Prepare XML parser */
+ parser = ne_xml_create();
+ ctx->parser = parser;
+ ne_xml_push_handler(parser, startelm, cdata, endelm, ctx); /* Callbacks */
+
+ /* Dispatch request and parse response as XML */
+ ret = ne_xml_dispatch_request(req, parser);
+ if (ret != NE_OK) { /* Error handling */
+ ast_log(LOG_WARNING, "Unable to communicate with Exchange Web Service at '%s': %s\n", ctx->pvt->url, ne_get_error(ctx->pvt->session));
+ ne_request_destroy(req);
+ ast_free(request);
+ ne_xml_destroy(parser);
+ return -1;
+ }
+
+ /* Cleanup */
+ ne_request_destroy(req);
+ ne_xml_destroy(parser);
+
+ return 0;
+}
+
+static int ewscal_write_event(struct ast_calendar_event *event)
+{
+ struct ast_str *request;
+ struct ewscal_pvt *pvt = event->owner->tech_pvt;
+ char start[21], end[21];
+ struct xml_context ctx = {
+ .op = XML_OP_CREATE,
+ .pvt = pvt,
+ };
+ int ret;
+
+ if (!pvt) {
+ return -1;
+ }
+
+ if (!(request = ast_str_create(1024))) {
+ return -1;
+ }
+
+ ast_str_set(&request, 0,
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
+ "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+ "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">"
+ "<soap:Body>"
+ "<CreateItem xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\" "
+ "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\" "
+ "SendMeetingInvitations=\"SendToNone\" >"
+ "<SavedItemFolderId>"
+ "<t:DistinguishedFolderId Id=\"calendar\"/>"
+ "</SavedItemFolderId>"
+ "<Items>"
+ "<t:CalendarItem xmlns=\"http://schemas.microsoft.com/exchange/services/2006/types\">"
+ "<Subject>%s</Subject>"
+ "<Body BodyType=\"Text\">%s</Body>"
+ "<ReminderIsSet>false</ReminderIsSet>"
+ "<Start>%s</Start>"
+ "<End>%s</End>"
+ "<IsAllDayEvent>false</IsAllDayEvent>"
+ "<LegacyFreeBusyStatus>%s</LegacyFreeBusyStatus>"
+ "<Location>%s</Location>"
+ "</t:CalendarItem>"
+ "</Items>"
+ "</CreateItem>"
+ "</soap:Body>"
+ "</soap:Envelope>",
+ event->summary,
+ event->description,
+ mstime(event->start, start, sizeof(start)),
+ mstime(event->end, end, sizeof(end)),
+ msstatus(event->busy_state),
+ event->location
+ );
+
+ ret = send_ews_request_and_parse(request, &ctx);
+
+ ast_free(request);
+
+ return ret;
+}
+
static struct calendar_id *get_ewscal_ids_for(struct ewscal_pvt *pvt)
{
char start[21], end[21];
struct ast_tm tm;
struct timeval tv;
struct ast_str *request;
- int ret;
- ne_request *req;
- ne_xml_parser *parser;
struct xml_context ctx = {
+ .op = XML_OP_FIND,
.pvt = pvt,
- .op = XML_OP_FIND,
};
ast_debug(1, "EWS: get_ewscal_ids_for()\n");
@@ -461,48 +623,23 @@
"</SOAP-ENV:Envelope>",
start, end /* Timeframe */
);
- ast_debug(3, "%s\n", ast_str_buffer(request));
-
- /* Prepare HTTP POST request */
- req = ne_request_create(pvt->session, "POST", pvt->uri.path);
- ne_set_request_flag(req, NE_REQFLAG_IDEMPOTENT, 0);
-
- /* Set headers */
- ne_add_request_header(req, "Content-Type", "text/xml; charset=utf-8"); /* should be application/soap+xml, but MS⦠:/ */
- ne_add_request_header(req, "SOAPAction", "\"http://schemas.microsoft.com/exchange/services/2006/messages/FindItem\"");
-
- /* Set body to SOAP request */
- ne_set_request_body_buffer(req, ast_str_buffer(request), ast_str_strlen(request));
-
- /* Prepare XML parser */
- parser = ne_xml_create();
- ctx.parser = parser;
+
AST_LIST_HEAD_INIT_NOLOCK(&ctx.ids);
- ne_xml_push_handler(parser, startelm, cdata, endelm, &ctx); /* Callbacks */
/* Dispatch request and parse response as XML */
- ret = ne_xml_dispatch_request(req, parser);
- if (ret != NE_OK) { /* Error handling */
- ast_log(LOG_WARNING, "Unable to communicate with Exchange Web Service at '%s': %s\n", pvt->url, ne_get_error(pvt->session));
- ne_request_destroy(req);
+ if (send_ews_request_and_parse(request, &ctx)) {
ast_free(request);
- ne_xml_destroy(parser);
return NULL;
}
/* Cleanup */
ast_free(request);
- ne_request_destroy(req);
- ne_xml_destroy(parser);
return AST_LIST_FIRST(&ctx.ids);
}
static int parse_ewscal_id(struct ewscal_pvt *pvt, const char *id) {
struct ast_str *request;
- int ret;
- ne_request *req;
- ne_xml_parser *parser;
struct xml_context ctx = {
.pvt = pvt,
.op = XML_OP_GET,
@@ -528,37 +665,10 @@
"</soap:Body>"
"</soap:Envelope>",
id);
- ast_debug(3, "%s\n", ast_str_buffer(request));
-
- /* Prepare HTTP POST request */
- req = ne_request_create(pvt->session, "POST", pvt->uri.path);
- ne_set_request_flag(req, NE_REQFLAG_IDEMPOTENT, 0);
-
- /* Set headers */
- ne_add_request_header(req, "Content-Type", "text/xml; charset=utf-8"); /* should be application/soap+xml, but MS⦠:/ */
- ne_add_request_header(req, "SOAPAction", "\"http://schemas.microsoft.com/exchange/services/2006/messages/GetItem\"");
-
- /* Set body to SOAP request */
- ne_set_request_body_buffer(req, ast_str_buffer(request), ast_str_strlen(request));
-
- /* Prepare XML parser */
- parser = ne_xml_create();
- ctx.parser = parser;
- ne_xml_push_handler(parser, startelm, cdata, endelm, &ctx); /* Callbacks */
-
- /* Dispatch request and parse response as XML */
- ret = ne_xml_dispatch_request(req, parser);
- if (ret != NE_OK) { /* Error handling */
- ast_log(LOG_WARNING, "Unable to communicate with Exchange Web Service at '%s': %s\n", pvt->url, ne_get_error(pvt->session));
- ne_request_destroy(req);
- ne_xml_destroy(parser);
+ if (send_ews_request_and_parse(request, &ctx)) {
ast_free(request);
return -1;
}
-
- /* Cleanup */
- ne_request_destroy(req);
- ne_xml_destroy(parser);
ast_free(request);
return 0;
More information about the asterisk-commits
mailing list