]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
xml.c: Update deprecated libxml2 API usage.
authorSean Bright <sean@seanbright.com>
Thu, 23 May 2024 14:23:03 +0000 (10:23 -0400)
committerAsterisk Development Team <asteriskteam@digium.com>
Thu, 11 Jul 2024 13:23:24 +0000 (13:23 +0000)
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

(cherry picked from commit f9a359c5c58b9e928f0038b952c8277f164f9a32)

main/xml.c
res/res_calendar_caldav.c

index 58003d63dede32d5b7482a0d75385cc8c1c20434..bd4c59f5defb0bef8cbb7edfec2b2ed9c5441e30 100644 (file)
@@ -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;
        }
 
index a5266f3369bf2c2b2bf6afa15df4108c89487233..d531f98063934e5269f7fe7393dd1f0157bb2be2 100644 (file)
@@ -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);