#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"
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;
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;
}
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;
}
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)
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
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);