[asterisk-commits] twilson: branch twilson/calendaring r190185 - in /team/twilson/calendaring: i...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Apr 22 21:31:36 CDT 2009


Author: twilson
Date: Wed Apr 22 21:31:26 2009
New Revision: 190185

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=190185
Log:
Add attendee (read) support for iCalendar and CalDAV

Of course, MS in their infinite wisdom, don't make the attendee list
available over WebDAV like all of the other calendar data--youe have
to use some other hacked up way to get it. Oh, and they deprecated
the WebDAV interface in favor of a SOAP interface. So eventually
we will have to support multiple protocols to be able to access the
wonder that is Microsoft Exchange Server calendaring.

I am negotiating access to a friend's MS Exchange account so that I
can try to get attendees working, but it may be a bit. I would just
re-write everything to use the SOAP interface, but it is only
available in Exchange Server 2007.  Gah.  But, it looks like
"Mainstream support" for ES 2003 ended 8 days ago...so maybe I should
rewrite it. To heck with those users of ES 2003. Although, apparently
"Extended support" lasts until 4/8/2014--whatever that means.

I really hope the new SOAP interface doesn't suck.

Modified:
    team/twilson/calendaring/include/asterisk/calendar.h
    team/twilson/calendaring/res/res_caldav.c
    team/twilson/calendaring/res/res_calendar.c
    team/twilson/calendaring/res/res_exchangecal.c
    team/twilson/calendaring/res/res_icalendar.c

Modified: team/twilson/calendaring/include/asterisk/calendar.h
URL: http://svn.digium.com/svn-view/asterisk/team/twilson/calendaring/include/asterisk/calendar.h?view=diff&rev=190185&r1=190184&r2=190185
==============================================================================
--- team/twilson/calendaring/include/asterisk/calendar.h (original)
+++ team/twilson/calendaring/include/asterisk/calendar.h Wed Apr 22 21:31:26 2009
@@ -83,6 +83,11 @@
 	AST_CALENDAR_BS_BUSY,
 };
 
+struct ast_calendar_attendee {
+	char *data;
+	AST_LIST_ENTRY(ast_calendar_attendee) next;
+};
+
 /* \brief Calendar events */
 struct ast_calendar_event {
 	AST_DECLARE_STRING_FIELDS(
@@ -100,6 +105,7 @@
 	int notify_sched;    /*!< The sched for event notification */
 	int bs_start_sched;  /*!< The sched for changing the device state at the start of an event */
 	int bs_end_sched;    /*!< The sched for changing the device state at the end of an event */
+	AST_LIST_HEAD_NOLOCK(attendees, ast_calendar_attendee) attendees;
 };
 
 /*! \brief Asterisk calendar structure */

Modified: team/twilson/calendaring/res/res_caldav.c
URL: http://svn.digium.com/svn-view/asterisk/team/twilson/calendaring/res/res_caldav.c?view=diff&rev=190185&r1=190184&r2=190185
==============================================================================
--- team/twilson/calendaring/res/res_caldav.c (original)
+++ team/twilson/calendaring/res/res_caldav.c Wed Apr 22 21:31:26 2009
@@ -364,8 +364,27 @@
 		}
 	}
 
-	/* Only set values for alarm based on VALARM.  Can be overriden in main/calendar.c by autoreminder */
-	/* Currently we are only getting the first VALARM and are handling repitition in main/calendar.c from calendar.conf */
+	/* Get the attendees */
+	for (prop = icalcomponent_get_first_property(comp, ICAL_ATTENDEE_PROPERTY);
+			prop; prop = icalcomponent_get_next_property(comp, ICAL_ATTENDEE_PROPERTY)) {
+		struct ast_calendar_attendee *attendee;
+		const char *data;
+
+		if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
+			event = ast_calendar_unref_event(event);
+			return;
+		}
+		data = icalproperty_get_attendee(prop);
+		if (!ast_strlen_zero(data)) {
+			attendee->data = ast_strdup(data);;
+			AST_LIST_INSERT_TAIL(&event->attendees, attendee, next);
+		}
+	}
+
+
+	/* Only set values for alarm based on VALARM.  Can be overriden in main/calendar.c by autoreminder
+	 * therefore, go ahead and add events even if their is no VALARM or it is malformed
+	 * Currently we are only getting the first VALARM and are handling repitition in main/calendar.c from calendar.conf */
 	if (!(valarm = icalcomponent_get_first_component(comp, ICAL_VALARM_COMPONENT))) {
 		ao2_link(pvt->events, event);
 		event = ast_calendar_unref_event(event);

Modified: team/twilson/calendaring/res/res_calendar.c
URL: http://svn.digium.com/svn-view/asterisk/team/twilson/calendaring/res/res_calendar.c?view=diff&rev=190185&r1=190184&r2=190185
==============================================================================
--- team/twilson/calendaring/res/res_calendar.c (original)
+++ team/twilson/calendaring/res/res_calendar.c Wed Apr 22 21:31:26 2009
@@ -461,9 +461,16 @@
 static void calendar_event_destructor(void *obj)
 {
 	struct ast_calendar_event *event = obj;
+	struct ast_calendar_attendee *attendee;
 
 	ast_debug(3, "Destroying event for calendar '%s'\n", event->owner->name);
 	ast_string_field_free_memory(event);
+	while ((attendee = AST_LIST_REMOVE_HEAD(&event->attendees, next))) {
+		if (attendee->data) {
+			ast_free(attendee->data);
+		}
+		ast_free(attendee);
+	}
 
 	return;
 }
@@ -529,6 +536,8 @@
 	event->notify_sched = -1;
 	event->bs_start_sched = -1;
 	event->bs_end_sched = -1;
+
+	AST_LIST_HEAD_INIT_NOLOCK(&event->attendees);
 
 	return event;
 }
