summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/expat/tests/handlers.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/expat/tests/handlers.c')
-rw-r--r--3rdparty/expat/tests/handlers.c1956
1 files changed, 1956 insertions, 0 deletions
diff --git a/3rdparty/expat/tests/handlers.c b/3rdparty/expat/tests/handlers.c
new file mode 100644
index 00000000000..0211985fe95
--- /dev/null
+++ b/3rdparty/expat/tests/handlers.c
@@ -0,0 +1,1956 @@
+/* XML handler functions for the Expat test suite
+ __ __ _
+ ___\ \/ /_ __ __ _| |_
+ / _ \\ /| '_ \ / _` | __|
+ | __// \| |_) | (_| | |_
+ \___/_/\_\ .__/ \__,_|\__|
+ |_| XML parser
+
+ Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
+ Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
+ Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
+ Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
+ Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
+ Copyright (c) 2017 Joe Orton <jorton@redhat.com>
+ Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
+ Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it>
+ Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
+ Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
+ Copyright (c) 2021 Donghee Na <donghee.na@python.org>
+ Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
+ Licensed under the MIT license:
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to permit
+ persons to whom the Software is furnished to do so, subject to the
+ following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if defined(NDEBUG)
+# undef NDEBUG /* because test suite relies on assert(...) at the moment */
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "expat_config.h"
+
+#include "expat.h"
+#include "internal.h"
+#include "chardata.h"
+#include "structdata.h"
+#include "common.h"
+#include "handlers.h"
+
+/* Global variables for user parameter settings tests */
+/* Variable holding the expected handler userData */
+const void *g_handler_data = NULL;
+/* Count of the number of times the comment handler has been invoked */
+int g_comment_count = 0;
+/* Count of the number of skipped entities */
+int g_skip_count = 0;
+/* Count of the number of times the XML declaration handler is invoked */
+int g_xdecl_count = 0;
+
+/* Start/End Element Handlers */
+
+void XMLCALL
+start_element_event_handler(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ UNUSED_P(atts);
+ CharData_AppendXMLChars((CharData *)userData, name, -1);
+}
+
+void XMLCALL
+end_element_event_handler(void *userData, const XML_Char *name) {
+ CharData *storage = (CharData *)userData;
+ CharData_AppendXMLChars(storage, XCS("/"), 1);
+ CharData_AppendXMLChars(storage, name, -1);
+}
+
+void XMLCALL
+start_element_event_handler2(void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ StructData *storage = (StructData *)userData;
+ UNUSED_P(attr);
+ StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
+ XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
+}
+
+void XMLCALL
+end_element_event_handler2(void *userData, const XML_Char *name) {
+ StructData *storage = (StructData *)userData;
+ StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
+ XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
+}
+
+void XMLCALL
+counting_start_element_handler(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ ParserAndElementInfo *const parserAndElementInfos
+ = (ParserAndElementInfo *)userData;
+ ElementInfo *info = parserAndElementInfos->info;
+ AttrInfo *attr;
+ int count, id, i;
+
+ while (info->name != NULL) {
+ if (! xcstrcmp(name, info->name))
+ break;
+ info++;
+ }
+ if (info->name == NULL)
+ fail("Element not recognised");
+ /* The attribute count is twice what you might expect. It is a
+ * count of items in atts, an array which contains alternating
+ * attribute names and attribute values. For the naive user this
+ * is possibly a little unexpected, but it is what the
+ * documentation in expat.h tells us to expect.
+ */
+ count = XML_GetSpecifiedAttributeCount(parserAndElementInfos->parser);
+ if (info->attr_count * 2 != count) {
+ fail("Not got expected attribute count");
+ return;
+ }
+ id = XML_GetIdAttributeIndex(parserAndElementInfos->parser);
+ if (id == -1 && info->id_name != NULL) {
+ fail("ID not present");
+ return;
+ }
+ if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
+ fail("ID does not have the correct name");
+ return;
+ }
+ for (i = 0; i < info->attr_count; i++) {
+ attr = info->attributes;
+ while (attr->name != NULL) {
+ if (! xcstrcmp(atts[0], attr->name))
+ break;
+ attr++;
+ }
+ if (attr->name == NULL) {
+ fail("Attribute not recognised");
+ return;
+ }
+ if (xcstrcmp(atts[1], attr->value)) {
+ fail("Attribute has wrong value");
+ return;
+ }
+ /* Remember, two entries in atts per attribute (see above) */
+ atts += 2;
+ }
+}
+
+void XMLCALL
+suspending_end_handler(void *userData, const XML_Char *s) {
+ UNUSED_P(s);
+ XML_StopParser((XML_Parser)userData, 1);
+}
+
+void XMLCALL
+start_element_suspender(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ UNUSED_P(userData);
+ UNUSED_P(atts);
+ if (! xcstrcmp(name, XCS("suspend")))
+ XML_StopParser(g_parser, XML_TRUE);
+ if (! xcstrcmp(name, XCS("abort")))
+ XML_StopParser(g_parser, XML_FALSE);
+}
+
+/* Check that an element name and attribute name match the expected values.
+ The expected values are passed as an array reference of string pointers
+ provided as the userData argument; the first is the expected
+ element name, and the second is the expected attribute name.
+*/
+int g_triplet_start_flag = XML_FALSE;
+int g_triplet_end_flag = XML_FALSE;
+
+void XMLCALL
+triplet_start_checker(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ XML_Char **elemstr = (XML_Char **)userData;
+ char buffer[1024];
+ if (xcstrcmp(elemstr[0], name) != 0) {
+ snprintf(buffer, sizeof(buffer),
+ "unexpected start string: '%" XML_FMT_STR "'", name);
+ fail(buffer);
+ }
+ if (xcstrcmp(elemstr[1], atts[0]) != 0) {
+ snprintf(buffer, sizeof(buffer),
+ "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
+ fail(buffer);
+ }
+ g_triplet_start_flag = XML_TRUE;
+}
+
+/* Check that the element name passed to the end-element handler matches
+ the expected value. The expected value is passed as the first element
+ in an array of strings passed as the userData argument.
+*/
+void XMLCALL
+triplet_end_checker(void *userData, const XML_Char *name) {
+ XML_Char **elemstr = (XML_Char **)userData;
+ if (xcstrcmp(elemstr[0], name) != 0) {
+ char buffer[1024];
+ snprintf(buffer, sizeof(buffer),
+ "unexpected end string: '%" XML_FMT_STR "'", name);
+ fail(buffer);
+ }
+ g_triplet_end_flag = XML_TRUE;
+}
+
+void XMLCALL
+overwrite_start_checker(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ CharData *storage = (CharData *)userData;
+ CharData_AppendXMLChars(storage, XCS("start "), 6);
+ CharData_AppendXMLChars(storage, name, -1);
+ while (*atts != NULL) {
+ CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
+ CharData_AppendXMLChars(storage, *atts, -1);
+ atts += 2;
+ }
+ CharData_AppendXMLChars(storage, XCS("\n"), 1);
+}
+
+void XMLCALL
+overwrite_end_checker(void *userData, const XML_Char *name) {
+ CharData *storage = (CharData *)userData;
+ CharData_AppendXMLChars(storage, XCS("end "), 4);
+ CharData_AppendXMLChars(storage, name, -1);
+ CharData_AppendXMLChars(storage, XCS("\n"), 1);
+}
+
+void XMLCALL
+start_element_fail(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ UNUSED_P(userData);
+ UNUSED_P(name);
+ UNUSED_P(atts);
+
+ /* We should never get here. */
+ fail("should never reach start_element_fail()");
+}
+
+void XMLCALL
+start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
+ const XML_Char *uri) {
+ UNUSED_P(prefix);
+ UNUSED_P(uri);
+ XML_SetStartElementHandler((XML_Parser)userData, NULL);
+}
+
+void XMLCALL
+start_element_issue_240(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ DataIssue240 *mydata = (DataIssue240 *)userData;
+ UNUSED_P(name);
+ UNUSED_P(atts);
+ mydata->deep++;
+}
+
+void XMLCALL
+end_element_issue_240(void *userData, const XML_Char *name) {
+ DataIssue240 *mydata = (DataIssue240 *)userData;
+
+ UNUSED_P(name);
+ mydata->deep--;
+ if (mydata->deep == 0) {
+ XML_StopParser(mydata->parser, 0);
+ }
+}
+
+/* Text encoding handlers */
+
+int XMLCALL
+UnknownEncodingHandler(void *data, const XML_Char *encoding,
+ XML_Encoding *info) {
+ UNUSED_P(data);
+ if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
+ int i;
+ for (i = 0; i < 256; ++i)
+ info->map[i] = i;
+ info->data = NULL;
+ info->convert = NULL;
+ info->release = NULL;
+ return XML_STATUS_OK;
+ }
+ return XML_STATUS_ERROR;
+}
+
+static void
+dummy_release(void *data) {
+ UNUSED_P(data);
+}
+
+int XMLCALL
+UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
+ XML_Encoding *info) {
+ UNUSED_P(data);
+ UNUSED_P(encoding);
+ info->data = NULL;
+ info->convert = NULL;
+ info->release = dummy_release;
+ return XML_STATUS_ERROR;
+}
+
+int XMLCALL
+unknown_released_encoding_handler(void *data, const XML_Char *encoding,
+ XML_Encoding *info) {
+ UNUSED_P(data);
+ if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
+ int i;
+
+ for (i = 0; i < 256; i++)
+ info->map[i] = i;
+ info->data = NULL;
+ info->convert = NULL;
+ info->release = dummy_release;
+ return XML_STATUS_OK;
+ }
+ return XML_STATUS_ERROR;
+}
+
+static int XMLCALL
+failing_converter(void *data, const char *s) {
+ UNUSED_P(data);
+ UNUSED_P(s);
+ /* Always claim to have failed */
+ return -1;
+}
+
+static int XMLCALL
+prefix_converter(void *data, const char *s) {
+ UNUSED_P(data);
+ /* If the first byte is 0xff, raise an error */
+ if (s[0] == (char)-1)
+ return -1;
+ /* Just add the low bits of the first byte to the second */
+ return (s[1] + (s[0] & 0x7f)) & 0x01ff;
+}
+
+int XMLCALL
+MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
+ int i;
+ int high_map = -2; /* Assume a 2-byte sequence */
+
+ if (! xcstrcmp(encoding, XCS("invalid-9"))
+ || ! xcstrcmp(encoding, XCS("ascii-like"))
+ || ! xcstrcmp(encoding, XCS("invalid-len"))
+ || ! xcstrcmp(encoding, XCS("invalid-a"))
+ || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
+ || ! xcstrcmp(encoding, XCS("invalid-high")))
+ high_map = -1;
+
+ for (i = 0; i < 128; ++i)
+ info->map[i] = i;
+ for (; i < 256; ++i)
+ info->map[i] = high_map;
+
+ /* If required, put an invalid value in the ASCII entries */
+ if (! xcstrcmp(encoding, XCS("invalid-9")))
+ info->map[9] = 5;
+ /* If required, have a top-bit set character starts a 5-byte sequence */
+ if (! xcstrcmp(encoding, XCS("invalid-len")))
+ info->map[0x81] = -5;
+ /* If required, make a top-bit set character a valid ASCII character */
+ if (! xcstrcmp(encoding, XCS("invalid-a")))
+ info->map[0x82] = 'a';
+ /* If required, give a top-bit set character a forbidden value,
+ * what would otherwise be the first of a surrogate pair.
+ */
+ if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
+ info->map[0x83] = 0xd801;
+ /* If required, give a top-bit set character too high a value */
+ if (! xcstrcmp(encoding, XCS("invalid-high")))
+ info->map[0x84] = 0x010101;
+
+ info->data = data;
+ info->release = NULL;
+ if (! xcstrcmp(encoding, XCS("failing-conv")))
+ info->convert = failing_converter;
+ else if (! xcstrcmp(encoding, XCS("prefix-conv")))
+ info->convert = prefix_converter;
+ else
+ info->convert = NULL;
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+long_encoding_handler(void *userData, const XML_Char *encoding,
+ XML_Encoding *info) {
+ int i;
+
+ UNUSED_P(userData);
+ UNUSED_P(encoding);
+ for (i = 0; i < 256; i++)
+ info->map[i] = i;
+ info->data = NULL;
+ info->convert = NULL;
+ info->release = NULL;
+ return XML_STATUS_OK;
+}
+
+/* External Entity Handlers */
+
+int XMLCALL
+external_entity_optioner(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ ExtOption *options = (ExtOption *)XML_GetUserData(parser);
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(publicId);
+ while (options->parse_text != NULL) {
+ if (! xcstrcmp(systemId, options->system_id)) {
+ enum XML_Status rc;
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ return XML_STATUS_ERROR;
+ rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
+ (int)strlen(options->parse_text), XML_TRUE);
+ XML_ParserFree(ext_parser);
+ return rc;
+ }
+ options++;
+ }
+ fail("No suitable option found");
+ return XML_STATUS_ERROR;
+}
+
+int XMLCALL
+external_entity_loader(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
+ XML_Parser extparser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (extparser == NULL)
+ fail("Could not create external entity parser.");
+ if (test_data->encoding != NULL) {
+ if (! XML_SetEncoding(extparser, test_data->encoding))
+ fail("XML_SetEncoding() ignored for external entity");
+ }
+ if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
+ (int)strlen(test_data->parse_text), XML_TRUE)
+ == XML_STATUS_ERROR) {
+ xml_failure(extparser);
+ return XML_STATUS_ERROR;
+ }
+ XML_ParserFree(extparser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_faulter(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ XML_Parser ext_parser;
+ ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ if (fault->encoding != NULL) {
+ if (! XML_SetEncoding(ext_parser, fault->encoding))
+ fail("XML_SetEncoding failed");
+ }
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
+ (int)strlen(fault->parse_text), XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail(fault->fail_text);
+ if (XML_GetErrorCode(ext_parser) != fault->error)
+ xml_failure(ext_parser);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_ERROR;
+}
+
+int XMLCALL
+external_entity_null_loader(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ UNUSED_P(parser);
+ UNUSED_P(context);
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_resetter(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<!ELEMENT doc (#PCDATA)*>";
+ XML_Parser ext_parser;
+ XML_ParsingStatus status;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ XML_GetParsingStatus(ext_parser, &status);
+ if (status.parsing != XML_INITIALIZED) {
+ fail("Parsing status is not INITIALIZED");
+ return XML_STATUS_ERROR;
+ }
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR) {
+ xml_failure(parser);
+ return XML_STATUS_ERROR;
+ }
+ XML_GetParsingStatus(ext_parser, &status);
+ if (status.parsing != XML_FINISHED) {
+ fail("Parsing status is not FINISHED");
+ return XML_STATUS_ERROR;
+ }
+ /* Check we can't parse here */
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail("Parsing when finished not faulted");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
+ fail("Parsing when finished faulted with wrong code");
+ XML_ParserReset(ext_parser, NULL);
+ XML_GetParsingStatus(ext_parser, &status);
+ if (status.parsing != XML_FINISHED) {
+ fail("Parsing status not still FINISHED");
+ return XML_STATUS_ERROR;
+ }
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+void XMLCALL
+entity_suspending_decl_handler(void *userData, const XML_Char *name,
+ XML_Content *model) {
+ XML_Parser ext_parser = (XML_Parser)userData;
+
+ UNUSED_P(name);
+ if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
+ fail("Attempting to suspend a subordinate parser not faulted");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
+ fail("Suspending subordinate parser get wrong code");
+ XML_SetElementDeclHandler(ext_parser, NULL);
+ XML_FreeContentModel(g_parser, model);
+}
+
+int XMLCALL
+external_entity_suspender(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<!ELEMENT doc (#PCDATA)*>";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
+ XML_SetUserData(ext_parser, ext_parser);
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR) {
+ xml_failure(ext_parser);
+ return XML_STATUS_ERROR;
+ }
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+void XMLCALL
+entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
+ const XML_Char *encoding, int standalone) {
+ XML_Parser ext_parser = (XML_Parser)userData;
+
+ UNUSED_P(version);
+ UNUSED_P(encoding);
+ UNUSED_P(standalone);
+ XML_StopParser(ext_parser, g_resumable);
+ XML_SetXmlDeclHandler(ext_parser, NULL);
+}
+
+int XMLCALL
+external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
+ XML_Parser ext_parser;
+ XML_ParsingStatus status;
+ enum XML_Status rc;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
+ XML_SetUserData(ext_parser, ext_parser);
+ rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
+ XML_GetParsingStatus(ext_parser, &status);
+ if (g_resumable) {
+ if (rc == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+ if (status.parsing != XML_SUSPENDED)
+ fail("Ext Parsing status not SUSPENDED");
+ } else {
+ if (rc != XML_STATUS_ERROR)
+ fail("Ext parsing not aborted");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
+ xml_failure(ext_parser);
+ if (status.parsing != XML_FINISHED)
+ fail("Ext Parsing status not FINISHED");
+ }
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ XML_Parser ext_parser;
+ ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
+ void *buffer;
+ int parse_len = (int)strlen(fault->parse_text);
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
+ XML_SetUserData(ext_parser, ext_parser);
+ g_resumable = XML_TRUE;
+ buffer = XML_GetBuffer(ext_parser, parse_len);
+ if (buffer == NULL)
+ fail("Could not allocate parse buffer");
+ assert(buffer != NULL);
+ memcpy(buffer, fault->parse_text, parse_len);
+ if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
+ fail("XML declaration did not suspend");
+ if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
+ xml_failure(ext_parser);
+ if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
+ fail(fault->fail_text);
+ if (XML_GetErrorCode(ext_parser) != fault->error)
+ xml_failure(ext_parser);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_ERROR;
+}
+
+int XMLCALL
+external_entity_failer__if_not_xml_ge(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ UNUSED_P(parser);
+ UNUSED_P(context);
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+#if XML_GE == 0
+ fail(
+ "Function external_entity_suspending_failer was called despite XML_GE==0.");
+#endif
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "\r";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<tag>\r";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_OK)
+ fail("Async entity error not caught");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
+ xml_failure(ext_parser);
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<tag>]";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail("Async entity error not caught");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
+ xml_failure(ext_parser);
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
+ const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
+ CharData storage;
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ CharData_Init(&storage);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ XML_SetUserData(ext_parser, &storage);
+ XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
+
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+ CharData_CheckXMLChars(&storage, expected);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_param_checker(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<!-- Subordinate parser -->\n"
+ "<!ELEMENT doc (#PCDATA)*>";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ g_handler_data = ext_parser;
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR) {
+ xml_failure(parser);
+ return XML_STATUS_ERROR;
+ }
+ g_handler_data = parser;
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<!ELEMENT doc (#PCDATA)*>";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ if ((void *)parameter != g_handler_data)
+ fail("External entity ref handler parameter not correct");
+
+ /* Here we use the global 'parser' variable */
+ ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_param(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text1 = "<!ELEMENT doc EMPTY>\n"
+ "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
+ "<!ENTITY % e2 '%e1;'>\n"
+ "%e1;\n";
+ const char *text2 = "<!ELEMENT el EMPTY>\n"
+ "<el/>\n";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(publicId);
+ if (systemId == NULL)
+ return XML_STATUS_OK;
+
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+
+ if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail("Inner DTD with invalid tag not rejected");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
+ xml_failure(ext_parser);
+ } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail("Invalid tag in external param not rejected");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
+ xml_failure(ext_parser);
+ } else {
+ fail("Unknown system ID");
+ }
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_ERROR;
+}
+
+int XMLCALL
+external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(parser);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char text[] =
+ /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
+ "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
+ "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
+ "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(parser);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char text[] =
+ /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
+ "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
+ "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
+ "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(parser);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_valuer(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text1 = "<!ELEMENT doc EMPTY>\n"
+ "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
+ "<!ENTITY % e2 '%e1;'>\n"
+ "%e1;\n";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(publicId);
+ if (systemId == NULL)
+ return XML_STATUS_OK;
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+ } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
+ ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
+ enum XML_Status status;
+ enum XML_Error error;
+
+ status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
+ (int)strlen(fault->parse_text), XML_TRUE);
+ if (fault->error == XML_ERROR_NONE) {
+ if (status == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+ } else {
+ if (status != XML_STATUS_ERROR)
+ fail(fault->fail_text);
+ error = XML_GetErrorCode(ext_parser);
+ if (error != fault->error
+ && (fault->error != XML_ERROR_XML_DECL
+ || error != XML_ERROR_TEXT_DECL))
+ xml_failure(ext_parser);
+ }
+ }
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text1 = "<!ELEMENT doc EMPTY>\n"
+ "<!ENTITY % e1 SYSTEM 'bar'>\n"
+ "%e1;\n";
+ const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(publicId);
+ if (systemId == NULL)
+ return XML_STATUS_OK;
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ if (! xcstrcmp(systemId, XCS("foo"))) {
+ XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail("Expected not standalone rejection");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
+ xml_failure(ext_parser);
+ XML_SetNotStandaloneHandler(ext_parser, NULL);
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_ERROR;
+ } else if (! xcstrcmp(systemId, XCS("bar"))) {
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+ }
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text1 = "<!ELEMENT doc EMPTY>\n"
+ "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
+ "<!ENTITY % e2 '%e1;'>\n"
+ "%e1;\n";
+ const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(publicId);
+ if (systemId == NULL)
+ return XML_STATUS_OK;
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+ if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+ }
+ if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
+ XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
+ XML_SetUserData(ext_parser, ext_parser);
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail("Aborted parse not faulted");
+ if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
+ xml_failure(ext_parser);
+ }
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_public(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text1 = (const char *)XML_GetUserData(parser);
+ const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
+ const char *text = NULL;
+ XML_Parser ext_parser;
+ int parse_res;
+
+ UNUSED_P(base);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ return XML_STATUS_ERROR;
+ if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
+ text = text1;
+ } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
+ text = text2;
+ } else
+ fail("Unexpected parameters to external entity parser");
+ assert(text != NULL);
+ parse_res
+ = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
+ XML_ParserFree(ext_parser);
+ return parse_res;
+}
+
+int XMLCALL
+external_entity_devaluer(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<!ELEMENT doc EMPTY>\n"
+ "<!ENTITY % e1 SYSTEM 'bar'>\n"
+ "%e1;\n";
+ XML_Parser ext_parser;
+ int clear_handler_flag = (XML_GetUserData(parser) != NULL);
+
+ UNUSED_P(base);
+ UNUSED_P(publicId);
+ if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
+ return XML_STATUS_OK;
+ if (xcstrcmp(systemId, XCS("foo")))
+ fail("Unexpected system ID");
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could note create external entity parser");
+ if (clear_handler_flag)
+ XML_SetExternalEntityRefHandler(ext_parser, NULL);
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser.");
+ /* Use the requested entity parser for further externals */
+ XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
+ (int)strlen(test_data->parse_text), XML_TRUE)
+ == XML_STATUS_ERROR) {
+ xml_failure(ext_parser);
+ }
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_loader2(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
+ XML_Parser extparser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (extparser == NULL)
+ fail("Coulr not create external entity parser");
+ if (test_data->encoding != NULL) {
+ if (! XML_SetEncoding(extparser, test_data->encoding))
+ fail("XML_SetEncoding() ignored for external entity");
+ }
+ if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
+ test_data->parse_len, XML_TRUE)
+ == XML_STATUS_ERROR) {
+ xml_failure(extparser);
+ }
+
+ XML_ParserFree(extparser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_faulter2(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
+ XML_Parser extparser;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (extparser == NULL)
+ fail("Could not create external entity parser");
+ if (test_data->encoding != NULL) {
+ if (! XML_SetEncoding(extparser, test_data->encoding))
+ fail("XML_SetEncoding() ignored for external entity");
+ }
+ if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
+ test_data->parse_len, XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail(test_data->fail_text);
+ if (XML_GetErrorCode(extparser) != test_data->error)
+ xml_failure(extparser);
+
+ XML_ParserFree(extparser);
+ return XML_STATUS_ERROR;
+}
+
+int XMLCALL
+external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = "<!ELEMENT barf ANY>\n"
+ "<!ATTLIST barf my_attr (blah|%blah;a|foo) #REQUIRED>\n"
+ "<!--COMMENT-->\n";
+ XML_Parser ext_parser;
+
+ UNUSED_P(base);
+ UNUSED_P(publicId);
+ if (systemId == NULL)
+ return XML_STATUS_OK;
+
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+
+ if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(ext_parser);
+
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_handler(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ void *user_data = XML_GetUserData(parser);
+ const char *text;
+ XML_Parser p2;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ if (user_data == NULL)
+ text = ("<!ELEMENT doc (e+)>\n"
+ "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
+ "<!ELEMENT e EMPTY>\n");
+ else
+ text = ("<?xml version='1.0' encoding='us-ascii'?>"
+ "<e/>");
+
+ /* Set user data to any non-NULL value */
+ XML_SetUserData(parser, parser);
+ p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR) {
+ xml_failure(p2);
+ return XML_STATUS_ERROR;
+ }
+ XML_ParserFree(p2);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ XML_Parser new_parser;
+ unsigned int i;
+ const unsigned int max_alloc_count = 10;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ /* Try a few different allocation levels */
+ for (i = 0; i < max_alloc_count; i++) {
+ g_allocation_count = i;
+ new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (new_parser != NULL) {
+ XML_ParserFree(new_parser);
+ break;
+ }
+ }
+ if (i == 0)
+ fail("External parser creation ignored failing allocator");
+ else if (i == max_alloc_count)
+ fail("Extern parser not created with max allocation count");
+
+ /* Make sure other random allocation doesn't now fail */
+ g_allocation_count = ALLOC_ALWAYS_SUCCEED;
+
+ /* Make sure the failure code path is executed too */
+ return XML_STATUS_ERROR;
+}
+
+int XMLCALL
+external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ int *pcallno = (int *)XML_GetUserData(parser);
+ int callno = *pcallno;
+ const char *text;
+ XML_Parser new_parser = NULL;
+ int i;
+ const int max_alloc_count = 20;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ if (callno == 0) {
+ /* First time through, check how many calls to malloc occur */
+ text = ("<!ELEMENT doc (e+)>\n"
+ "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
+ "<!ELEMENT e EMPTY>\n");
+ g_allocation_count = 10000;
+ new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (new_parser == NULL) {
+ fail("Unable to allocate first external parser");
+ return XML_STATUS_ERROR;
+ }
+ /* Stash the number of calls in the user data */
+ *pcallno = 10000 - g_allocation_count;
+ } else {
+ text = ("<?xml version='1.0' encoding='us-ascii'?>"
+ "<e/>");
+ /* Try at varying levels to exercise more code paths */
+ for (i = 0; i < max_alloc_count; i++) {
+ g_allocation_count = callno + i;
+ new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (new_parser != NULL)
+ break;
+ }
+ if (i == 0) {
+ fail("Second external parser unexpectedly created");
+ XML_ParserFree(new_parser);
+ return XML_STATUS_ERROR;
+ } else if (i == max_alloc_count) {
+ fail("Second external parser not created");
+ return XML_STATUS_ERROR;
+ }
+ }
+
+ g_allocation_count = ALLOC_ALWAYS_SUCCEED;
+ if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR) {
+ xml_failure(new_parser);
+ return XML_STATUS_ERROR;
+ }
+ XML_ParserFree(new_parser);
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ int *pcallno = (int *)XML_GetUserData(parser);
+ int callno = *pcallno;
+ const char *text;
+ XML_Parser new_parser;
+ enum XML_Status rv;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ if (callno == 0) {
+ /* Try different allocation levels for whole exercise */
+ text = ("<!ELEMENT doc (e+)>\n"
+ "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
+ "<!ELEMENT e EMPTY>\n");
+ *pcallno = 1;
+ new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (new_parser == NULL)
+ return XML_STATUS_ERROR;
+ rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
+ } else {
+ /* Just run through once */
+ text = ("<?xml version='1.0' encoding='us-ascii'?>"
+ "<e/>");
+ new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (new_parser == NULL)
+ return XML_STATUS_ERROR;
+ rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
+ }
+ XML_ParserFree(new_parser);
+ if (rv == XML_STATUS_ERROR)
+ return XML_STATUS_ERROR;
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ /* As for external_entity_loader() */
+ const char *text = "<?xml encoding='iso-8859-3'?>"
+ "\xC3\xA9";
+ XML_Parser ext_parser;
+ enum XML_Status status;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ return XML_STATUS_ERROR;
+ if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
+ XML_ParserFree(ext_parser);
+ return XML_STATUS_ERROR;
+ }
+ status
+ = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
+ XML_ParserFree(ext_parser);
+ if (status == XML_STATUS_ERROR)
+ return XML_STATUS_ERROR;
+ return XML_STATUS_OK;
+}
+
+int XMLCALL
+external_entity_reallocator(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = get_buffer_test_text;
+ XML_Parser ext_parser;
+ void *buffer;
+ enum XML_Status status;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ fail("Could not create external entity parser");
+
+ g_reallocation_count = *(int *)XML_GetUserData(parser);
+ buffer = XML_GetBuffer(ext_parser, 1536);
+ if (buffer == NULL)
+ fail("Buffer allocation failed");
+ assert(buffer != NULL);
+ memcpy(buffer, text, strlen(text));
+ status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
+ g_reallocation_count = -1;
+ XML_ParserFree(ext_parser);
+ return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
+}
+
+int XMLCALL
+external_entity_alloc(XML_Parser parser, const XML_Char *context,
+ const XML_Char *base, const XML_Char *systemId,
+ const XML_Char *publicId) {
+ const char *text = (const char *)XML_GetUserData(parser);
+ XML_Parser ext_parser;
+ int parse_res;
+
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+ if (ext_parser == NULL)
+ return XML_STATUS_ERROR;
+ parse_res
+ = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
+ XML_ParserFree(ext_parser);
+ return parse_res;
+}
+
+int XMLCALL
+external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+
+ if (context != NULL)
+ fail("Unexpected non-NULL context");
+
+ // The following number intends to fail the upcoming allocation in line
+ // "parser->m_protocolEncodingName = copyString(encodingName,
+ // &(parser->m_mem));" in function parserInit.
+ g_allocation_count = 3;
+
+ const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
+ const XML_Parser ext_parser
+ = XML_ExternalEntityParserCreate(parser, context, encodingName);
+ if (ext_parser != NULL)
+ fail(
+ "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
+
+ g_allocation_count = ALLOC_ALWAYS_SUCCEED;
+ return XML_STATUS_ERROR;
+}
+
+#if XML_GE == 1
+int
+accounting_external_entity_ref_handler(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ UNUSED_P(base);
+ UNUSED_P(publicId);
+
+ const struct AccountingTestCase *const testCase
+ = (const struct AccountingTestCase *)XML_GetUserData(parser);
+
+ const char *externalText = NULL;
+ if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
+ externalText = testCase->firstExternalText;
+ } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
+ externalText = testCase->secondExternalText;
+ } else {
+ assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
+ }
+ assert(externalText);
+
+ XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
+ assert(entParser);
+
+ const enum XML_Status status = _XML_Parse_SINGLE_BYTES(
+ entParser, externalText, (int)strlen(externalText), XML_TRUE);
+
+ XML_ParserFree(entParser);
+ return status;
+}
+#endif /* XML_GE == 1 */
+
+/* NotStandalone handlers */
+
+int XMLCALL
+reject_not_standalone_handler(void *userData) {
+ UNUSED_P(userData);
+ return XML_STATUS_ERROR;
+}
+
+int XMLCALL
+accept_not_standalone_handler(void *userData) {
+ UNUSED_P(userData);
+ return XML_STATUS_OK;
+}
+
+/* Attribute List handlers */
+void XMLCALL
+verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
+ const XML_Char *attr_name,
+ const XML_Char *attr_type,
+ const XML_Char *default_value, int is_required) {
+ AttTest *at = (AttTest *)userData;
+
+ if (xcstrcmp(element_name, at->element_name))
+ fail("Unexpected element name in attribute declaration");
+ if (xcstrcmp(attr_name, at->attr_name))
+ fail("Unexpected attribute name in attribute declaration");
+ if (xcstrcmp(attr_type, at->attr_type))
+ fail("Unexpected attribute type in attribute declaration");
+ if ((default_value == NULL && at->default_value != NULL)
+ || (default_value != NULL && at->default_value == NULL)
+ || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
+ fail("Unexpected default value in attribute declaration");
+ if (is_required != at->is_required)
+ fail("Requirement mismatch in attribute declaration");
+}
+
+/* Character Data handlers */
+
+void XMLCALL
+clearing_aborting_character_handler(void *userData, const XML_Char *s,
+ int len) {
+ UNUSED_P(userData);
+ UNUSED_P(s);
+ UNUSED_P(len);
+ XML_StopParser(g_parser, g_resumable);
+ XML_SetCharacterDataHandler(g_parser, NULL);
+}
+
+void XMLCALL
+parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
+ UNUSED_P(userData);
+ UNUSED_P(s);
+ UNUSED_P(len);
+ XML_ParsingStatus status;
+ XML_GetParsingStatus(g_parser, &status);
+ if (status.parsing == XML_FINISHED) {
+ return; // the parser was stopped by a previous call to this handler.
+ }
+ XML_StopParser(g_parser, g_resumable);
+ XML_SetCharacterDataHandler(g_parser, NULL);
+ if (! g_resumable) {
+ /* Check that aborting an aborted parser is faulted */
+ if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
+ fail("Aborting aborted parser not faulted");
+ if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
+ xml_failure(g_parser);
+ } else if (g_abortable) {
+ /* Check that aborting a suspended parser works */
+ if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
+ xml_failure(g_parser);
+ } else {
+ /* Check that suspending a suspended parser works */
+ if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
+ fail("Suspending suspended parser not faulted");
+ if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
+ xml_failure(g_parser);
+ }
+}
+
+void XMLCALL
+cr_cdata_handler(void *userData, const XML_Char *s, int len) {
+ int *pfound = (int *)userData;
+
+ /* Internal processing turns the CR into a newline for the
+ * character data handler, but not for the default handler
+ */
+ if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
+ *pfound = 1;
+}
+
+void XMLCALL
+rsqb_handler(void *userData, const XML_Char *s, int len) {
+ int *pfound = (int *)userData;
+
+ if (len == 1 && *s == XCS(']'))
+ *pfound = 1;
+}
+
+void XMLCALL
+byte_character_handler(void *userData, const XML_Char *s, int len) {
+#if XML_CONTEXT_BYTES > 0
+ int offset, size;
+ const char *buffer;
+ ByteTestData *data = (ByteTestData *)userData;
+
+ UNUSED_P(s);
+ buffer = XML_GetInputContext(g_parser, &offset, &size);
+ if (buffer == NULL)
+ fail("Failed to get context buffer");
+ if (offset != data->start_element_len)
+ fail("Context offset in unexpected position");
+ if (len != data->cdata_len)
+ fail("CDATA length reported incorrectly");
+ if (size != data->total_string_len)
+ fail("Context size is not full buffer");
+ if (XML_GetCurrentByteIndex(g_parser) != offset)
+ fail("Character byte index incorrect");
+ if (XML_GetCurrentByteCount(g_parser) != len)
+ fail("Character byte count incorrect");
+#else
+ UNUSED_P(s);
+ UNUSED_P(userData);
+ UNUSED_P(len);
+#endif
+}
+
+void XMLCALL
+ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
+ ExtTest2 *test_data = (ExtTest2 *)userData;
+ accumulate_characters(test_data->storage, s, len);
+}
+
+/* Handlers that record their function name and int arg. */
+
+static void
+record_call(struct handler_record_list *const rec, const char *funcname,
+ const int arg) {
+ const int max_entries = sizeof(rec->entries) / sizeof(rec->entries[0]);
+ assert_true(rec->count < max_entries);
+ struct handler_record_entry *const e = &rec->entries[rec->count++];
+ e->name = funcname;
+ e->arg = arg;
+}
+
+void XMLCALL
+record_default_handler(void *userData, const XML_Char *s, int len) {
+ UNUSED_P(s);
+ record_call((struct handler_record_list *)userData, __func__, len);
+}
+
+void XMLCALL
+record_cdata_handler(void *userData, const XML_Char *s, int len) {
+ UNUSED_P(s);
+ record_call((struct handler_record_list *)userData, __func__, len);
+ XML_DefaultCurrent(g_parser);
+}
+
+void XMLCALL
+record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
+ UNUSED_P(s);
+ record_call((struct handler_record_list *)userData, __func__, len);
+}
+
+void XMLCALL
+record_skip_handler(void *userData, const XML_Char *entityName,
+ int is_parameter_entity) {
+ UNUSED_P(entityName);
+ record_call((struct handler_record_list *)userData, __func__,
+ is_parameter_entity);
+}
+
+void XMLCALL
+record_element_start_handler(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ UNUSED_P(atts);
+ CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
+}
+
+void XMLCALL
+record_element_end_handler(void *userData, const XML_Char *name) {
+ CharData *storage = (CharData *)userData;
+
+ CharData_AppendXMLChars(storage, XCS("/"), 1);
+ CharData_AppendXMLChars(storage, name, -1);
+}
+
+const struct handler_record_entry *
+_handler_record_get(const struct handler_record_list *storage, int index,
+ const char *file, int line) {
+ if (storage->count <= index) {
+ _fail(file, line, "too few handler calls");
+ }
+ return &storage->entries[index];
+}
+
+/* Entity Declaration Handlers */
+static const XML_Char *entity_name_to_match = NULL;
+static const XML_Char *entity_value_to_match = NULL;
+static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
+
+void XMLCALL
+param_entity_match_handler(void *userData, const XML_Char *entityName,
+ int is_parameter_entity, const XML_Char *value,
+ int value_length, const XML_Char *base,
+ const XML_Char *systemId, const XML_Char *publicId,
+ const XML_Char *notationName) {
+ UNUSED_P(userData);
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ UNUSED_P(notationName);
+ if (! is_parameter_entity || entity_name_to_match == NULL
+ || entity_value_to_match == NULL) {
+ return;
+ }
+ if (! xcstrcmp(entityName, entity_name_to_match)) {
+ /* The cast here is safe because we control the horizontal and
+ * the vertical, and we therefore know our strings are never
+ * going to overflow an int.
+ */
+ if (value_length != (int)xcstrlen(entity_value_to_match)
+ || xcstrncmp(value, entity_value_to_match, value_length)) {
+ entity_match_flag = ENTITY_MATCH_FAIL;
+ } else {
+ entity_match_flag = ENTITY_MATCH_SUCCESS;
+ }
+ }
+ /* Else leave the match flag alone */
+}
+
+void
+param_entity_match_init(const XML_Char *name, const XML_Char *value) {
+ entity_name_to_match = name;
+ entity_value_to_match = value;
+ entity_match_flag = ENTITY_MATCH_NOT_FOUND;
+}
+
+int
+get_param_entity_match_flag(void) {
+ return entity_match_flag;
+}
+
+/* Misc handlers */
+
+void XMLCALL
+xml_decl_handler(void *userData, const XML_Char *version,
+ const XML_Char *encoding, int standalone) {
+ UNUSED_P(version);
+ UNUSED_P(encoding);
+ if (userData != g_handler_data)
+ fail("User data (xml decl) not correctly set");
+ if (standalone != -1)
+ fail("Standalone not flagged as not present in XML decl");
+ g_xdecl_count++;
+}
+
+void XMLCALL
+param_check_skip_handler(void *userData, const XML_Char *entityName,
+ int is_parameter_entity) {
+ UNUSED_P(entityName);
+ UNUSED_P(is_parameter_entity);
+ if (userData != g_handler_data)
+ fail("User data (skip) not correctly set");
+ g_skip_count++;
+}
+
+void XMLCALL
+data_check_comment_handler(void *userData, const XML_Char *data) {
+ UNUSED_P(data);
+ /* Check that the userData passed through is what we expect */
+ if (userData != g_handler_data)
+ fail("User data (parser) not correctly set");
+ /* Check that the user data in the parser is appropriate */
+ if (XML_GetUserData(userData) != (void *)1)
+ fail("User data in parser not correctly set");
+ g_comment_count++;
+}
+
+void XMLCALL
+selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
+ const XML_Char trigger_char = *(const XML_Char *)userData;
+
+ int found = 0;
+ for (int i = 0; i < len; ++i) {
+ if (s[i] == trigger_char) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ XML_StopParser(g_parser, g_resumable);
+ XML_SetDefaultHandler(g_parser, NULL);
+ }
+}
+
+void XMLCALL
+suspending_comment_handler(void *userData, const XML_Char *data) {
+ UNUSED_P(data);
+ XML_Parser parser = (XML_Parser)userData;
+ XML_StopParser(parser, XML_TRUE);
+}
+
+void XMLCALL
+element_decl_suspender(void *userData, const XML_Char *name,
+ XML_Content *model) {
+ UNUSED_P(userData);
+ UNUSED_P(name);
+ XML_StopParser(g_parser, XML_TRUE);
+ XML_FreeContentModel(g_parser, model);
+}
+
+void XMLCALL
+accumulate_pi_characters(void *userData, const XML_Char *target,
+ const XML_Char *data) {
+ CharData *storage = (CharData *)userData;
+
+ CharData_AppendXMLChars(storage, target, -1);
+ CharData_AppendXMLChars(storage, XCS(": "), 2);
+ CharData_AppendXMLChars(storage, data, -1);
+ CharData_AppendXMLChars(storage, XCS("\n"), 1);
+}
+
+void XMLCALL
+accumulate_comment(void *userData, const XML_Char *data) {
+ CharData *storage = (CharData *)userData;
+
+ CharData_AppendXMLChars(storage, data, -1);
+}
+
+void XMLCALL
+accumulate_entity_decl(void *userData, const XML_Char *entityName,
+ int is_parameter_entity, const XML_Char *value,
+ int value_length, const XML_Char *base,
+ const XML_Char *systemId, const XML_Char *publicId,
+ const XML_Char *notationName) {
+ CharData *storage = (CharData *)userData;
+
+ UNUSED_P(is_parameter_entity);
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+ UNUSED_P(notationName);
+ CharData_AppendXMLChars(storage, entityName, -1);
+ CharData_AppendXMLChars(storage, XCS("="), 1);
+ if (value == NULL)
+ CharData_AppendXMLChars(storage, XCS("(null)"), -1);
+ else
+ CharData_AppendXMLChars(storage, value, value_length);
+ CharData_AppendXMLChars(storage, XCS("\n"), 1);
+}
+
+void XMLCALL
+accumulate_start_element(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ CharData *const storage = (CharData *)userData;
+ CharData_AppendXMLChars(storage, XCS("("), 1);
+ CharData_AppendXMLChars(storage, name, -1);
+
+ if ((atts != NULL) && (atts[0] != NULL)) {
+ CharData_AppendXMLChars(storage, XCS("("), 1);
+ while (atts[0] != NULL) {
+ CharData_AppendXMLChars(storage, atts[0], -1);
+ CharData_AppendXMLChars(storage, XCS("="), 1);
+ CharData_AppendXMLChars(storage, atts[1], -1);
+ atts += 2;
+ if (atts[0] != NULL) {
+ CharData_AppendXMLChars(storage, XCS(","), 1);
+ }
+ }
+ CharData_AppendXMLChars(storage, XCS(")"), 1);
+ }
+
+ CharData_AppendXMLChars(storage, XCS(")\n"), 2);
+}
+
+void XMLCALL
+accumulate_characters(void *userData, const XML_Char *s, int len) {
+ CharData *const storage = (CharData *)userData;
+ CharData_AppendXMLChars(storage, s, len);
+}
+
+void XMLCALL
+accumulate_attribute(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ CharData *const storage = (CharData *)userData;
+ UNUSED_P(name);
+ /* Check there are attributes to deal with */
+ if (atts == NULL)
+ return;
+
+ while (storage->count < 0 && atts[0] != NULL) {
+ /* "accumulate" the value of the first attribute we see */
+ CharData_AppendXMLChars(storage, atts[1], -1);
+ atts += 2;
+ }
+}
+
+void XMLCALL
+ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
+ ExtTest *const test_data = (ExtTest *)userData;
+ accumulate_characters(test_data->storage, s, len);
+}
+
+void XMLCALL
+checking_default_handler(void *userData, const XML_Char *s, int len) {
+ DefaultCheck *data = (DefaultCheck *)userData;
+ int i;
+
+ for (i = 0; data[i].expected != NULL; i++) {
+ if (data[i].expectedLen == len
+ && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
+ data[i].seen = XML_TRUE;
+ break;
+ }
+ }
+}
+
+void XMLCALL
+accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) {
+ ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
+ accumulate_comment(parserPlusStorage->storage, data);
+ XML_StopParser(parserPlusStorage->parser, XML_TRUE);
+}