[asterisk-commits] twilson: branch group/calendaring_ews r263194 - /team/group/calendaring_ews/res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri May 14 14:46:54 CDT 2010


Author: twilson
Date: Fri May 14 14:46:50 2010
New Revision: 263194

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=263194
Log:
Add attendee support

Modified:
    team/group/calendaring_ews/res/res_calendar_ews.c

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=263194&r1=263193&r2=263194
==============================================================================
--- team/group/calendaring_ews/res/res_calendar_ews.c (original)
+++ team/group/calendaring_ews/res/res_calendar_ews.c Fri May 14 14:46:50 2010
@@ -53,11 +53,23 @@
 	.unref_calendar = unref_ewscal,
 };
 
+enum xml_op {
+	XML_OP_FIND = 100,
+	XML_OP_GET,
+};
+
+struct calendar_id {
+	struct ast_str *id;
+	AST_LIST_ENTRY(calendar_id) next;
+};
+
 struct xml_context {
 	ne_xml_parser *parser;
 	struct ast_str *cdata;
 	struct ast_calendar_event *event;
+	enum xml_op op;
 	struct ewscal_pvt *pvt;
+	AST_LIST_HEAD_NOLOCK(ids, calendar_id) ids;
 };
 
 /* Important states of XML parsing */
@@ -67,7 +79,11 @@
 	XML_EVENT_END,
 	XML_EVENT_BUSY,
 	XML_EVENT_ORGANIZER,