@@ -703,6 +712,8 @@
 
 static void copy_event_data(struct ast_calendar_event *dst, struct ast_calendar_event *src)
 {
+	struct ast_calendar_attendee *attendee;
+
 	ast_string_field_set(dst, summary, src->summary);
 	ast_string_field_set(dst, description, src->description);
 	ast_string_field_set(dst, organizer, src->organizer);
@@ -713,6 +724,10 @@
 	dst->end = src->end;
 	dst->alarm = src->alarm;
 	dst->busy_state = src->busy_state;
+
+	while ((attendee = AST_LIST_REMOVE_HEAD(&src->attendees, next))) {
+		AST_LIST_INSERT_TAIL(&dst->attendees, attendee, next);
+	}
 }
 
 static int schedule_calendar_event(struct ast_calendar *cal, struct ast_calendar_event *old_event, struct ast_calendar_event *cmp_event)
@@ -1001,14 +1016,14 @@
 	);
 
 	if (!chan) {
-		ast_log(LOG_WARNING, "CALENDAR_QUERY requires a channel to store the data on\n");
+		ast_log(LOG_WARNING, "%s requires a channel to store the data on\n", cmd);
 		return -1;
 	}
 
 	AST_STANDARD_APP_ARGS(args, data);
 
 	if (ast_strlen_zero(args.calendar)) {
-		ast_log(LOG_WARNING, "CALENDAR_QUERY requires a calendar argument\n");
+		ast_log(LOG_WARNING, "%s requires a calendar argument\n", cmd);
 		return -1;
 	}
 
@@ -1017,7 +1032,7 @@
 		return -1;
 	}
 
-	if (!(events = ao2_alloc(sizeof(struct eventlist), eventlist_destructor))) {
+	if (!(events = ao2_alloc(sizeof(*events), eventlist_destructor))) {
 		ast_log(LOG_ERROR, "Unable to allocate memory for event list\n");
 		cal = unref_calendar(cal);
 		return -1;
@@ -1069,6 +1084,24 @@
     .name = "CALENDAR_QUERY",
     .read = calendar_query_exec,
 };
+
+static void calendar_join_attendees(struct ast_calendar_event *event, char *buf, size_t len)
+{
+	struct ast_str *tmp;
+	struct ast_calendar_attendee *attendee;
+
+	if (!(tmp = ast_str_create(32))) {
+		ast_log(LOG_ERROR, "Could not allocate memory for attendees!\n");
+		return;
+	}
+
+	AST_LIST_TRAVERSE(&event->attendees, attendee, next) {
+		ast_str_append(&tmp, 0, "%s%s", attendee == AST_LIST_FIRST(&event->attendees) ? "" : ",", attendee->data);
+	}
+
+	ast_copy_string(buf, ast_str_buffer(tmp), len);
+	ast_free(tmp);
+}
 
 static int calendar_query_result_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
@@ -1083,14 +1116,14 @@
 	);
 
 	if (!chan) {
-		ast_log(LOG_WARNING, "CALENDAR_QUERY_RESULT requires a channel\n");
+		ast_log(LOG_WARNING, "%s requires a channel\n", cmd);
 		return -1;
 	}
 
 	AST_STANDARD_APP_ARGS(args, data);
 
 	if (ast_strlen_zero(args.id) || ast_strlen_zero(args.field)) {
-		ast_log(LOG_WARNING, "CALENDAR_QUERY_RESULT requires an id and a field");
+		ast_log(LOG_WARNING, "%s requires an id and a field", cmd);
 		return -1;
 	}
 
@@ -1133,6 +1166,8 @@
 			snprintf(buf, len, "%ld", entry->event->end);
 		} else if (!strcasecmp(args.field, "busystate")) {
 			snprintf(buf, len, "%d", entry->event->busy_state);
+		} else if (!strcasecmp(args.field, "attendees")) {
+			calendar_join_attendees(entry->event, buf, len);
 		} else {
 			ast_log(LOG_WARNING, "Unknown field '%s'\n", args.field);
 		}
@@ -1395,7 +1430,7 @@
 	struct ast_calendar_event *event;
 
 	if (ast_strlen_zero(data)) {
-		ast_log(LOG_WARNING, "CALENDAR_EVENT requires an argument\n");
+		ast_log(LOG_WARNING, "%s requires an argument\n", cmd);
 		return -1;
 	}
 
