<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/6491">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Joshua Colp: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved
Jenkins2: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_calendar: Various fixes<br><br>* The way that we were looking at XML elements for CalDAV was extremely<br> fragile, so use SAX2 for increased robustness.<br><br>* Don't complain about a 'channel' not be specified if autoreminder is<br> not set. Assume that if 'channel' is not set, we don't want to be<br> notified.<br><br>* Fix some truncated CLI output in 'calendar show calendar' and make the<br> 'Autoreminder' description a bit more clear<br><br>ASTERISK-24588 #close<br>Reported by: Stefan Gofferje<br><br>ASTERISK-25523 #close<br>Reported by: Jesper<br><br>Change-Id: I200d11afca6a47e7d97888f286977e2e69874b2c<br>---<br>M res/res_calendar.c<br>M res/res_calendar_caldav.c<br>2 files changed, 50 insertions(+), 13 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/res/res_calendar.c b/res/res_calendar.c<br>index 298970a..048f5e0 100644<br>--- a/res/res_calendar.c<br>+++ b/res/res_calendar.c<br>@@ -482,6 +482,13 @@<br> }<br> }<br> <br>+ if (cal->autoreminder && ast_strlen_zero(cal->notify_channel)) {<br>+ ast_log(LOG_WARNING,<br>+ "You have set 'autoreminder' but not 'channel' for calendar '%s.' "<br>+ "Notifications will not occur.\n",<br>+ cal->name);<br>+ }<br>+<br> if (new_calendar) {<br> cal->thread = AST_PTHREADT_NULL;<br> ast_cond_init(&cal->unload, NULL);<br>@@ -489,7 +496,7 @@<br> if (ast_pthread_create(&cal->thread, NULL, cal->tech->load_calendar, cal)) {<br> /* If we start failing to create threads, go ahead and return NULL<br> * and the tech module will be unregistered<br>- */ <br>+ */<br> ao2_unlink(calendars, cal);<br> cal = unref_calendar(cal);<br> }<br>@@ -948,7 +955,7 @@<br> event = cmp_event ? cmp_event : old_event;<br> <br> ao2_lock(event);<br>- if (!cmp_event || old_event->alarm != event->alarm) {<br>+ if (!ast_strlen_zero(cal->notify_channel) && (!cmp_event || old_event->alarm != event->alarm)) {<br> changed = 1;<br> if (cal->autoreminder) {<br> alarm_notify_sched = (event->start - (60 * cal->autoreminder) - now.tv_sec) * 1000;<br>@@ -957,7 +964,7 @@<br> }<br> <br> /* For now, send the notification if we missed it, but the meeting hasn't happened yet */<br>- if (event->start >= now.tv_sec) {<br>+ if (event->start >= now.tv_sec) {<br> if (alarm_notify_sched <= 0) {<br> alarm_notify_sched = 1;<br> }<br>@@ -1590,7 +1597,7 @@<br> <br> static char *handle_show_calendar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)<br> {<br>-#define FORMAT "%-17.17s : %-20.20s\n"<br>+#define FORMAT "%-18.18s : %-20.20s\n"<br> #define FORMAT2 "%-12.12s: %-40.60s\n"<br> struct ao2_iterator i;<br> struct ast_calendar *cal;<br>@@ -1639,7 +1646,13 @@<br> ast_cli(a->fd, FORMAT, "Notify appdata", cal->notify_appdata);<br> ast_cli(a->fd, "%-17.17s : %d\n", "Refresh time", cal->refresh);<br> ast_cli(a->fd, "%-17.17s : %d\n", "Timeframe", cal->timeframe);<br>- ast_cli(a->fd, "%-17.17s : %d\n", "Autoreminder", cal->autoreminder);<br>+<br>+ if (cal->autoreminder) {<br>+ ast_cli(a->fd, "%-17.17s : %d minutes before event\n", "Autoreminder", cal->autoreminder);<br>+ } else {<br>+ ast_cli(a->fd, "%-17.17s : None\n", "Autoreminder");<br>+ }<br>+<br> ast_cli(a->fd, "%s\n", "Events");<br> ast_cli(a->fd, "%s\n", "------");<br> <br>diff --git a/res/res_calendar_caldav.c b/res/res_calendar_caldav.c<br>index 6b4f908..355dd1f 100644<br>--- a/res/res_calendar_caldav.c<br>+++ b/res/res_calendar_caldav.c<br>@@ -158,6 +158,7 @@<br> ne_add_response_body_reader(req, debug_response_handler, fetch_response_reader, &response);<br> ne_set_request_body_buffer(req, ast_str_buffer(req_body), ast_str_strlen(req_body));<br> ne_add_request_header(req, "Content-type", ast_strlen_zero(content_type) ? "text/xml" : content_type);<br>+ ne_add_request_header(req, "Depth", "1");<br> <br> ret = ne_request_dispatch(req);<br> ne_request_destroy(req);<br>@@ -478,17 +479,26 @@<br> time_t end;<br> };<br> <br>-static void handle_start_element(void *data, const xmlChar *fullname, const xmlChar **atts)<br>+static const xmlChar *caldav_node_localname = BAD_CAST "calendar-data";<br>+static const xmlChar *caldav_node_nsuri = BAD_CAST "urn:ietf:params:xml:ns:caldav";<br>+<br>+static void handle_start_element(void *data,<br>+ const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri,<br>+ int nb_namespaces, const xmlChar **namespaces,<br>+ int nb_attributes, int nb_defaulted, const xmlChar **attributes)<br> {<br> struct xmlstate *state = data;<br> <br>- if (!xmlStrcasecmp(fullname, BAD_CAST "C:calendar-data") || !xmlStrcasecmp(fullname, BAD_CAST "caldav:calendar-data")) {<br>- state->in_caldata = 1;<br>- ast_str_reset(state->cdata);<br>+ if (xmlStrcmp(localname, caldav_node_localname) || xmlStrcmp(uri, caldav_node_nsuri)) {<br>+ return;<br> }<br>+<br>+ state->in_caldata = 1;<br>+ ast_str_reset(state->cdata);<br> }<br> <br>-static void handle_end_element(void *data, const xmlChar *name)<br>+static void handle_end_element(void *data,<br>+ const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri)<br> {<br> struct xmlstate *state = data;<br> struct icaltimetype start, end;<br>@@ -496,7 +506,7 @@<br> icalcomponent *iter;<br> icalcomponent *comp;<br> <br>- if (xmlStrcasecmp(name, BAD_CAST "C:calendar-data") && xmlStrcasecmp(name, BAD_CAST "caldav:calendar-data")) {<br>+ if (xmlStrcmp(localname, caldav_node_localname) || xmlStrcmp(uri, caldav_node_nsuri)) {<br> return;<br> }<br> <br>@@ -559,9 +569,23 @@<br> state.start = start;<br> state.end = end;<br> <br>+ /*<br>+ * We want SAX2, so you assume that we want to call xmlSAXVersion() here, and<br>+ * that certainly seems like the right thing to do, but the default SAX<br>+ * handling functions assume that the 'data' pointer is going to be a<br>+ * xmlParserCtxtPtr, not a user data pointer, so we have to make sure that we<br>+ * are only calling the handlers that we control.<br>+ *<br>+ * So instead we hack things up a bit, clearing the struct and then assigning<br>+ * the magic number manually.<br>+ *<br>+ * There may be a cleaner way to do this, but frankly the libxml2 docs are<br>+ * pretty sparse.<br>+ */<br> memset(&saxHandler, 0, sizeof(saxHandler));<br>- saxHandler.startElement = handle_start_element;<br>- saxHandler.endElement = handle_end_element;<br>+ saxHandler.initialized = XML_SAX2_MAGIC;<br>+ saxHandler.startElementNs = handle_start_element;<br>+ saxHandler.endElementNs = handle_end_element;<br> saxHandler.characters = handle_characters;<br> <br> xmlSAXUserParseMemory(&saxHandler, &state, ast_str_buffer(response), ast_str_strlen(response));<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/6491">change 6491</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/6491"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I200d11afca6a47e7d97888f286977e2e69874b2c </div>
<div style="display:none"> Gerrit-Change-Number: 6491 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Sean Bright <sean.bright@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>