-	XML_EVENT_LOCATION
+	XML_EVENT_LOCATION,
+	XML_EVENT_ATTENDEE_LIST,
+	XML_EVENT_ATTENDEE,
+	XML_EVENT_MAILBOX,
+	XML_EVENT_EMAIL_ADDRESS,
 };
 
 struct ewscal_pvt {
@@ -150,11 +166,11 @@
 	struct xml_context *ctx = userdata;
 
 	/* Nodes needed for traversing until CalendarItem is found */
-	if (	!strcmp(name, "Envelope")			||
-		!strcmp(name, "Body")				||
-		!strcmp(name, "FindItemResponse")		||
-		!strcmp(name, "ResponseMessages")		||
-		!strcmp(name, "FindItemResponseMessage")	||
+	if (!strcmp(name, "Envelope") ||
+		!strcmp(name, "Body") ||
+		!strcmp(name, "FindItemResponse") || !strcmp(name, "GetItemResponse") ||
+		!strcmp(name, "ResponseMessages") ||
+		!strcmp(name, "FindItemResponseMessage") || !strcmp(name, "GetItemResponseMessage") ||
 		!strcmp(name, "Items")
 	) {
 		return 1;
@@ -201,8 +217,22 @@
 
 	/* Event UID */
 	else if (!strcmp(name, "ItemId")) {
-		ast_debug(1, "EWS: XML: UID: %s\n", ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
-		ast_string_field_set(ctx->event, uid, ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
+		if (ctx->op == XML_OP_FIND) {
+			struct calendar_id *id;
+			if (!(id = ast_calloc(1, sizeof(id)))) {
+				return NE_XML_ABORT;
+			}
+			if (!(id->id = ast_str_create(256))) {
+				ast_free(id);
+				return NE_XML_ABORT;
+			}
+			ast_str_set(&id->id, 0, "%s", ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
+			AST_LIST_INSERT_TAIL(&ctx->ids, id, next);
+			ast_debug(1, "EWS_FIND: XML: UID: %s\n", ast_str_buffer(id->id));
+		} else {
+			ast_debug(1, "EWS_GET: XML: UID: %s\n", ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
+			ast_string_field_set(ctx->event, uid, ne_xml_get_attr(ctx->parser, atts, NULL, "Id"));
+		}
 		return XML_EVENT_NAME;
 	}
 
@@ -246,6 +276,18 @@
 		}
 		ast_str_reset(ctx->cdata);
 		return XML_EVENT_LOCATION;
+	} else if (!strcmp(name, "RequiredAttendees") || !strcmp(name, "OptionalAttendees")) {
+		return XML_EVENT_ATTENDEE_LIST;
+	} else if (!strcmp(name, "Attendee") && parent == XML_EVENT_ATTENDEE_LIST) {
+		return XML_EVENT_ATTENDEE;
+	} else if (!strcmp(name, "Mailbox") && parent == XML_EVENT_ATTENDEE) {
+		return XML_EVENT_MAILBOX;
+	} else if (!strcmp(name, "EmailAddress") && parent == XML_EVENT_MAILBOX) {
+		if (!ctx->cdata) {
+			return NE_XML_ABORT;
+		}
+		ast_str_reset(ctx->cdata);
+		return XML_EVENT_EMAIL_ADDRESS;
 	}
 
 	return NE_XML_DECLINE;
@@ -306,6 +348,10 @@
 	/* ast_debug(1, "EWS: XML: End:   %s\n", name); */
 	struct xml_context *ctx = userdata;
 
+	if (ctx->op == XML_OP_FIND) {
+		return 0;
+	}
+
 	/* Event name end*/
 	if (!strcmp(name, "Subject")) {
 		ast_string_field_set(ctx->event, summary, ast_str_buffer(ctx->cdata));
@@ -324,6 +370,20 @@
 	else if (!strcmp(name, "Location")) {
 		ast_string_field_set(ctx->event, location, ast_str_buffer(ctx->cdata));
 		ast_debug(1, "EWS: XML: Location: %s\n", ctx->event->location);
+		ast_str_reset(ctx->cdata);
+	} else if (state == XML_EVENT_EMAIL_ADDRESS) {
+		struct ast_calendar_attendee *attendee;
+
+		if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
+			ctx->event = ast_calendar_unref_event(ctx->event);
+			return  1;
+		}
+
+		if (ast_str_strlen(ctx->cdata)) {
+			attendee->data = ast_strdup(ast_str_buffer(ctx->cdata));
+			AST_LIST_INSERT_TAIL(&ctx->event->attendees, attendee, next);
+		}
+		ast_debug(1, "EWS: XML: attendee address '%s'\n", ast_str_buffer(ctx->cdata));
 		ast_str_reset(ctx->cdata);
 	}
 
@@ -341,25 +401,28 @@
 	}
 
 	/* Events end */
-	else if (!strcmp(name, "RootFolder")) {
+	else if (!strcmp(name, "Envelope")) {
 		ast_debug(1, "EWS: XML: All events has been parsed, merging…\n");
 		ast_calendar_merge_events(ctx->pvt->owner, ctx->pvt->events);
 	}
 	return 0;
 }
 
-static int update_ewscal(struct ewscal_pvt *pvt)
+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;
-	struct xml_context ctx;
 	int ret;
 	ne_request *req;
 	ne_xml_parser *parser;
-
-	ast_debug(1, "EWS: update_ewscal()\n");
+	struct xml_context ctx = {
+		.pvt = pvt,
+		.op = XML_OP_FIND,
+	};
+
+	ast_debug(1, "EWS: get_ewscal_ids_for()\n");
 
 	/*
 	 * This will perform HTTP request
@@ -367,7 +430,7 @@
 	ast_debug(1, "EWS: HTTP request...\n");
 	if (!pvt) {
 		ast_log(LOG_ERROR, "There is no private!\n");
-		return -1;
+		return NULL;
 	}
 
 	/* Prepare timeframe strings */
@@ -380,14 +443,14 @@
 
 	/* Prepare SOAP request */
 	if (!(request = ast_str_create(512))) {
-		return -1;
+		return NULL;
 	}
 	ast_str_set(&request, 0,
 		"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"http://schemas.microsoft.com/exchange/services/2006/types\" xmlns:ns2=\"http://schemas.microsoft.com/exchange/services/2006/messages\">"
 			"<SOAP-ENV:Body>"
 				"<ns2:FindItem Traversal=\"Shallow\">"
 					"<ns2:ItemShape>"
-						"<ns1:BaseShape>AllProperties</ns1:BaseShape>"
+						"<ns1:BaseShape>IdOnly</ns1:BaseShape>"
 					"</ns2:ItemShape>"
 					"<ns2:CalendarView StartDate=\"%s\" EndDate=\"%s\"/>"	/* Timeframe */
 					"<ns2:ParentFolderIds>"
@@ -398,7 +461,7 @@
 		"</SOAP-ENV:Envelope>",
 		start, end	/* Timeframe */
 	);
-	ast_debug(1, "%s", ast_str_buffer(request));
+	ast_debug(3, "%s\n", ast_str_buffer(request));
 
 	/* Prepare HTTP POST request */
 	req = ne_request_create(pvt->session, "POST", pvt->uri.path);
@@ -414,8 +477,7 @@
 	/* Prepare XML parser */
 	parser = ne_xml_create();
 	ctx.parser = parser;
-	ctx.event = NULL;
-	ctx.pvt = pvt;
+	AST_LIST_HEAD_INIT_NOLOCK(&ctx.ids);
 	ne_xml_push_handler(parser, startelm, cdata, endelm, &ctx);	/* Callbacks */
 
 	/* Dispatch request and parse response as XML */
@@ -425,13 +487,97 @@
 		ne_request_destroy(req);
 		ast_free(request);
 		ne_xml_destroy(parser);
-		return -1;
+		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,
+	};
+
+	if (!(request = ast_str_create(512))) {
+		return -1;
+	}
+
+	ast_str_set(&request, 0,
+		"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+		"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+		  "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">"
+		  "<soap:Body>"
+			"<GetItem xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\">"
+			  "<ItemShape>"
+				"<t:BaseShape>AllProperties</t:BaseShape>"
+			  "</ItemShape>"
+			  "<ItemIds>"
+				"<t:ItemId Id=\"%s\"/>"
+			  "</ItemIds>"
+			"</GetItem>"
+		  "</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);
+		ast_free(request);
+		return -1;
+	}
+
+	/* Cleanup */
+	ne_request_destroy(req);
+	ne_xml_destroy(parser);
+	ast_free(request);
+
+	return 0;
+}
+
+static int update_ewscal(struct ewscal_pvt *pvt)
+{
+	struct calendar_id *id_head;
+	struct calendar_id *iter;
+
+	if (!(id_head = get_ewscal_ids_for(pvt))) {
+		return 0;
+	}
+
+	for (iter = id_head; iter; iter = AST_LIST_NEXT(iter, next)) {
+		parse_ewscal_id(pvt, ast_str_buffer(iter->id));
+		ast_free(iter->id);
+		ast_free(iter);
+	}
 
 	return 0;
 }




More information about the asterisk-commits mailing list