@@ -1430,7 +1465,10 @@
 		snprintf(buf, len, "%ld", (long)event->end);
 	} else if (!strcasecmp(data, "busystate")) {
 		snprintf(buf, len, "%d", event->busy_state);
-	}
+	} else if (!strcasecmp(data, "attendees")) {
+		calendar_join_attendees(event, buf, len);
+	}
+
 
 	return 0;
 }

Modified: team/twilson/calendaring/res/res_exchangecal.c
URL: http://svn.digium.com/svn-view/asterisk/team/twilson/calendaring/res/res_exchangecal.c?view=diff&rev=190185&r1=190184&r2=190185
==============================================================================
--- team/twilson/calendaring/res/res_exchangecal.c (original)
+++ team/twilson/calendaring/res/res_exchangecal.c Wed Apr 22 21:31:26 2009
@@ -181,6 +181,7 @@
 	}
 	memcpy(str, value, len);
 	if (!(state->in_response && state->in_propstat && state->in_prop)) {
+		ast_free(str);
 		return IKS_OK;
 	}
 	/* We use ast_string_field_build here because libiksemel is parsing CDATA with &lt; as
@@ -207,6 +208,7 @@
 		event->alarm = event->start - atoi(str);
 	}
 
+	ast_free(str);
 	return IKS_OK;
 }
 
@@ -219,7 +221,7 @@
 {
 	struct exchangecal_pvt *pvt = obj;
 
-	ast_debug(1, "Destroying pvt for iCalendar %s\n", pvt->owner->name);
+	ast_debug(1, "Destroying pvt for Exchange calendar %s\n", pvt->owner->name);
 	if (pvt->session) {
 		ne_session_destroy(pvt->session);
 	}
@@ -370,7 +372,7 @@
 	struct exchangecal_pvt *pvt = userdata;
 
 	if (attempts > 1) {
-		ast_log(LOG_WARNING, "Invalid username or password for iCalendar '%s'\n", pvt->owner->name);
+		ast_log(LOG_WARNING, "Invalid username or password for Exchange calendar '%s'\n", pvt->owner->name);
 		return -1;
 	}
 
@@ -660,14 +662,14 @@
 	}
 
 	if (ast_strlen_zero(pvt->url)) {
-		ast_log(LOG_WARNING, "No URL was specified for iCalendar '%s' - skipping.\n", cal->name);
+		ast_log(LOG_WARNING, "No URL was specified for Exchange calendar '%s' - skipping.\n", cal->name);
 		pvt = unref_exchangecal(pvt);
 		ao2_unlock(cal);
 		return NULL;
 	}
 
 	if (ne_uri_parse(pvt->url, &pvt->uri) || pvt->uri.host == NULL || pvt->uri.path == NULL) {
-		ast_log(LOG_WARNING, "Could not parse url '%s' for iCalendar '%s' - skipping.\n", pvt->url, cal->name);
+		ast_log(LOG_WARNING, "Could not parse url '%s' for Exchange calendar '%s' - skipping.\n", pvt->url, cal->name);
 		pvt = unref_exchangecal(pvt);
 		ao2_unlock(cal);
 		return NULL;

Modified: team/twilson/calendaring/res/res_icalendar.c
URL: http://svn.digium.com/svn-view/asterisk/team/twilson/calendaring/res/res_icalendar.c?view=diff&rev=190185&r1=190184&r2=190185
==============================================================================
--- team/twilson/calendaring/res/res_icalendar.c (original)
+++ team/twilson/calendaring/res/res_icalendar.c Wed Apr 22 21:31:26 2009
@@ -227,8 +227,27 @@
 		}
 	}
 
-	/* Only set values for alarm based on VALARM.  Can be overriden in main/calendar.c by autoreminder */
-	/* Currently we are only getting the first VALARM and are handling repitition in main/calendar.c from calendar.conf */
+	/* Get the attendees */
+	for (prop = icalcomponent_get_first_property(comp, ICAL_ATTENDEE_PROPERTY);
+			prop; prop = icalcomponent_get_next_property(comp, ICAL_ATTENDEE_PROPERTY)) {
+		struct ast_calendar_attendee *attendee;
+		const char *data;
+
+		if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
+			event = ast_calendar_unref_event(event);
+			return;
+		}
+		data = icalproperty_get_attendee(prop);
+		if (!ast_strlen_zero(data)) {
+			attendee->data = ast_strdup(data);;
+			AST_LIST_INSERT_TAIL(&event->attendees, attendee, next);
+		}
+	}
+
+
+	/* Only set values for alarm based on VALARM.  Can be overriden in main/calendar.c by autoreminder
+	 * therefore, go ahead and add events even if their is no VALARM or it is malformed
+	 * Currently we are only getting the first VALARM and are handling repitition in main/calendar.c from calendar.conf */
 	if (!(valarm = icalcomponent_get_first_component(comp, ICAL_VALARM_COMPONENT))) {
 		ao2_link(pvt->events, event);
 		event = ast_calendar_unref_event(event);




More information about the asterisk-commits mailing list