xml.c: Update deprecated libxml2 API usage.

Two functions are deprecated as of libxml2 2.12:

  * xmlSubstituteEntitiesDefault
  * xmlParseMemory

So we update those with supported API.

Additionally, `res_calendar_caldav` has been updated to use libxml2's
xmlreader API instead of the SAX2 API which has always felt a little
hacky (see deleted comment block in `res_calendar_caldav.c`).

The xmlreader API has been around since libxml2 2.5.0 which was
released in 2003.

Fixes #725
pull/764/head
Sean Bright 11 months ago committed by asterisk-org-access-app[bot]
parent f789b7765b
commit f3e88d366c

@ -99,9 +99,7 @@ struct ast_xml_doc *ast_xml_open(char *filename)
return NULL;
}
xmlSubstituteEntitiesDefault(1);
doc = xmlReadFile(filename, NULL, XML_PARSE_RECOVER);
doc = xmlReadFile(filename, NULL, XML_PARSE_RECOVER | XML_PARSE_NOENT);
if (!doc) {
return NULL;
}
@ -505,9 +503,7 @@ struct ast_xslt_doc *ast_xslt_open(char *filename)
xsltStylesheet *xslt;
xmlDoc *xml;
xmlSubstituteEntitiesDefault(1);
xml = xmlReadFile(filename, NULL, XML_PARSE_RECOVER);
xml = xmlReadFile(filename, NULL, XML_PARSE_RECOVER | XML_PARSE_NOENT);
if (!xml) {
return NULL;
}
@ -535,9 +531,8 @@ struct ast_xslt_doc *ast_xslt_read_memory(char *buffer, size_t size)
return NULL;
}
xmlSubstituteEntitiesDefault(1);
if (!(doc = xmlParseMemory(buffer, (int) size))) {
doc = xmlReadMemory(buffer, (int) size, NULL, NULL, XML_PARSE_RECOVER | XML_PARSE_NOENT);
if (!doc) {
return NULL;
}

@ -36,8 +36,7 @@
#include <ne_request.h>
#include <ne_auth.h>
#include <ne_redirect.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xmlreader.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
@ -129,7 +128,11 @@ static int auth_credentials(void *userdata, const char *realm, int attempts, cha
static int debug_response_handler(void *userdata, ne_request *req, const ne_status *st)
{
if (st->code < 200 || st->code > 299) {
ast_debug(1, "Unexpected response from server, %d: %s\n", st->code, st->reason_phrase);
if (st->code == 401) {
ast_debug(1, "Got a 401 from the server but we expect this to happen when authenticating, %d: %s\n", st->code, st->reason_phrase);
} else {
ast_debug(1, "Unexpected response from server, %d: %s\n", st->code, st->reason_phrase);
}
return 0;
}
return 1;
@ -482,14 +485,12 @@ struct xmlstate {
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)
static void handle_start_element(xmlTextReaderPtr reader, struct xmlstate *state)
{
struct xmlstate *state = data;
const xmlChar *localname = xmlTextReaderConstLocalName(reader);
const xmlChar *uri = xmlTextReaderConstNamespaceUri(reader);
if (xmlStrcmp(localname, caldav_node_localname) || xmlStrcmp(uri, caldav_node_nsuri)) {
if (!xmlStrEqual(localname, caldav_node_localname) || !xmlStrEqual(uri, caldav_node_nsuri)) {
return;
}
@ -497,16 +498,16 @@ static void handle_start_element(void *data,
ast_str_reset(state->cdata);
}
static void handle_end_element(void *data,
const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri)
static void handle_end_element(xmlTextReaderPtr reader, struct xmlstate *state)
{
struct xmlstate *state = data;
struct icaltimetype start, end;
icaltimezone *utc = icaltimezone_get_utc_timezone();
icalcomponent *iter;
icalcomponent *comp;
const xmlChar *localname = xmlTextReaderConstLocalName(reader);
const xmlChar *uri = xmlTextReaderConstNamespaceUri(reader);
if (xmlStrcmp(localname, caldav_node_localname) || xmlStrcmp(uri, caldav_node_nsuri)) {
if (!xmlStrEqual(localname, caldav_node_localname) || !xmlStrEqual(uri, caldav_node_nsuri)) {
return;
}
@ -530,18 +531,39 @@ static void handle_end_element(void *data,
icalcomponent_free(comp);
}
static void handle_characters(void *data, const xmlChar *ch, int len)
static void handle_characters(xmlTextReaderPtr reader, struct xmlstate *state)
{
struct xmlstate *state = data;
xmlChar *tmp;
xmlChar *text;
if (!state->in_caldata) {
return;
}
tmp = xmlStrndup(ch, len);
ast_str_append(&state->cdata, 0, "%s", (char *)tmp);
xmlFree(tmp);
text = xmlTextReaderValue(reader);
if (text) {
ast_str_append(&state->cdata, 0, "%s", text);
xmlFree(text);
}
}
static void parse_error_handler(void *arg, const char *msg,
xmlParserSeverities severity, xmlTextReaderLocatorPtr locator)
{
switch (severity) {
case XML_PARSER_SEVERITY_VALIDITY_WARNING:
case XML_PARSER_SEVERITY_WARNING:
ast_log(LOG_WARNING, "While parsing CalDAV response at line %d: %s\n",
xmlTextReaderLocatorLineNumber(locator),
msg);
break;
case XML_PARSER_SEVERITY_VALIDITY_ERROR:
case XML_PARSER_SEVERITY_ERROR:
default:
ast_log(LOG_ERROR, "While parsing CalDAV response at line %d: %s\n",
xmlTextReaderLocatorLineNumber(locator),
msg);
break;
}
}
static int update_caldav(struct caldav_pvt *pvt)
@ -549,7 +571,7 @@ static int update_caldav(struct caldav_pvt *pvt)
struct timeval now = ast_tvnow();
time_t start, end;
struct ast_str *response;
xmlSAXHandler saxHandler;
xmlTextReaderPtr reader;
struct xmlstate state = {
.in_caldata = 0,
.pvt = pvt
@ -569,26 +591,39 @@ 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.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));
reader = xmlReaderForMemory(
ast_str_buffer(response),
ast_str_strlen(response),
NULL,
NULL,
0);
if (reader) {
int res;
xmlTextReaderSetErrorHandler(reader, parse_error_handler, NULL);
res = xmlTextReaderRead(reader);
while (res == 1) {
int node_type = xmlTextReaderNodeType(reader);
switch (node_type) {
case XML_READER_TYPE_ELEMENT:
handle_start_element(reader, &state);
break;
case XML_READER_TYPE_END_ELEMENT:
handle_end_element(reader, &state);
break;
case XML_READER_TYPE_TEXT:
case XML_READER_TYPE_CDATA:
handle_characters(reader, &state);
break;
default:
break;
}
res = xmlTextReaderRead(reader);
}
xmlFreeTextReader(reader);
}
ast_calendar_merge_events(pvt->owner, pvt->events);

Loading…
Cancel
Save