1#include "Python.h" 2#include <ctype.h> 3 4#include "structmember.h" // PyMemberDef 5#include "expat.h" 6 7#include "pyexpat.h" 8 9/* Do not emit Clinic output to a file as that wreaks havoc with conditionally 10 included methods. */ 11/*[clinic input] 12module pyexpat 13[clinic start generated code]*/ 14/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b168d503a4490c15]*/ 15 16#define XML_COMBINED_VERSION (10000*XML_MAJOR_VERSION+100*XML_MINOR_VERSION+XML_MICRO_VERSION) 17 18static XML_Memory_Handling_Suite ExpatMemoryHandler = { 19 PyObject_Malloc, PyObject_Realloc, PyObject_Free}; 20 21enum HandlerTypes { 22 StartElement, 23 EndElement, 24 ProcessingInstruction, 25 CharacterData, 26 UnparsedEntityDecl, 27 NotationDecl, 28 StartNamespaceDecl, 29 EndNamespaceDecl, 30 Comment, 31 StartCdataSection, 32 EndCdataSection, 33 Default, 34 DefaultHandlerExpand, 35 NotStandalone, 36 ExternalEntityRef, 37 StartDoctypeDecl, 38 EndDoctypeDecl, 39 EntityDecl, 40 XmlDecl, 41 ElementDecl, 42 AttlistDecl, 43#if XML_COMBINED_VERSION >= 19504 44 SkippedEntity, 45#endif 46 _DummyDecl 47}; 48 49typedef struct { 50 PyTypeObject *xml_parse_type; 51 PyObject *error; 52 PyObject *str_read; 53} pyexpat_state; 54 55static inline pyexpat_state* 56pyexpat_get_state(PyObject *module) 57{ 58 void *state = PyModule_GetState(module); 59 assert(state != NULL); 60 return (pyexpat_state *)state; 61} 62 63/* ----------------------------------------------------- */ 64 65/* Declarations for objects of type xmlparser */ 66 67typedef struct { 68 PyObject_HEAD 69 70 XML_Parser itself; 71 int ordered_attributes; /* Return attributes as a list. */ 72 int specified_attributes; /* Report only specified attributes. */ 73 int in_callback; /* Is a callback active? */ 74 int ns_prefixes; /* Namespace-triplets mode? */ 75 XML_Char *buffer; /* Buffer used when accumulating characters */ 76 /* NULL if not enabled */ 77 int buffer_size; /* Size of buffer, in XML_Char units */ 78 int buffer_used; /* Buffer units in use */ 79 PyObject *intern; /* Dictionary to intern strings */ 80 PyObject **handlers; 81} xmlparseobject; 82 83#include "clinic/pyexpat.c.h" 84 85#define CHARACTER_DATA_BUFFER_SIZE 8192 86 87typedef void (*xmlhandlersetter)(XML_Parser self, void *meth); 88typedef void* xmlhandler; 89 90struct HandlerInfo { 91 const char *name; 92 xmlhandlersetter setter; 93 xmlhandler handler; 94 PyGetSetDef getset; 95}; 96 97static struct HandlerInfo handler_info[64]; 98 99/* Set an integer attribute on the error object; return true on success, 100 * false on an exception. 101 */ 102static int 103set_error_attr(PyObject *err, const char *name, int value) 104{ 105 PyObject *v = PyLong_FromLong(value); 106 107 if (v == NULL || PyObject_SetAttrString(err, name, v) == -1) { 108 Py_XDECREF(v); 109 return 0; 110 } 111 Py_DECREF(v); 112 return 1; 113} 114 115/* Build and set an Expat exception, including positioning 116 * information. Always returns NULL. 117 */ 118static PyObject * 119set_error(pyexpat_state *state, xmlparseobject *self, enum XML_Error code) 120{ 121 PyObject *err; 122 PyObject *buffer; 123 XML_Parser parser = self->itself; 124 int lineno = XML_GetErrorLineNumber(parser); 125 int column = XML_GetErrorColumnNumber(parser); 126 127 buffer = PyUnicode_FromFormat("%s: line %i, column %i", 128 XML_ErrorString(code), lineno, column); 129 if (buffer == NULL) 130 return NULL; 131 err = PyObject_CallOneArg(state->error, buffer); 132 Py_DECREF(buffer); 133 if ( err != NULL 134 && set_error_attr(err, "code", code) 135 && set_error_attr(err, "offset", column) 136 && set_error_attr(err, "lineno", lineno)) { 137 PyErr_SetObject(state->error, err); 138 } 139 Py_XDECREF(err); 140 return NULL; 141} 142 143static int 144have_handler(xmlparseobject *self, int type) 145{ 146 PyObject *handler = self->handlers[type]; 147 return handler != NULL; 148} 149 150/* Convert a string of XML_Chars into a Unicode string. 151 Returns None if str is a null pointer. */ 152 153static PyObject * 154conv_string_to_unicode(const XML_Char *str) 155{ 156 /* XXX currently this code assumes that XML_Char is 8-bit, 157 and hence in UTF-8. */ 158 /* UTF-8 from Expat, Unicode desired */ 159 if (str == NULL) { 160 Py_RETURN_NONE; 161 } 162 return PyUnicode_DecodeUTF8(str, strlen(str), "strict"); 163} 164 165static PyObject * 166conv_string_len_to_unicode(const XML_Char *str, int len) 167{ 168 /* XXX currently this code assumes that XML_Char is 8-bit, 169 and hence in UTF-8. */ 170 /* UTF-8 from Expat, Unicode desired */ 171 if (str == NULL) { 172 Py_RETURN_NONE; 173 } 174 return PyUnicode_DecodeUTF8((const char *)str, len, "strict"); 175} 176 177/* Callback routines */ 178 179static void clear_handlers(xmlparseobject *self, int initial); 180 181/* This handler is used when an error has been detected, in the hope 182 that actual parsing can be terminated early. This will only help 183 if an external entity reference is encountered. */ 184static int 185error_external_entity_ref_handler(XML_Parser parser, 186 const XML_Char *context, 187 const XML_Char *base, 188 const XML_Char *systemId, 189 const XML_Char *publicId) 190{ 191 return 0; 192} 193 194/* Dummy character data handler used when an error (exception) has 195 been detected, and the actual parsing can be terminated early. 196 This is needed since character data handler can't be safely removed 197 from within the character data handler, but can be replaced. It is 198 used only from the character data handler trampoline, and must be 199 used right after `flag_error()` is called. */ 200static void 201noop_character_data_handler(void *userData, const XML_Char *data, int len) 202{ 203 /* Do nothing. */ 204} 205 206static void 207flag_error(xmlparseobject *self) 208{ 209 clear_handlers(self, 0); 210 XML_SetExternalEntityRefHandler(self->itself, 211 error_external_entity_ref_handler); 212} 213 214static PyObject* 215call_with_frame(const char *funcname, int lineno, PyObject* func, PyObject* args, 216 xmlparseobject *self) 217{ 218 PyObject *res; 219 220 res = PyObject_Call(func, args, NULL); 221 if (res == NULL) { 222 _PyTraceback_Add(funcname, __FILE__, lineno); 223 XML_StopParser(self->itself, XML_FALSE); 224 } 225 return res; 226} 227 228static PyObject* 229string_intern(xmlparseobject *self, const char* str) 230{ 231 PyObject *result = conv_string_to_unicode(str); 232 PyObject *value; 233 /* result can be NULL if the unicode conversion failed. */ 234 if (!result) 235 return result; 236 if (!self->intern) 237 return result; 238 value = PyDict_GetItemWithError(self->intern, result); 239 if (!value) { 240 if (!PyErr_Occurred() && 241 PyDict_SetItem(self->intern, result, result) == 0) 242 { 243 return result; 244 } 245 else { 246 Py_DECREF(result); 247 return NULL; 248 } 249 } 250 Py_INCREF(value); 251 Py_DECREF(result); 252 return value; 253} 254 255/* Return 0 on success, -1 on exception. 256 * flag_error() will be called before return if needed. 257 */ 258static int 259call_character_handler(xmlparseobject *self, const XML_Char *buffer, int len) 260{ 261 PyObject *args; 262 PyObject *temp; 263 264 if (!have_handler(self, CharacterData)) 265 return -1; 266 267 args = PyTuple_New(1); 268 if (args == NULL) 269 return -1; 270 temp = (conv_string_len_to_unicode(buffer, len)); 271 if (temp == NULL) { 272 Py_DECREF(args); 273 flag_error(self); 274 XML_SetCharacterDataHandler(self->itself, 275 noop_character_data_handler); 276 return -1; 277 } 278 PyTuple_SET_ITEM(args, 0, temp); 279 /* temp is now a borrowed reference; consider it unused. */ 280 self->in_callback = 1; 281 temp = call_with_frame("CharacterData", __LINE__, 282 self->handlers[CharacterData], args, self); 283 /* temp is an owned reference again, or NULL */ 284 self->in_callback = 0; 285 Py_DECREF(args); 286 if (temp == NULL) { 287 flag_error(self); 288 XML_SetCharacterDataHandler(self->itself, 289 noop_character_data_handler); 290 return -1; 291 } 292 Py_DECREF(temp); 293 return 0; 294} 295 296static int 297flush_character_buffer(xmlparseobject *self) 298{ 299 int rc; 300 if (self->buffer == NULL || self->buffer_used == 0) 301 return 0; 302 rc = call_character_handler(self, self->buffer, self->buffer_used); 303 self->buffer_used = 0; 304 return rc; 305} 306 307static void 308my_CharacterDataHandler(void *userData, const XML_Char *data, int len) 309{ 310 xmlparseobject *self = (xmlparseobject *) userData; 311 312 if (PyErr_Occurred()) 313 return; 314 315 if (self->buffer == NULL) 316 call_character_handler(self, data, len); 317 else { 318 if ((self->buffer_used + len) > self->buffer_size) { 319 if (flush_character_buffer(self) < 0) 320 return; 321 /* handler might have changed; drop the rest on the floor 322 * if there isn't a handler anymore 323 */ 324 if (!have_handler(self, CharacterData)) 325 return; 326 } 327 if (len > self->buffer_size) { 328 call_character_handler(self, data, len); 329 self->buffer_used = 0; 330 } 331 else { 332 memcpy(self->buffer + self->buffer_used, 333 data, len * sizeof(XML_Char)); 334 self->buffer_used += len; 335 } 336 } 337} 338 339static void 340my_StartElementHandler(void *userData, 341 const XML_Char *name, const XML_Char *atts[]) 342{ 343 xmlparseobject *self = (xmlparseobject *)userData; 344 345 if (have_handler(self, StartElement)) { 346 PyObject *container, *rv, *args; 347 int i, max; 348 349 if (PyErr_Occurred()) 350 return; 351 352 if (flush_character_buffer(self) < 0) 353 return; 354 /* Set max to the number of slots filled in atts[]; max/2 is 355 * the number of attributes we need to process. 356 */ 357 if (self->specified_attributes) { 358 max = XML_GetSpecifiedAttributeCount(self->itself); 359 } 360 else { 361 max = 0; 362 while (atts[max] != NULL) 363 max += 2; 364 } 365 /* Build the container. */ 366 if (self->ordered_attributes) 367 container = PyList_New(max); 368 else 369 container = PyDict_New(); 370 if (container == NULL) { 371 flag_error(self); 372 return; 373 } 374 for (i = 0; i < max; i += 2) { 375 PyObject *n = string_intern(self, (XML_Char *) atts[i]); 376 PyObject *v; 377 if (n == NULL) { 378 flag_error(self); 379 Py_DECREF(container); 380 return; 381 } 382 v = conv_string_to_unicode((XML_Char *) atts[i+1]); 383 if (v == NULL) { 384 flag_error(self); 385 Py_DECREF(container); 386 Py_DECREF(n); 387 return; 388 } 389 if (self->ordered_attributes) { 390 PyList_SET_ITEM(container, i, n); 391 PyList_SET_ITEM(container, i+1, v); 392 } 393 else if (PyDict_SetItem(container, n, v)) { 394 flag_error(self); 395 Py_DECREF(n); 396 Py_DECREF(v); 397 Py_DECREF(container); 398 return; 399 } 400 else { 401 Py_DECREF(n); 402 Py_DECREF(v); 403 } 404 } 405 args = string_intern(self, name); 406 if (args == NULL) { 407 Py_DECREF(container); 408 return; 409 } 410 args = Py_BuildValue("(NN)", args, container); 411 if (args == NULL) { 412 return; 413 } 414 /* Container is now a borrowed reference; ignore it. */ 415 self->in_callback = 1; 416 rv = call_with_frame("StartElement", __LINE__, 417 self->handlers[StartElement], args, self); 418 self->in_callback = 0; 419 Py_DECREF(args); 420 if (rv == NULL) { 421 flag_error(self); 422 return; 423 } 424 Py_DECREF(rv); 425 } 426} 427 428#define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \ 429 RETURN, GETUSERDATA) \ 430static RC \ 431my_##NAME##Handler PARAMS {\ 432 xmlparseobject *self = GETUSERDATA ; \ 433 PyObject *args = NULL; \ 434 PyObject *rv = NULL; \ 435 INIT \ 436\ 437 if (have_handler(self, NAME)) { \ 438 if (PyErr_Occurred()) \ 439 return RETURN; \ 440 if (flush_character_buffer(self) < 0) \ 441 return RETURN; \ 442 args = Py_BuildValue PARAM_FORMAT ;\ 443 if (!args) { flag_error(self); return RETURN;} \ 444 self->in_callback = 1; \ 445 rv = call_with_frame(#NAME,__LINE__, \ 446 self->handlers[NAME], args, self); \ 447 self->in_callback = 0; \ 448 Py_DECREF(args); \ 449 if (rv == NULL) { \ 450 flag_error(self); \ 451 return RETURN; \ 452 } \ 453 CONVERSION \ 454 Py_DECREF(rv); \ 455 } \ 456 return RETURN; \ 457} 458 459#define VOID_HANDLER(NAME, PARAMS, PARAM_FORMAT) \ 460 RC_HANDLER(void, NAME, PARAMS, ;, PARAM_FORMAT, ;, ;,\ 461 (xmlparseobject *)userData) 462 463#define INT_HANDLER(NAME, PARAMS, PARAM_FORMAT)\ 464 RC_HANDLER(int, NAME, PARAMS, int rc=0;, PARAM_FORMAT, \ 465 rc = PyLong_AsLong(rv);, rc, \ 466 (xmlparseobject *)userData) 467 468VOID_HANDLER(EndElement, 469 (void *userData, const XML_Char *name), 470 ("(N)", string_intern(self, name))) 471 472VOID_HANDLER(ProcessingInstruction, 473 (void *userData, 474 const XML_Char *target, 475 const XML_Char *data), 476 ("(NO&)", string_intern(self, target), conv_string_to_unicode ,data)) 477 478VOID_HANDLER(UnparsedEntityDecl, 479 (void *userData, 480 const XML_Char *entityName, 481 const XML_Char *base, 482 const XML_Char *systemId, 483 const XML_Char *publicId, 484 const XML_Char *notationName), 485 ("(NNNNN)", 486 string_intern(self, entityName), string_intern(self, base), 487 string_intern(self, systemId), string_intern(self, publicId), 488 string_intern(self, notationName))) 489 490VOID_HANDLER(EntityDecl, 491 (void *userData, 492 const XML_Char *entityName, 493 int is_parameter_entity, 494 const XML_Char *value, 495 int value_length, 496 const XML_Char *base, 497 const XML_Char *systemId, 498 const XML_Char *publicId, 499 const XML_Char *notationName), 500 ("NiNNNNN", 501 string_intern(self, entityName), is_parameter_entity, 502 (conv_string_len_to_unicode(value, value_length)), 503 string_intern(self, base), string_intern(self, systemId), 504 string_intern(self, publicId), 505 string_intern(self, notationName))) 506 507VOID_HANDLER(XmlDecl, 508 (void *userData, 509 const XML_Char *version, 510 const XML_Char *encoding, 511 int standalone), 512 ("(O&O&i)", 513 conv_string_to_unicode ,version, conv_string_to_unicode ,encoding, 514 standalone)) 515 516static PyObject * 517conv_content_model(XML_Content * const model, 518 PyObject *(*conv_string)(const XML_Char *)) 519{ 520 PyObject *result = NULL; 521 PyObject *children = PyTuple_New(model->numchildren); 522 int i; 523 524 if (children != NULL) { 525 assert(model->numchildren < INT_MAX); 526 for (i = 0; i < (int)model->numchildren; ++i) { 527 PyObject *child = conv_content_model(&model->children[i], 528 conv_string); 529 if (child == NULL) { 530 Py_XDECREF(children); 531 return NULL; 532 } 533 PyTuple_SET_ITEM(children, i, child); 534 } 535 result = Py_BuildValue("(iiO&N)", 536 model->type, model->quant, 537 conv_string,model->name, children); 538 } 539 return result; 540} 541 542static void 543my_ElementDeclHandler(void *userData, 544 const XML_Char *name, 545 XML_Content *model) 546{ 547 xmlparseobject *self = (xmlparseobject *)userData; 548 PyObject *args = NULL; 549 550 if (have_handler(self, ElementDecl)) { 551 PyObject *rv = NULL; 552 PyObject *modelobj, *nameobj; 553 554 if (PyErr_Occurred()) 555 return; 556 557 if (flush_character_buffer(self) < 0) 558 goto finally; 559 modelobj = conv_content_model(model, (conv_string_to_unicode)); 560 if (modelobj == NULL) { 561 flag_error(self); 562 goto finally; 563 } 564 nameobj = string_intern(self, name); 565 if (nameobj == NULL) { 566 Py_DECREF(modelobj); 567 flag_error(self); 568 goto finally; 569 } 570 args = Py_BuildValue("NN", nameobj, modelobj); 571 if (args == NULL) { 572 flag_error(self); 573 goto finally; 574 } 575 self->in_callback = 1; 576 rv = call_with_frame("ElementDecl", __LINE__, 577 self->handlers[ElementDecl], args, self); 578 self->in_callback = 0; 579 if (rv == NULL) { 580 flag_error(self); 581 goto finally; 582 } 583 Py_DECREF(rv); 584 } 585 finally: 586 Py_XDECREF(args); 587 XML_FreeContentModel(self->itself, model); 588 return; 589} 590 591VOID_HANDLER(AttlistDecl, 592 (void *userData, 593 const XML_Char *elname, 594 const XML_Char *attname, 595 const XML_Char *att_type, 596 const XML_Char *dflt, 597 int isrequired), 598 ("(NNO&O&i)", 599 string_intern(self, elname), string_intern(self, attname), 600 conv_string_to_unicode ,att_type, conv_string_to_unicode ,dflt, 601 isrequired)) 602 603#if XML_COMBINED_VERSION >= 19504 604VOID_HANDLER(SkippedEntity, 605 (void *userData, 606 const XML_Char *entityName, 607 int is_parameter_entity), 608 ("Ni", 609 string_intern(self, entityName), is_parameter_entity)) 610#endif 611 612VOID_HANDLER(NotationDecl, 613 (void *userData, 614 const XML_Char *notationName, 615 const XML_Char *base, 616 const XML_Char *systemId, 617 const XML_Char *publicId), 618 ("(NNNN)", 619 string_intern(self, notationName), string_intern(self, base), 620 string_intern(self, systemId), string_intern(self, publicId))) 621 622VOID_HANDLER(StartNamespaceDecl, 623 (void *userData, 624 const XML_Char *prefix, 625 const XML_Char *uri), 626 ("(NN)", 627 string_intern(self, prefix), string_intern(self, uri))) 628 629VOID_HANDLER(EndNamespaceDecl, 630 (void *userData, 631 const XML_Char *prefix), 632 ("(N)", string_intern(self, prefix))) 633 634VOID_HANDLER(Comment, 635 (void *userData, const XML_Char *data), 636 ("(O&)", conv_string_to_unicode ,data)) 637 638VOID_HANDLER(StartCdataSection, 639 (void *userData), 640 ("()")) 641 642VOID_HANDLER(EndCdataSection, 643 (void *userData), 644 ("()")) 645 646VOID_HANDLER(Default, 647 (void *userData, const XML_Char *s, int len), 648 ("(N)", (conv_string_len_to_unicode(s,len)))) 649 650VOID_HANDLER(DefaultHandlerExpand, 651 (void *userData, const XML_Char *s, int len), 652 ("(N)", (conv_string_len_to_unicode(s,len)))) 653#define my_DefaultHandlerExpand my_DefaultHandlerExpandHandler 654 655INT_HANDLER(NotStandalone, 656 (void *userData), 657 ("()")) 658 659RC_HANDLER(int, ExternalEntityRef, 660 (XML_Parser parser, 661 const XML_Char *context, 662 const XML_Char *base, 663 const XML_Char *systemId, 664 const XML_Char *publicId), 665 int rc=0;, 666 ("(O&NNN)", 667 conv_string_to_unicode ,context, string_intern(self, base), 668 string_intern(self, systemId), string_intern(self, publicId)), 669 rc = PyLong_AsLong(rv);, rc, 670 XML_GetUserData(parser)) 671 672/* XXX UnknownEncodingHandler */ 673 674VOID_HANDLER(StartDoctypeDecl, 675 (void *userData, const XML_Char *doctypeName, 676 const XML_Char *sysid, const XML_Char *pubid, 677 int has_internal_subset), 678 ("(NNNi)", string_intern(self, doctypeName), 679 string_intern(self, sysid), string_intern(self, pubid), 680 has_internal_subset)) 681 682VOID_HANDLER(EndDoctypeDecl, (void *userData), ("()")) 683 684/* ---------------------------------------------------------------- */ 685/*[clinic input] 686class pyexpat.xmlparser "xmlparseobject *" "&Xmlparsetype" 687[clinic start generated code]*/ 688/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2393162385232e1c]*/ 689 690 691static PyObject * 692get_parse_result(pyexpat_state *state, xmlparseobject *self, int rv) 693{ 694 if (PyErr_Occurred()) { 695 return NULL; 696 } 697 if (rv == 0) { 698 return set_error(state, self, XML_GetErrorCode(self->itself)); 699 } 700 if (flush_character_buffer(self) < 0) { 701 return NULL; 702 } 703 return PyLong_FromLong(rv); 704} 705 706#define MAX_CHUNK_SIZE (1 << 20) 707 708/*[clinic input] 709pyexpat.xmlparser.Parse 710 711 cls: defining_class 712 data: object 713 isfinal: bool(accept={int}) = False 714 / 715 716Parse XML data. 717 718`isfinal' should be true at end of input. 719[clinic start generated code]*/ 720 721static PyObject * 722pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyTypeObject *cls, 723 PyObject *data, int isfinal) 724/*[clinic end generated code: output=8faffe07fe1f862a input=fc97f833558ca715]*/ 725{ 726 const char *s; 727 Py_ssize_t slen; 728 Py_buffer view; 729 int rc; 730 pyexpat_state *state = PyType_GetModuleState(cls); 731 732 if (PyUnicode_Check(data)) { 733 view.buf = NULL; 734 s = PyUnicode_AsUTF8AndSize(data, &slen); 735 if (s == NULL) 736 return NULL; 737 /* Explicitly set UTF-8 encoding. Return code ignored. */ 738 (void)XML_SetEncoding(self->itself, "utf-8"); 739 } 740 else { 741 if (PyObject_GetBuffer(data, &view, PyBUF_SIMPLE) < 0) 742 return NULL; 743 s = view.buf; 744 slen = view.len; 745 } 746 747 static_assert(MAX_CHUNK_SIZE <= INT_MAX, 748 "MAX_CHUNK_SIZE is larger than INT_MAX"); 749 while (slen > MAX_CHUNK_SIZE) { 750 rc = XML_Parse(self->itself, s, MAX_CHUNK_SIZE, 0); 751 if (!rc) 752 goto done; 753 s += MAX_CHUNK_SIZE; 754 slen -= MAX_CHUNK_SIZE; 755 } 756 757 assert(slen <= INT_MAX); 758 rc = XML_Parse(self->itself, s, (int)slen, isfinal); 759 760done: 761 if (view.buf != NULL) { 762 PyBuffer_Release(&view); 763 } 764 return get_parse_result(state, self, rc); 765} 766 767/* File reading copied from cPickle */ 768 769#define BUF_SIZE 2048 770 771static int 772readinst(char *buf, int buf_size, PyObject *meth) 773{ 774 PyObject *str; 775 Py_ssize_t len; 776 const char *ptr; 777 778 str = PyObject_CallFunction(meth, "i", buf_size); 779 if (str == NULL) 780 goto error; 781 782 if (PyBytes_Check(str)) 783 ptr = PyBytes_AS_STRING(str); 784 else if (PyByteArray_Check(str)) 785 ptr = PyByteArray_AS_STRING(str); 786 else { 787 PyErr_Format(PyExc_TypeError, 788 "read() did not return a bytes object (type=%.400s)", 789 Py_TYPE(str)->tp_name); 790 goto error; 791 } 792 len = Py_SIZE(str); 793 if (len > buf_size) { 794 PyErr_Format(PyExc_ValueError, 795 "read() returned too much data: " 796 "%i bytes requested, %zd returned", 797 buf_size, len); 798 goto error; 799 } 800 memcpy(buf, ptr, len); 801 Py_DECREF(str); 802 /* len <= buf_size <= INT_MAX */ 803 return (int)len; 804 805error: 806 Py_XDECREF(str); 807 return -1; 808} 809 810/*[clinic input] 811pyexpat.xmlparser.ParseFile 812 813 cls: defining_class 814 file: object 815 / 816 817Parse XML data from file-like object. 818[clinic start generated code]*/ 819 820static PyObject * 821pyexpat_xmlparser_ParseFile_impl(xmlparseobject *self, PyTypeObject *cls, 822 PyObject *file) 823/*[clinic end generated code: output=34780a094c8ca3ae input=ba4bc9c541684793]*/ 824{ 825 int rv = 1; 826 PyObject *readmethod = NULL; 827 828 pyexpat_state *state = PyType_GetModuleState(cls); 829 830 if (_PyObject_LookupAttr(file, state->str_read, &readmethod) < 0) { 831 return NULL; 832 } 833 if (readmethod == NULL) { 834 PyErr_SetString(PyExc_TypeError, 835 "argument must have 'read' attribute"); 836 return NULL; 837 } 838 for (;;) { 839 int bytes_read; 840 void *buf = XML_GetBuffer(self->itself, BUF_SIZE); 841 if (buf == NULL) { 842 Py_XDECREF(readmethod); 843 return get_parse_result(state, self, 0); 844 } 845 846 bytes_read = readinst(buf, BUF_SIZE, readmethod); 847 if (bytes_read < 0) { 848 Py_DECREF(readmethod); 849 return NULL; 850 } 851 rv = XML_ParseBuffer(self->itself, bytes_read, bytes_read == 0); 852 if (PyErr_Occurred()) { 853 Py_XDECREF(readmethod); 854 return NULL; 855 } 856 857 if (!rv || bytes_read == 0) 858 break; 859 } 860 Py_XDECREF(readmethod); 861 return get_parse_result(state, self, rv); 862} 863 864/*[clinic input] 865pyexpat.xmlparser.SetBase 866 867 base: str 868 / 869 870Set the base URL for the parser. 871[clinic start generated code]*/ 872 873static PyObject * 874pyexpat_xmlparser_SetBase_impl(xmlparseobject *self, const char *base) 875/*[clinic end generated code: output=c212ddceb607b539 input=c684e5de895ee1a8]*/ 876{ 877 if (!XML_SetBase(self->itself, base)) { 878 return PyErr_NoMemory(); 879 } 880 Py_RETURN_NONE; 881} 882 883/*[clinic input] 884pyexpat.xmlparser.GetBase 885 886Return base URL string for the parser. 887[clinic start generated code]*/ 888 889static PyObject * 890pyexpat_xmlparser_GetBase_impl(xmlparseobject *self) 891/*[clinic end generated code: output=2886cb21f9a8739a input=918d71c38009620e]*/ 892{ 893 return Py_BuildValue("z", XML_GetBase(self->itself)); 894} 895 896/*[clinic input] 897pyexpat.xmlparser.GetInputContext 898 899Return the untranslated text of the input that caused the current event. 900 901If the event was generated by a large amount of text (such as a start tag 902for an element with many attributes), not all of the text may be available. 903[clinic start generated code]*/ 904 905static PyObject * 906pyexpat_xmlparser_GetInputContext_impl(xmlparseobject *self) 907/*[clinic end generated code: output=a88026d683fc22cc input=034df8712db68379]*/ 908{ 909 if (self->in_callback) { 910 int offset, size; 911 const char *buffer 912 = XML_GetInputContext(self->itself, &offset, &size); 913 914 if (buffer != NULL) 915 return PyBytes_FromStringAndSize(buffer + offset, 916 size - offset); 917 else 918 Py_RETURN_NONE; 919 } 920 else 921 Py_RETURN_NONE; 922} 923 924/*[clinic input] 925pyexpat.xmlparser.ExternalEntityParserCreate 926 927 cls: defining_class 928 context: str(accept={str, NoneType}) 929 encoding: str = NULL 930 / 931 932Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler. 933[clinic start generated code]*/ 934 935static PyObject * 936pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, 937 PyTypeObject *cls, 938 const char *context, 939 const char *encoding) 940/*[clinic end generated code: output=01d4472b49cb3f92 input=ec70c6b9e6e9619a]*/ 941{ 942 xmlparseobject *new_parser; 943 int i; 944 945 pyexpat_state *state = PyType_GetModuleState(cls); 946 947 new_parser = PyObject_GC_New(xmlparseobject, state->xml_parse_type); 948 if (new_parser == NULL) { 949 return NULL; 950 } 951 952 new_parser->buffer_size = self->buffer_size; 953 new_parser->buffer_used = 0; 954 new_parser->buffer = NULL; 955 new_parser->ordered_attributes = self->ordered_attributes; 956 new_parser->specified_attributes = self->specified_attributes; 957 new_parser->in_callback = 0; 958 new_parser->ns_prefixes = self->ns_prefixes; 959 new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context, 960 encoding); 961 new_parser->handlers = 0; 962 new_parser->intern = self->intern; 963 Py_XINCREF(new_parser->intern); 964 965 if (self->buffer != NULL) { 966 new_parser->buffer = PyMem_Malloc(new_parser->buffer_size); 967 if (new_parser->buffer == NULL) { 968 Py_DECREF(new_parser); 969 return PyErr_NoMemory(); 970 } 971 } 972 if (!new_parser->itself) { 973 Py_DECREF(new_parser); 974 return PyErr_NoMemory(); 975 } 976 977 XML_SetUserData(new_parser->itself, (void *)new_parser); 978 979 /* allocate and clear handlers first */ 980 for (i = 0; handler_info[i].name != NULL; i++) 981 /* do nothing */; 982 983 new_parser->handlers = PyMem_New(PyObject *, i); 984 if (!new_parser->handlers) { 985 Py_DECREF(new_parser); 986 return PyErr_NoMemory(); 987 } 988 clear_handlers(new_parser, 1); 989 990 /* then copy handlers from self */ 991 for (i = 0; handler_info[i].name != NULL; i++) { 992 PyObject *handler = self->handlers[i]; 993 if (handler != NULL) { 994 Py_INCREF(handler); 995 new_parser->handlers[i] = handler; 996 handler_info[i].setter(new_parser->itself, 997 handler_info[i].handler); 998 } 999 } 1000 1001 PyObject_GC_Track(new_parser); 1002 return (PyObject *)new_parser; 1003} 1004 1005/*[clinic input] 1006pyexpat.xmlparser.SetParamEntityParsing 1007 1008 flag: int 1009 / 1010 1011Controls parsing of parameter entities (including the external DTD subset). 1012 1013Possible flag values are XML_PARAM_ENTITY_PARSING_NEVER, 1014XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE and 1015XML_PARAM_ENTITY_PARSING_ALWAYS. Returns true if setting the flag 1016was successful. 1017[clinic start generated code]*/ 1018 1019static PyObject * 1020pyexpat_xmlparser_SetParamEntityParsing_impl(xmlparseobject *self, int flag) 1021/*[clinic end generated code: output=18668ee8e760d64c input=8aea19b4b15e9af1]*/ 1022{ 1023 flag = XML_SetParamEntityParsing(self->itself, flag); 1024 return PyLong_FromLong(flag); 1025} 1026 1027 1028#if XML_COMBINED_VERSION >= 19505 1029/*[clinic input] 1030pyexpat.xmlparser.UseForeignDTD 1031 1032 cls: defining_class 1033 flag: bool = True 1034 / 1035 1036Allows the application to provide an artificial external subset if one is not specified as part of the document instance. 1037 1038This readily allows the use of a 'default' document type controlled by the 1039application, while still getting the advantage of providing document type 1040information to the parser. 'flag' defaults to True if not provided. 1041[clinic start generated code]*/ 1042 1043static PyObject * 1044pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, PyTypeObject *cls, 1045 int flag) 1046/*[clinic end generated code: output=d7d98252bd25a20f input=23440ecb0573fb29]*/ 1047{ 1048 pyexpat_state *state = PyType_GetModuleState(cls); 1049 enum XML_Error rc; 1050 1051 rc = XML_UseForeignDTD(self->itself, flag ? XML_TRUE : XML_FALSE); 1052 if (rc != XML_ERROR_NONE) { 1053 return set_error(state, self, rc); 1054 } 1055 Py_RETURN_NONE; 1056} 1057#endif 1058 1059static struct PyMethodDef xmlparse_methods[] = { 1060 PYEXPAT_XMLPARSER_PARSE_METHODDEF 1061 PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF 1062 PYEXPAT_XMLPARSER_SETBASE_METHODDEF 1063 PYEXPAT_XMLPARSER_GETBASE_METHODDEF 1064 PYEXPAT_XMLPARSER_GETINPUTCONTEXT_METHODDEF 1065 PYEXPAT_XMLPARSER_EXTERNALENTITYPARSERCREATE_METHODDEF 1066 PYEXPAT_XMLPARSER_SETPARAMENTITYPARSING_METHODDEF 1067#if XML_COMBINED_VERSION >= 19505 1068 PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF 1069#endif 1070 {NULL, NULL} /* sentinel */ 1071}; 1072 1073/* ---------- */ 1074 1075 1076 1077/* pyexpat international encoding support. 1078 Make it as simple as possible. 1079*/ 1080 1081static int 1082PyUnknownEncodingHandler(void *encodingHandlerData, 1083 const XML_Char *name, 1084 XML_Encoding *info) 1085{ 1086 static unsigned char template_buffer[256] = {0}; 1087 PyObject* u; 1088 int i; 1089 const void *data; 1090 unsigned int kind; 1091 1092 if (PyErr_Occurred()) 1093 return XML_STATUS_ERROR; 1094 1095 if (template_buffer[1] == 0) { 1096 for (i = 0; i < 256; i++) 1097 template_buffer[i] = i; 1098 } 1099 1100 u = PyUnicode_Decode((char*) template_buffer, 256, name, "replace"); 1101 if (u == NULL || PyUnicode_READY(u)) { 1102 Py_XDECREF(u); 1103 return XML_STATUS_ERROR; 1104 } 1105 1106 if (PyUnicode_GET_LENGTH(u) != 256) { 1107 Py_DECREF(u); 1108 PyErr_SetString(PyExc_ValueError, 1109 "multi-byte encodings are not supported"); 1110 return XML_STATUS_ERROR; 1111 } 1112 1113 kind = PyUnicode_KIND(u); 1114 data = PyUnicode_DATA(u); 1115 for (i = 0; i < 256; i++) { 1116 Py_UCS4 ch = PyUnicode_READ(kind, data, i); 1117 if (ch != Py_UNICODE_REPLACEMENT_CHARACTER) 1118 info->map[i] = ch; 1119 else 1120 info->map[i] = -1; 1121 } 1122 1123 info->data = NULL; 1124 info->convert = NULL; 1125 info->release = NULL; 1126 Py_DECREF(u); 1127 1128 return XML_STATUS_OK; 1129} 1130 1131 1132static PyObject * 1133newxmlparseobject(pyexpat_state *state, const char *encoding, 1134 const char *namespace_separator, PyObject *intern) 1135{ 1136 int i; 1137 xmlparseobject *self; 1138 1139 self = PyObject_GC_New(xmlparseobject, state->xml_parse_type); 1140 if (self == NULL) 1141 return NULL; 1142 1143 self->buffer = NULL; 1144 self->buffer_size = CHARACTER_DATA_BUFFER_SIZE; 1145 self->buffer_used = 0; 1146 self->ordered_attributes = 0; 1147 self->specified_attributes = 0; 1148 self->in_callback = 0; 1149 self->ns_prefixes = 0; 1150 self->handlers = NULL; 1151 self->intern = intern; 1152 Py_XINCREF(self->intern); 1153 1154 /* namespace_separator is either NULL or contains one char + \0 */ 1155 self->itself = XML_ParserCreate_MM(encoding, &ExpatMemoryHandler, 1156 namespace_separator); 1157 if (self->itself == NULL) { 1158 PyErr_SetString(PyExc_RuntimeError, 1159 "XML_ParserCreate failed"); 1160 Py_DECREF(self); 1161 return NULL; 1162 } 1163#if XML_COMBINED_VERSION >= 20100 1164 /* This feature was added upstream in libexpat 2.1.0. */ 1165 XML_SetHashSalt(self->itself, 1166 (unsigned long)_Py_HashSecret.expat.hashsalt); 1167#endif 1168 XML_SetUserData(self->itself, (void *)self); 1169 XML_SetUnknownEncodingHandler(self->itself, 1170 (XML_UnknownEncodingHandler) PyUnknownEncodingHandler, NULL); 1171 1172 for (i = 0; handler_info[i].name != NULL; i++) 1173 /* do nothing */; 1174 1175 self->handlers = PyMem_New(PyObject *, i); 1176 if (!self->handlers) { 1177 Py_DECREF(self); 1178 return PyErr_NoMemory(); 1179 } 1180 clear_handlers(self, 1); 1181 1182 PyObject_GC_Track(self); 1183 return (PyObject*)self; 1184} 1185 1186static int 1187xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) 1188{ 1189 for (int i = 0; handler_info[i].name != NULL; i++) { 1190 Py_VISIT(op->handlers[i]); 1191 } 1192 Py_VISIT(Py_TYPE(op)); 1193 return 0; 1194} 1195 1196static int 1197xmlparse_clear(xmlparseobject *op) 1198{ 1199 clear_handlers(op, 0); 1200 Py_CLEAR(op->intern); 1201 return 0; 1202} 1203 1204static void 1205xmlparse_dealloc(xmlparseobject *self) 1206{ 1207 PyObject_GC_UnTrack(self); 1208 (void)xmlparse_clear(self); 1209 if (self->itself != NULL) 1210 XML_ParserFree(self->itself); 1211 self->itself = NULL; 1212 1213 if (self->handlers != NULL) { 1214 PyMem_Free(self->handlers); 1215 self->handlers = NULL; 1216 } 1217 if (self->buffer != NULL) { 1218 PyMem_Free(self->buffer); 1219 self->buffer = NULL; 1220 } 1221 PyTypeObject *tp = Py_TYPE(self); 1222 PyObject_GC_Del(self); 1223 Py_DECREF(tp); 1224} 1225 1226 1227static PyObject * 1228xmlparse_handler_getter(xmlparseobject *self, struct HandlerInfo *hi) 1229{ 1230 assert((hi - handler_info) < (Py_ssize_t)Py_ARRAY_LENGTH(handler_info)); 1231 int handlernum = (int)(hi - handler_info); 1232 PyObject *result = self->handlers[handlernum]; 1233 if (result == NULL) 1234 result = Py_None; 1235 Py_INCREF(result); 1236 return result; 1237} 1238 1239static int 1240xmlparse_handler_setter(xmlparseobject *self, PyObject *v, struct HandlerInfo *hi) 1241{ 1242 assert((hi - handler_info) < (Py_ssize_t)Py_ARRAY_LENGTH(handler_info)); 1243 int handlernum = (int)(hi - handler_info); 1244 if (v == NULL) { 1245 PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); 1246 return -1; 1247 } 1248 if (handlernum == CharacterData) { 1249 /* If we're changing the character data handler, flush all 1250 * cached data with the old handler. Not sure there's a 1251 * "right" thing to do, though, but this probably won't 1252 * happen. 1253 */ 1254 if (flush_character_buffer(self) < 0) 1255 return -1; 1256 } 1257 1258 xmlhandler c_handler = NULL; 1259 if (v == Py_None) { 1260 /* If this is the character data handler, and a character 1261 data handler is already active, we need to be more 1262 careful. What we can safely do is replace the existing 1263 character data handler callback function with a no-op 1264 function that will refuse to call Python. The downside 1265 is that this doesn't completely remove the character 1266 data handler from the C layer if there's any callback 1267 active, so Expat does a little more work than it 1268 otherwise would, but that's really an odd case. A more 1269 elaborate system of handlers and state could remove the 1270 C handler more effectively. */ 1271 if (handlernum == CharacterData && self->in_callback) 1272 c_handler = noop_character_data_handler; 1273 v = NULL; 1274 } 1275 else if (v != NULL) { 1276 Py_INCREF(v); 1277 c_handler = handler_info[handlernum].handler; 1278 } 1279 Py_XSETREF(self->handlers[handlernum], v); 1280 handler_info[handlernum].setter(self->itself, c_handler); 1281 return 0; 1282} 1283 1284#define INT_GETTER(name) \ 1285 static PyObject * \ 1286 xmlparse_##name##_getter(xmlparseobject *self, void *closure) \ 1287 { \ 1288 return PyLong_FromLong((long) XML_Get##name(self->itself)); \ 1289 } 1290INT_GETTER(ErrorCode) 1291INT_GETTER(ErrorLineNumber) 1292INT_GETTER(ErrorColumnNumber) 1293INT_GETTER(ErrorByteIndex) 1294INT_GETTER(CurrentLineNumber) 1295INT_GETTER(CurrentColumnNumber) 1296INT_GETTER(CurrentByteIndex) 1297 1298#undef INT_GETTER 1299 1300static PyObject * 1301xmlparse_buffer_text_getter(xmlparseobject *self, void *closure) 1302{ 1303 return PyBool_FromLong(self->buffer != NULL); 1304} 1305 1306static int 1307xmlparse_buffer_text_setter(xmlparseobject *self, PyObject *v, void *closure) 1308{ 1309 if (v == NULL) { 1310 PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); 1311 return -1; 1312 } 1313 int b = PyObject_IsTrue(v); 1314 if (b < 0) 1315 return -1; 1316 if (b) { 1317 if (self->buffer == NULL) { 1318 self->buffer = PyMem_Malloc(self->buffer_size); 1319 if (self->buffer == NULL) { 1320 PyErr_NoMemory(); 1321 return -1; 1322 } 1323 self->buffer_used = 0; 1324 } 1325 } 1326 else if (self->buffer != NULL) { 1327 if (flush_character_buffer(self) < 0) 1328 return -1; 1329 PyMem_Free(self->buffer); 1330 self->buffer = NULL; 1331 } 1332 return 0; 1333} 1334 1335static PyObject * 1336xmlparse_buffer_size_getter(xmlparseobject *self, void *closure) 1337{ 1338 return PyLong_FromLong((long) self->buffer_size); 1339} 1340 1341static int 1342xmlparse_buffer_size_setter(xmlparseobject *self, PyObject *v, void *closure) 1343{ 1344 if (v == NULL) { 1345 PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); 1346 return -1; 1347 } 1348 long new_buffer_size; 1349 if (!PyLong_Check(v)) { 1350 PyErr_SetString(PyExc_TypeError, "buffer_size must be an integer"); 1351 return -1; 1352 } 1353 1354 new_buffer_size = PyLong_AsLong(v); 1355 if (new_buffer_size <= 0) { 1356 if (!PyErr_Occurred()) 1357 PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than zero"); 1358 return -1; 1359 } 1360 1361 /* trivial case -- no change */ 1362 if (new_buffer_size == self->buffer_size) { 1363 return 0; 1364 } 1365 1366 /* check maximum */ 1367 if (new_buffer_size > INT_MAX) { 1368 char errmsg[100]; 1369 sprintf(errmsg, "buffer_size must not be greater than %i", INT_MAX); 1370 PyErr_SetString(PyExc_ValueError, errmsg); 1371 return -1; 1372 } 1373 1374 if (self->buffer != NULL) { 1375 /* there is already a buffer */ 1376 if (self->buffer_used != 0) { 1377 if (flush_character_buffer(self) < 0) { 1378 return -1; 1379 } 1380 } 1381 /* free existing buffer */ 1382 PyMem_Free(self->buffer); 1383 } 1384 self->buffer = PyMem_Malloc(new_buffer_size); 1385 if (self->buffer == NULL) { 1386 PyErr_NoMemory(); 1387 return -1; 1388 } 1389 self->buffer_size = new_buffer_size; 1390 return 0; 1391} 1392 1393static PyObject * 1394xmlparse_buffer_used_getter(xmlparseobject *self, void *closure) 1395{ 1396 return PyLong_FromLong((long) self->buffer_used); 1397} 1398 1399static PyObject * 1400xmlparse_namespace_prefixes_getter(xmlparseobject *self, void *closure) 1401{ 1402 return PyBool_FromLong(self->ns_prefixes); 1403} 1404 1405static int 1406xmlparse_namespace_prefixes_setter(xmlparseobject *self, PyObject *v, void *closure) 1407{ 1408 if (v == NULL) { 1409 PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); 1410 return -1; 1411 } 1412 int b = PyObject_IsTrue(v); 1413 if (b < 0) 1414 return -1; 1415 self->ns_prefixes = b; 1416 XML_SetReturnNSTriplet(self->itself, self->ns_prefixes); 1417 return 0; 1418} 1419 1420static PyObject * 1421xmlparse_ordered_attributes_getter(xmlparseobject *self, void *closure) 1422{ 1423 return PyBool_FromLong(self->ordered_attributes); 1424} 1425 1426static int 1427xmlparse_ordered_attributes_setter(xmlparseobject *self, PyObject *v, void *closure) 1428{ 1429 if (v == NULL) { 1430 PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); 1431 return -1; 1432 } 1433 int b = PyObject_IsTrue(v); 1434 if (b < 0) 1435 return -1; 1436 self->ordered_attributes = b; 1437 return 0; 1438} 1439 1440static PyObject * 1441xmlparse_specified_attributes_getter(xmlparseobject *self, void *closure) 1442{ 1443 return PyBool_FromLong((long) self->specified_attributes); 1444} 1445 1446static int 1447xmlparse_specified_attributes_setter(xmlparseobject *self, PyObject *v, void *closure) 1448{ 1449 if (v == NULL) { 1450 PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); 1451 return -1; 1452 } 1453 int b = PyObject_IsTrue(v); 1454 if (b < 0) 1455 return -1; 1456 self->specified_attributes = b; 1457 return 0; 1458} 1459 1460static PyMemberDef xmlparse_members[] = { 1461 {"intern", T_OBJECT, offsetof(xmlparseobject, intern), READONLY, NULL}, 1462 {NULL} 1463}; 1464 1465#define XMLPARSE_GETTER_DEF(name) \ 1466 {#name, (getter)xmlparse_##name##_getter, NULL, NULL}, 1467#define XMLPARSE_GETTER_SETTER_DEF(name) \ 1468 {#name, (getter)xmlparse_##name##_getter, \ 1469 (setter)xmlparse_##name##_setter, NULL}, 1470 1471static PyGetSetDef xmlparse_getsetlist[] = { 1472 XMLPARSE_GETTER_DEF(ErrorCode) 1473 XMLPARSE_GETTER_DEF(ErrorLineNumber) 1474 XMLPARSE_GETTER_DEF(ErrorColumnNumber) 1475 XMLPARSE_GETTER_DEF(ErrorByteIndex) 1476 XMLPARSE_GETTER_DEF(CurrentLineNumber) 1477 XMLPARSE_GETTER_DEF(CurrentColumnNumber) 1478 XMLPARSE_GETTER_DEF(CurrentByteIndex) 1479 XMLPARSE_GETTER_SETTER_DEF(buffer_size) 1480 XMLPARSE_GETTER_SETTER_DEF(buffer_text) 1481 XMLPARSE_GETTER_DEF(buffer_used) 1482 XMLPARSE_GETTER_SETTER_DEF(namespace_prefixes) 1483 XMLPARSE_GETTER_SETTER_DEF(ordered_attributes) 1484 XMLPARSE_GETTER_SETTER_DEF(specified_attributes) 1485 {NULL}, 1486}; 1487 1488#undef XMLPARSE_GETTER_DEF 1489#undef XMLPARSE_GETTER_SETTER_DEF 1490 1491PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser"); 1492 1493static PyType_Slot _xml_parse_type_spec_slots[] = { 1494 {Py_tp_dealloc, xmlparse_dealloc}, 1495 {Py_tp_doc, (void *)Xmlparsetype__doc__}, 1496 {Py_tp_traverse, xmlparse_traverse}, 1497 {Py_tp_clear, xmlparse_clear}, 1498 {Py_tp_methods, xmlparse_methods}, 1499 {Py_tp_members, xmlparse_members}, 1500 {Py_tp_getset, xmlparse_getsetlist}, 1501 {0, 0} 1502}; 1503 1504static PyType_Spec _xml_parse_type_spec = { 1505 .name = "pyexpat.xmlparser", 1506 .basicsize = sizeof(xmlparseobject), 1507 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 1508 Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), 1509 .slots = _xml_parse_type_spec_slots, 1510}; 1511 1512/* End of code for xmlparser objects */ 1513/* -------------------------------------------------------- */ 1514 1515/*[clinic input] 1516pyexpat.ParserCreate 1517 1518 encoding: str(accept={str, NoneType}) = None 1519 namespace_separator: str(accept={str, NoneType}) = None 1520 intern: object = NULL 1521 1522Return a new XML parser object. 1523[clinic start generated code]*/ 1524 1525static PyObject * 1526pyexpat_ParserCreate_impl(PyObject *module, const char *encoding, 1527 const char *namespace_separator, PyObject *intern) 1528/*[clinic end generated code: output=295c0cf01ab1146c input=e8da8e8d7122cb5d]*/ 1529{ 1530 PyObject *result; 1531 int intern_decref = 0; 1532 1533 if (namespace_separator != NULL 1534 && strlen(namespace_separator) > 1) { 1535 PyErr_SetString(PyExc_ValueError, 1536 "namespace_separator must be at most one" 1537 " character, omitted, or None"); 1538 return NULL; 1539 } 1540 /* Explicitly passing None means no interning is desired. 1541 Not passing anything means that a new dictionary is used. */ 1542 if (intern == Py_None) 1543 intern = NULL; 1544 else if (intern == NULL) { 1545 intern = PyDict_New(); 1546 if (!intern) 1547 return NULL; 1548 intern_decref = 1; 1549 } 1550 else if (!PyDict_Check(intern)) { 1551 PyErr_SetString(PyExc_TypeError, "intern must be a dictionary"); 1552 return NULL; 1553 } 1554 1555 pyexpat_state *state = pyexpat_get_state(module); 1556 result = newxmlparseobject(state, encoding, namespace_separator, intern); 1557 if (intern_decref) { 1558 Py_DECREF(intern); 1559 } 1560 return result; 1561} 1562 1563/*[clinic input] 1564pyexpat.ErrorString 1565 1566 code: long 1567 / 1568 1569Returns string error for given number. 1570[clinic start generated code]*/ 1571 1572static PyObject * 1573pyexpat_ErrorString_impl(PyObject *module, long code) 1574/*[clinic end generated code: output=2feae50d166f2174 input=cc67de010d9e62b3]*/ 1575{ 1576 return Py_BuildValue("z", XML_ErrorString((int)code)); 1577} 1578 1579/* List of methods defined in the module */ 1580 1581static struct PyMethodDef pyexpat_methods[] = { 1582 PYEXPAT_PARSERCREATE_METHODDEF 1583 PYEXPAT_ERRORSTRING_METHODDEF 1584 {NULL, NULL} /* sentinel */ 1585}; 1586 1587/* Module docstring */ 1588 1589PyDoc_STRVAR(pyexpat_module_documentation, 1590"Python wrapper for Expat parser."); 1591 1592/* Initialization function for the module */ 1593 1594#ifndef MODULE_NAME 1595#define MODULE_NAME "pyexpat" 1596#endif 1597 1598static int init_handler_descrs(pyexpat_state *state) 1599{ 1600 int i; 1601 assert(!PyType_HasFeature(state->xml_parse_type, Py_TPFLAGS_VALID_VERSION_TAG)); 1602 for (i = 0; handler_info[i].name != NULL; i++) { 1603 struct HandlerInfo *hi = &handler_info[i]; 1604 hi->getset.name = hi->name; 1605 hi->getset.get = (getter)xmlparse_handler_getter; 1606 hi->getset.set = (setter)xmlparse_handler_setter; 1607 hi->getset.closure = &handler_info[i]; 1608 1609 PyObject *descr = PyDescr_NewGetSet(state->xml_parse_type, &hi->getset); 1610 if (descr == NULL) 1611 return -1; 1612 1613 if (PyDict_SetDefault(state->xml_parse_type->tp_dict, PyDescr_NAME(descr), descr) == NULL) { 1614 Py_DECREF(descr); 1615 return -1; 1616 } 1617 Py_DECREF(descr); 1618 } 1619 return 0; 1620} 1621 1622static PyObject * 1623add_submodule(PyObject *mod, const char *fullname) 1624{ 1625 const char *name = strrchr(fullname, '.') + 1; 1626 1627 PyObject *submodule = PyModule_New(fullname); 1628 if (submodule == NULL) { 1629 return NULL; 1630 } 1631 1632 PyObject *mod_name = PyUnicode_FromString(fullname); 1633 if (mod_name == NULL) { 1634 Py_DECREF(submodule); 1635 return NULL; 1636 } 1637 1638 if (_PyImport_SetModule(mod_name, submodule) < 0) { 1639 Py_DECREF(submodule); 1640 Py_DECREF(mod_name); 1641 return NULL; 1642 } 1643 Py_DECREF(mod_name); 1644 1645 /* gives away the reference to the submodule */ 1646 if (PyModule_AddObject(mod, name, submodule) < 0) { 1647 Py_DECREF(submodule); 1648 return NULL; 1649 } 1650 1651 return submodule; 1652} 1653 1654struct ErrorInfo { 1655 const char * name; /* Error constant name, e.g. "XML_ERROR_NO_MEMORY" */ 1656 const char * description; /* Error description as returned by XML_ErrorString(<int>) */ 1657}; 1658 1659static 1660struct ErrorInfo error_info_of[] = { 1661 {NULL, NULL}, /* XML_ERROR_NONE (value 0) is not exposed */ 1662 1663 {"XML_ERROR_NO_MEMORY", "out of memory"}, 1664 {"XML_ERROR_SYNTAX", "syntax error"}, 1665 {"XML_ERROR_NO_ELEMENTS", "no element found"}, 1666 {"XML_ERROR_INVALID_TOKEN", "not well-formed (invalid token)"}, 1667 {"XML_ERROR_UNCLOSED_TOKEN", "unclosed token"}, 1668 {"XML_ERROR_PARTIAL_CHAR", "partial character"}, 1669 {"XML_ERROR_TAG_MISMATCH", "mismatched tag"}, 1670 {"XML_ERROR_DUPLICATE_ATTRIBUTE", "duplicate attribute"}, 1671 {"XML_ERROR_JUNK_AFTER_DOC_ELEMENT", "junk after document element"}, 1672 {"XML_ERROR_PARAM_ENTITY_REF", "illegal parameter entity reference"}, 1673 {"XML_ERROR_UNDEFINED_ENTITY", "undefined entity"}, 1674 {"XML_ERROR_RECURSIVE_ENTITY_REF", "recursive entity reference"}, 1675 {"XML_ERROR_ASYNC_ENTITY", "asynchronous entity"}, 1676 {"XML_ERROR_BAD_CHAR_REF", "reference to invalid character number"}, 1677 {"XML_ERROR_BINARY_ENTITY_REF", "reference to binary entity"}, 1678 {"XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", "reference to external entity in attribute"}, 1679 {"XML_ERROR_MISPLACED_XML_PI", "XML or text declaration not at start of entity"}, 1680 {"XML_ERROR_UNKNOWN_ENCODING", "unknown encoding"}, 1681 {"XML_ERROR_INCORRECT_ENCODING", "encoding specified in XML declaration is incorrect"}, 1682 {"XML_ERROR_UNCLOSED_CDATA_SECTION", "unclosed CDATA section"}, 1683 {"XML_ERROR_EXTERNAL_ENTITY_HANDLING", "error in processing external entity reference"}, 1684 {"XML_ERROR_NOT_STANDALONE", "document is not standalone"}, 1685 {"XML_ERROR_UNEXPECTED_STATE", "unexpected parser state - please send a bug report"}, 1686 {"XML_ERROR_ENTITY_DECLARED_IN_PE", "entity declared in parameter entity"}, 1687 {"XML_ERROR_FEATURE_REQUIRES_XML_DTD", "requested feature requires XML_DTD support in Expat"}, 1688 {"XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING", "cannot change setting once parsing has begun"}, 1689 1690 /* Added in Expat 1.95.7. */ 1691 {"XML_ERROR_UNBOUND_PREFIX", "unbound prefix"}, 1692 1693 /* Added in Expat 1.95.8. */ 1694 {"XML_ERROR_UNDECLARING_PREFIX", "must not undeclare prefix"}, 1695 {"XML_ERROR_INCOMPLETE_PE", "incomplete markup in parameter entity"}, 1696 {"XML_ERROR_XML_DECL", "XML declaration not well-formed"}, 1697 {"XML_ERROR_TEXT_DECL", "text declaration not well-formed"}, 1698 {"XML_ERROR_PUBLICID", "illegal character(s) in public id"}, 1699 {"XML_ERROR_SUSPENDED", "parser suspended"}, 1700 {"XML_ERROR_NOT_SUSPENDED", "parser not suspended"}, 1701 {"XML_ERROR_ABORTED", "parsing aborted"}, 1702 {"XML_ERROR_FINISHED", "parsing finished"}, 1703 {"XML_ERROR_SUSPEND_PE", "cannot suspend in external parameter entity"}, 1704 1705 /* Added in 2.0.0. */ 1706 {"XML_ERROR_RESERVED_PREFIX_XML", "reserved prefix (xml) must not be undeclared or bound to another namespace name"}, 1707 {"XML_ERROR_RESERVED_PREFIX_XMLNS", "reserved prefix (xmlns) must not be declared or undeclared"}, 1708 {"XML_ERROR_RESERVED_NAMESPACE_URI", "prefix must not be bound to one of the reserved namespace names"}, 1709 1710 /* Added in 2.2.1. */ 1711 {"XML_ERROR_INVALID_ARGUMENT", "invalid argument"}, 1712 1713 /* Added in 2.3.0. */ 1714 {"XML_ERROR_NO_BUFFER", "a successful prior call to function XML_GetBuffer is required"}, 1715 1716 /* Added in 2.4.0. */ 1717 {"XML_ERROR_AMPLIFICATION_LIMIT_BREACH", "limit on input amplification factor (from DTD and entities) breached"} 1718}; 1719 1720static int 1721add_error(PyObject *errors_module, PyObject *codes_dict, 1722 PyObject *rev_codes_dict, size_t error_index) 1723{ 1724 const char * const name = error_info_of[error_index].name; 1725 const int error_code = (int)error_index; 1726 1727 /* NOTE: This keeps the source of truth regarding error 1728 * messages with libexpat and (by definiton) in bulletproof sync 1729 * with the other uses of the XML_ErrorString function 1730 * elsewhere within this file. pyexpat's copy of the messages 1731 * only acts as a fallback in case of outdated runtime libexpat, 1732 * where it returns NULL. */ 1733 const char *error_string = XML_ErrorString(error_code); 1734 if (error_string == NULL) { 1735 error_string = error_info_of[error_index].description; 1736 } 1737 1738 if (PyModule_AddStringConstant(errors_module, name, error_string) < 0) { 1739 return -1; 1740 } 1741 1742 PyObject *num = PyLong_FromLong(error_code); 1743 if (num == NULL) { 1744 return -1; 1745 } 1746 1747 if (PyDict_SetItemString(codes_dict, error_string, num) < 0) { 1748 Py_DECREF(num); 1749 return -1; 1750 } 1751 1752 PyObject *str = PyUnicode_FromString(error_string); 1753 if (str == NULL) { 1754 Py_DECREF(num); 1755 return -1; 1756 } 1757 1758 int res = PyDict_SetItem(rev_codes_dict, num, str); 1759 Py_DECREF(str); 1760 Py_DECREF(num); 1761 if (res < 0) { 1762 return -1; 1763 } 1764 1765 return 0; 1766} 1767 1768static int 1769add_errors_module(PyObject *mod) 1770{ 1771 PyObject *errors_module = add_submodule(mod, MODULE_NAME ".errors"); 1772 if (errors_module == NULL) { 1773 return -1; 1774 } 1775 1776 PyObject *codes_dict = PyDict_New(); 1777 PyObject *rev_codes_dict = PyDict_New(); 1778 if (codes_dict == NULL || rev_codes_dict == NULL) { 1779 goto error; 1780 } 1781 1782 size_t error_index = 0; 1783 for (; error_index < sizeof(error_info_of) / sizeof(struct ErrorInfo); error_index++) { 1784 if (error_info_of[error_index].name == NULL) { 1785 continue; 1786 } 1787 1788 if (add_error(errors_module, codes_dict, rev_codes_dict, error_index) < 0) { 1789 goto error; 1790 } 1791 } 1792 1793 if (PyModule_AddStringConstant(errors_module, "__doc__", 1794 "Constants used to describe " 1795 "error conditions.") < 0) { 1796 goto error; 1797 } 1798 1799 Py_INCREF(codes_dict); 1800 if (PyModule_AddObject(errors_module, "codes", codes_dict) < 0) { 1801 Py_DECREF(codes_dict); 1802 goto error; 1803 } 1804 Py_CLEAR(codes_dict); 1805 1806 Py_INCREF(rev_codes_dict); 1807 if (PyModule_AddObject(errors_module, "messages", rev_codes_dict) < 0) { 1808 Py_DECREF(rev_codes_dict); 1809 goto error; 1810 } 1811 Py_CLEAR(rev_codes_dict); 1812 1813 return 0; 1814 1815error: 1816 Py_XDECREF(codes_dict); 1817 Py_XDECREF(rev_codes_dict); 1818 return -1; 1819} 1820 1821static int 1822add_model_module(PyObject *mod) 1823{ 1824 PyObject *model_module = add_submodule(mod, MODULE_NAME ".model"); 1825 if (model_module == NULL) { 1826 return -1; 1827 } 1828 1829#define MYCONST(c) do { \ 1830 if (PyModule_AddIntConstant(model_module, #c, c) < 0) { \ 1831 return -1; \ 1832 } \ 1833 } while(0) 1834 1835 if (PyModule_AddStringConstant( 1836 model_module, "__doc__", 1837 "Constants used to interpret content model information.") < 0) { 1838 return -1; 1839 } 1840 1841 MYCONST(XML_CTYPE_EMPTY); 1842 MYCONST(XML_CTYPE_ANY); 1843 MYCONST(XML_CTYPE_MIXED); 1844 MYCONST(XML_CTYPE_NAME); 1845 MYCONST(XML_CTYPE_CHOICE); 1846 MYCONST(XML_CTYPE_SEQ); 1847 1848 MYCONST(XML_CQUANT_NONE); 1849 MYCONST(XML_CQUANT_OPT); 1850 MYCONST(XML_CQUANT_REP); 1851 MYCONST(XML_CQUANT_PLUS); 1852#undef MYCONST 1853 return 0; 1854} 1855 1856#if XML_COMBINED_VERSION > 19505 1857static int 1858add_features(PyObject *mod) 1859{ 1860 PyObject *list = PyList_New(0); 1861 if (list == NULL) { 1862 return -1; 1863 } 1864 1865 const XML_Feature *features = XML_GetFeatureList(); 1866 for (size_t i = 0; features[i].feature != XML_FEATURE_END; ++i) { 1867 PyObject *item = Py_BuildValue("si", features[i].name, 1868 features[i].value); 1869 if (item == NULL) { 1870 goto error; 1871 } 1872 int ok = PyList_Append(list, item); 1873 Py_DECREF(item); 1874 if (ok < 0) { 1875 goto error; 1876 } 1877 } 1878 if (PyModule_AddObject(mod, "features", list) < 0) { 1879 goto error; 1880 } 1881 return 0; 1882 1883error: 1884 Py_DECREF(list); 1885 return -1; 1886} 1887#endif 1888 1889static int 1890pyexpat_exec(PyObject *mod) 1891{ 1892 pyexpat_state *state = pyexpat_get_state(mod); 1893 state->str_read = PyUnicode_InternFromString("read"); 1894 if (state->str_read == NULL) { 1895 return -1; 1896 } 1897 state->xml_parse_type = (PyTypeObject *)PyType_FromModuleAndSpec( 1898 mod, &_xml_parse_type_spec, NULL); 1899 1900 if (state->xml_parse_type == NULL) { 1901 return -1; 1902 } 1903 1904 if (init_handler_descrs(state) < 0) { 1905 return -1; 1906 } 1907 state->error = PyErr_NewException("xml.parsers.expat.ExpatError", 1908 NULL, NULL); 1909 if (state->error == NULL) { 1910 return -1; 1911 } 1912 1913 /* Add some symbolic constants to the module */ 1914 1915 if (PyModule_AddObjectRef(mod, "error", state->error) < 0) { 1916 return -1; 1917 } 1918 1919 if (PyModule_AddObjectRef(mod, "ExpatError", state->error) < 0) { 1920 return -1; 1921 } 1922 1923 if (PyModule_AddObjectRef(mod, "XMLParserType", 1924 (PyObject *) state->xml_parse_type) < 0) { 1925 return -1; 1926 } 1927 1928 if (PyModule_AddStringConstant(mod, "EXPAT_VERSION", 1929 XML_ExpatVersion()) < 0) { 1930 return -1; 1931 } 1932 { 1933 XML_Expat_Version info = XML_ExpatVersionInfo(); 1934 PyObject *versionInfo = Py_BuildValue("(iii)", 1935 info.major, 1936 info.minor, 1937 info.micro); 1938 if (PyModule_AddObject(mod, "version_info", versionInfo) < 0) { 1939 Py_DECREF(versionInfo); 1940 return -1; 1941 } 1942 } 1943 /* XXX When Expat supports some way of figuring out how it was 1944 compiled, this should check and set native_encoding 1945 appropriately. 1946 */ 1947 if (PyModule_AddStringConstant(mod, "native_encoding", "UTF-8") < 0) { 1948 return -1; 1949 } 1950 1951 if (add_errors_module(mod) < 0) { 1952 return -1; 1953 } 1954 1955 if (add_model_module(mod) < 0) { 1956 return -1; 1957 } 1958 1959#if XML_COMBINED_VERSION > 19505 1960 if (add_features(mod) < 0) { 1961 return -1; 1962 } 1963#endif 1964 1965#define MYCONST(c) do { \ 1966 if (PyModule_AddIntConstant(mod, #c, c) < 0) { \ 1967 return -1; \ 1968 } \ 1969 } while(0) 1970 1971 MYCONST(XML_PARAM_ENTITY_PARSING_NEVER); 1972 MYCONST(XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); 1973 MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS); 1974#undef MYCONST 1975 1976 static struct PyExpat_CAPI capi; 1977 /* initialize pyexpat dispatch table */ 1978 capi.size = sizeof(capi); 1979 capi.magic = PyExpat_CAPI_MAGIC; 1980 capi.MAJOR_VERSION = XML_MAJOR_VERSION; 1981 capi.MINOR_VERSION = XML_MINOR_VERSION; 1982 capi.MICRO_VERSION = XML_MICRO_VERSION; 1983 capi.ErrorString = XML_ErrorString; 1984 capi.GetErrorCode = XML_GetErrorCode; 1985 capi.GetErrorColumnNumber = XML_GetErrorColumnNumber; 1986 capi.GetErrorLineNumber = XML_GetErrorLineNumber; 1987 capi.Parse = XML_Parse; 1988 capi.ParserCreate_MM = XML_ParserCreate_MM; 1989 capi.ParserFree = XML_ParserFree; 1990 capi.SetCharacterDataHandler = XML_SetCharacterDataHandler; 1991 capi.SetCommentHandler = XML_SetCommentHandler; 1992 capi.SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand; 1993 capi.SetElementHandler = XML_SetElementHandler; 1994 capi.SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler; 1995 capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; 1996 capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; 1997 capi.SetUserData = XML_SetUserData; 1998 capi.SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler; 1999 capi.SetEncoding = XML_SetEncoding; 2000 capi.DefaultUnknownEncodingHandler = PyUnknownEncodingHandler; 2001#if XML_COMBINED_VERSION >= 20100 2002 capi.SetHashSalt = XML_SetHashSalt; 2003#else 2004 capi.SetHashSalt = NULL; 2005#endif 2006 2007 /* export using capsule */ 2008 PyObject *capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL); 2009 if (capi_object == NULL) { 2010 return -1; 2011 } 2012 2013 if (PyModule_AddObject(mod, "expat_CAPI", capi_object) < 0) { 2014 Py_DECREF(capi_object); 2015 return -1; 2016 } 2017 2018 return 0; 2019} 2020 2021static int 2022pyexpat_traverse(PyObject *module, visitproc visit, void *arg) 2023{ 2024 pyexpat_state *state = pyexpat_get_state(module); 2025 Py_VISIT(state->xml_parse_type); 2026 Py_VISIT(state->error); 2027 Py_VISIT(state->str_read); 2028 return 0; 2029} 2030 2031static int 2032pyexpat_clear(PyObject *module) 2033{ 2034 pyexpat_state *state = pyexpat_get_state(module); 2035 Py_CLEAR(state->xml_parse_type); 2036 Py_CLEAR(state->error); 2037 Py_CLEAR(state->str_read); 2038 return 0; 2039} 2040 2041static void 2042pyexpat_free(void *module) 2043{ 2044 pyexpat_clear((PyObject *)module); 2045} 2046 2047static PyModuleDef_Slot pyexpat_slots[] = { 2048 {Py_mod_exec, pyexpat_exec}, 2049 {0, NULL} 2050}; 2051 2052static struct PyModuleDef pyexpatmodule = { 2053 PyModuleDef_HEAD_INIT, 2054 .m_name = MODULE_NAME, 2055 .m_doc = pyexpat_module_documentation, 2056 .m_size = sizeof(pyexpat_state), 2057 .m_methods = pyexpat_methods, 2058 .m_slots = pyexpat_slots, 2059 .m_traverse = pyexpat_traverse, 2060 .m_clear = pyexpat_clear, 2061 .m_free = pyexpat_free 2062}; 2063 2064PyMODINIT_FUNC 2065PyInit_pyexpat(void) 2066{ 2067 return PyModuleDef_Init(&pyexpatmodule); 2068} 2069 2070static void 2071clear_handlers(xmlparseobject *self, int initial) 2072{ 2073 int i = 0; 2074 2075 for (; handler_info[i].name != NULL; i++) { 2076 if (initial) 2077 self->handlers[i] = NULL; 2078 else { 2079 Py_CLEAR(self->handlers[i]); 2080 handler_info[i].setter(self->itself, NULL); 2081 } 2082 } 2083} 2084 2085static struct HandlerInfo handler_info[] = { 2086 2087#define HANDLER_INFO(name) \ 2088 {#name, (xmlhandlersetter)XML_Set##name, (xmlhandler)my_##name}, 2089 2090 HANDLER_INFO(StartElementHandler) 2091 HANDLER_INFO(EndElementHandler) 2092 HANDLER_INFO(ProcessingInstructionHandler) 2093 HANDLER_INFO(CharacterDataHandler) 2094 HANDLER_INFO(UnparsedEntityDeclHandler) 2095 HANDLER_INFO(NotationDeclHandler) 2096 HANDLER_INFO(StartNamespaceDeclHandler) 2097 HANDLER_INFO(EndNamespaceDeclHandler) 2098 HANDLER_INFO(CommentHandler) 2099 HANDLER_INFO(StartCdataSectionHandler) 2100 HANDLER_INFO(EndCdataSectionHandler) 2101 HANDLER_INFO(DefaultHandler) 2102 HANDLER_INFO(DefaultHandlerExpand) 2103 HANDLER_INFO(NotStandaloneHandler) 2104 HANDLER_INFO(ExternalEntityRefHandler) 2105 HANDLER_INFO(StartDoctypeDeclHandler) 2106 HANDLER_INFO(EndDoctypeDeclHandler) 2107 HANDLER_INFO(EntityDeclHandler) 2108 HANDLER_INFO(XmlDeclHandler) 2109 HANDLER_INFO(ElementDeclHandler) 2110 HANDLER_INFO(AttlistDeclHandler) 2111#if XML_COMBINED_VERSION >= 19504 2112 HANDLER_INFO(SkippedEntityHandler) 2113#endif 2114 2115#undef HANDLER_INFO 2116 2117 {NULL, NULL, NULL} /* sentinel */ 2118}; 2119