#include #include #include #include #include int expatdump_err = 0; #define EXPATDUMP_XML_PARSER_ERR 1 static void start_fn(void *userData, const XML_Char *name, const XML_Char **atts) { printf("<%s>", name); } static void end_fn(void *userData, const XML_Char *name) { printf("", name); } static void doctype_start_fn(void *userData, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *pubid, int has_internal_subset) { printf("DOCTYPE %s [\n", doctypeName); } static void doctype_end_fn(void *userData) { printf("]\n"); } static void eldecl_fn(void *userData, const XML_Char *name, XML_Content *model) { printf("ELEMENT %s\n", name); free(model); } static void entdecl_fn(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) { printf("ENTITY %s\n", entityName); } static int parse(XML_Parser p, FILE *stream); static int extern_fn(XML_Parser p, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { XML_Parser ep; FILE *in; int ret; if ((in = fopen(systemId, "r")) == NULL) { expatdump_err = errno; return 0; } if ((ep = XML_ExternalEntityParserCreate(p, context, NULL)) == NULL) { expatdump_err = EXPATDUMP_XML_PARSER_ERR; fclose(in); return 0; } ret = 1; if (parse(ep, in) == -1) { ret = 0; } fclose(in); return ret; } static int parse(XML_Parser p, FILE *stream) { int ret, pret, done; void *buf; size_t n; ret = 0; for ( ;; ) { if ((buf = XML_GetBuffer(p, BUFSIZ)) == NULL) { expatdump_err = EXPATDUMP_XML_PARSER_ERR; ret = -1; break; } if ((n = fread(buf, 1, BUFSIZ, stream)) == 0 && ferror(stream)) { expatdump_err = ferror(stream); ret = -1; break; } pret = XML_ParseBuffer(p, n, (done = feof(stream))); if (pret == 0 || expatdump_err) { int err = XML_GetErrorCode(p); if (pret == 0 && err != XML_ERROR_EXTERNAL_ENTITY_HANDLING) { fprintf(stderr, "Error parsing external entity: %s\n", XML_ErrorString(err)); } ret = -1; break; } if (done) { break; } } return ret; } int expatdump(FILE *stream) { XML_Parser p; int ret; if ((p = XML_ParserCreate(NULL)) == NULL) { expatdump_err = EXPATDUMP_XML_PARSER_ERR; return -1; } XML_SetElementHandler(p, start_fn, end_fn); XML_SetDoctypeDeclHandler(p, doctype_start_fn, doctype_end_fn); XML_SetElementDeclHandler(p, eldecl_fn); XML_SetEntityDeclHandler(p, entdecl_fn); XML_SetExternalEntityRefHandler(p, extern_fn); XML_SetParamEntityParsing(p, XML_PARAM_ENTITY_PARSING_ALWAYS); ret = 0; if (parse(p, stream) == -1) { ret = -1; } XML_ParserFree(p); return ret; } int main(int argc, const char *argv[]) { FILE *in; errno = 0; if (argc == 2) { if ((in = fopen(argv[1], "r")) == NULL) { perror("fopen"); return EXIT_FAILURE; } } else if (argc == 1) { in = stdin; } else { fprintf(stderr, "usage: expatdump \n"); return EXIT_FAILURE; } if (expatdump(in) == -1) { fprintf(stderr, "Failure\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; }