mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	res_calendar: Various fixes
* The way that we were looking at XML elements for CalDAV was extremely fragile, so use SAX2 for increased robustness. * Don't complain about a 'channel' not be specified if autoreminder is not set. Assume that if 'channel' is not set, we don't want to be notified. * Fix some truncated CLI output in 'calendar show calendar' and make the 'Autoreminder' description a bit more clear ASTERISK-24588 #close Reported by: Stefan Gofferje ASTERISK-25523 #close Reported by: Jesper Change-Id: I200d11afca6a47e7d97888f286977e2e69874b2c
This commit is contained in:
		| @@ -482,6 +482,13 @@ static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *c | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (cal->autoreminder && ast_strlen_zero(cal->notify_channel)) { | ||||
| 		ast_log(LOG_WARNING, | ||||
| 				"You have set 'autoreminder' but not 'channel' for calendar '%s.' " | ||||
| 				"Notifications will not occur.\n", | ||||
| 				cal->name); | ||||
| 	} | ||||
|  | ||||
| 	if (new_calendar) { | ||||
| 		cal->thread = AST_PTHREADT_NULL; | ||||
| 		ast_cond_init(&cal->unload, NULL); | ||||
| @@ -489,7 +496,7 @@ static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *c | ||||
| 		if (ast_pthread_create(&cal->thread, NULL, cal->tech->load_calendar, cal)) { | ||||
| 			/* If we start failing to create threads, go ahead and return NULL | ||||
| 			 * and the tech module will be unregistered | ||||
| 			 */  | ||||
| 			 */ | ||||
| 			ao2_unlink(calendars, cal); | ||||
| 			cal = unref_calendar(cal); | ||||
| 		} | ||||
| @@ -948,7 +955,7 @@ static int schedule_calendar_event(struct ast_calendar *cal, struct ast_calendar | ||||
| 	event = cmp_event ? cmp_event : old_event; | ||||
|  | ||||
| 	ao2_lock(event); | ||||
| 	if (!cmp_event || old_event->alarm != event->alarm) { | ||||
| 	if (!ast_strlen_zero(cal->notify_channel) && (!cmp_event || old_event->alarm != event->alarm)) { | ||||
| 		changed = 1; | ||||
| 		if (cal->autoreminder) { | ||||
| 			alarm_notify_sched = (event->start - (60 * cal->autoreminder) - now.tv_sec) * 1000; | ||||
| @@ -957,7 +964,7 @@ static int schedule_calendar_event(struct ast_calendar *cal, struct ast_calendar | ||||
| 		} | ||||
|  | ||||
| 		/* For now, send the notification if we missed it, but the meeting hasn't happened yet */ | ||||
| 		if (event->start >=  now.tv_sec) { | ||||
| 		if (event->start >= now.tv_sec) { | ||||
| 			if (alarm_notify_sched <= 0) { | ||||
| 				alarm_notify_sched = 1; | ||||
| 			} | ||||
| @@ -1590,7 +1597,7 @@ static char *epoch_to_string(char *buf, size_t buflen, time_t epoch) | ||||
|  | ||||
| static char *handle_show_calendar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||
| { | ||||
| #define FORMAT "%-17.17s : %-20.20s\n" | ||||
| #define FORMAT  "%-18.18s : %-20.20s\n" | ||||
| #define FORMAT2 "%-12.12s: %-40.60s\n" | ||||
| 	struct ao2_iterator i; | ||||
| 	struct ast_calendar *cal; | ||||
| @@ -1639,7 +1646,13 @@ static char *handle_show_calendar(struct ast_cli_entry *e, int cmd, struct ast_c | ||||
| 	ast_cli(a->fd, FORMAT, "Notify appdata", cal->notify_appdata); | ||||
| 	ast_cli(a->fd, "%-17.17s : %d\n", "Refresh time", cal->refresh); | ||||
| 	ast_cli(a->fd, "%-17.17s : %d\n", "Timeframe", cal->timeframe); | ||||
| 	ast_cli(a->fd, "%-17.17s : %d\n", "Autoreminder", cal->autoreminder); | ||||
|  | ||||
| 	if (cal->autoreminder) { | ||||
| 		ast_cli(a->fd, "%-17.17s : %d minutes before event\n", "Autoreminder", cal->autoreminder); | ||||
| 	} else { | ||||
| 		ast_cli(a->fd, "%-17.17s : None\n", "Autoreminder"); | ||||
| 	} | ||||
|  | ||||
| 	ast_cli(a->fd, "%s\n", "Events"); | ||||
| 	ast_cli(a->fd, "%s\n", "------"); | ||||
|  | ||||
|   | ||||
| @@ -158,6 +158,7 @@ static struct ast_str *caldav_request(struct caldav_pvt *pvt, const char *method | ||||
| 	ne_add_response_body_reader(req, debug_response_handler, fetch_response_reader, &response); | ||||
| 	ne_set_request_body_buffer(req, ast_str_buffer(req_body), ast_str_strlen(req_body)); | ||||
| 	ne_add_request_header(req, "Content-type", ast_strlen_zero(content_type) ? "text/xml" : content_type); | ||||
| 	ne_add_request_header(req, "Depth", "1"); | ||||
|  | ||||
| 	ret = ne_request_dispatch(req); | ||||
| 	ne_request_destroy(req); | ||||
| @@ -478,17 +479,26 @@ struct xmlstate { | ||||
| 	time_t end; | ||||
| }; | ||||
|  | ||||
| static void handle_start_element(void *data, const xmlChar *fullname, const xmlChar **atts) | ||||
| static const xmlChar *caldav_node_localname = BAD_CAST "calendar-data"; | ||||
| static const xmlChar *caldav_node_nsuri     = BAD_CAST "urn:ietf:params:xml:ns:caldav"; | ||||
|  | ||||
| static void handle_start_element(void *data, | ||||
| 								 const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri, | ||||
| 								 int nb_namespaces, const xmlChar **namespaces, | ||||
| 								 int nb_attributes, int nb_defaulted, const xmlChar **attributes) | ||||
| { | ||||
| 	struct xmlstate *state = data; | ||||
|  | ||||
| 	if (!xmlStrcasecmp(fullname, BAD_CAST "C:calendar-data") || !xmlStrcasecmp(fullname, BAD_CAST "caldav:calendar-data")) { | ||||
| 		state->in_caldata = 1; | ||||
| 		ast_str_reset(state->cdata); | ||||
| 	if (xmlStrcmp(localname, caldav_node_localname) || xmlStrcmp(uri, caldav_node_nsuri)) { | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	state->in_caldata = 1; | ||||
| 	ast_str_reset(state->cdata); | ||||
| } | ||||
|  | ||||
| static void handle_end_element(void *data, const xmlChar *name) | ||||
| static void handle_end_element(void *data, | ||||
| 							   const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri) | ||||
| { | ||||
| 	struct xmlstate *state = data; | ||||
| 	struct icaltimetype start, end; | ||||
| @@ -496,7 +506,7 @@ static void handle_end_element(void *data, const xmlChar *name) | ||||
| 	icalcomponent *iter; | ||||
| 	icalcomponent *comp; | ||||
|  | ||||
| 	if (xmlStrcasecmp(name, BAD_CAST "C:calendar-data") && xmlStrcasecmp(name, BAD_CAST "caldav:calendar-data")) { | ||||
| 	if (xmlStrcmp(localname, caldav_node_localname) || xmlStrcmp(uri, caldav_node_nsuri)) { | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| @@ -559,9 +569,23 @@ static int update_caldav(struct caldav_pvt *pvt) | ||||
| 	state.start = start; | ||||
| 	state.end = end; | ||||
|  | ||||
| 	/* | ||||
| 	 * We want SAX2, so you assume that we want to call xmlSAXVersion() here, and | ||||
| 	 * that certainly seems like the right thing to do, but the default SAX | ||||
| 	 * handling functions assume that the 'data' pointer is going to be a | ||||
| 	 * xmlParserCtxtPtr, not a user data pointer, so we have to make sure that we | ||||
| 	 * are only calling the handlers that we control. | ||||
| 	 * | ||||
| 	 * So instead we hack things up a bit, clearing the struct and then assigning | ||||
| 	 * the magic number manually. | ||||
| 	 * | ||||
| 	 * There may be a cleaner way to do this, but frankly the libxml2 docs are | ||||
| 	 * pretty sparse. | ||||
| 	 */ | ||||
| 	memset(&saxHandler, 0, sizeof(saxHandler)); | ||||
| 	saxHandler.startElement = handle_start_element; | ||||
| 	saxHandler.endElement = handle_end_element; | ||||
| 	saxHandler.initialized = XML_SAX2_MAGIC; | ||||
| 	saxHandler.startElementNs = handle_start_element; | ||||
| 	saxHandler.endElementNs = handle_end_element; | ||||
| 	saxHandler.characters = handle_characters; | ||||
|  | ||||
| 	xmlSAXUserParseMemory(&saxHandler, &state, ast_str_buffer(response), ast_str_strlen(response)); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user