]> git.ipfire.org Git - thirdparty/squid.git/blob - src/esi/Libxml2Parser.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / esi / Libxml2Parser.cc
1 /*
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /*
10 * The ESI Libxml2 parser is Copyright (c) 2004 by Joachim Bauch
11 * http://www.joachim-bauch.de
12 * mail@joachim-bauch.de
13 */
14
15 #include "squid.h"
16
17 #if USE_SQUID_ESI && HAVE_LIBXML2
18
19 #include "esi/Libxml2Parser.h"
20
21 // the global document that will store the resolved entity
22 // definitions
23 static htmlDocPtr entity_doc = NULL;
24
25 EsiParserDefinition(ESILibxml2Parser);
26
27 // the SAX callback functions
28 void esi_startElementSAXFunc(void * ctx, const xmlChar * name, const xmlChar ** atts)
29 {
30 int count=0;
31 xmlChar **tmp = (xmlChar **)atts;
32
33 while (tmp && *tmp != NULL) {
34 ++count;
35 ++tmp;
36 }
37
38 // we increased on every key and value
39 count /= 2;
40
41 ESILibxml2Parser *p = (ESILibxml2Parser *)ctx;
42
43 p->getClient()->start((const char *)name, (const char **)atts, count);
44 }
45
46 void esi_endElementSAXFunc(void * ctx, const xmlChar * name)
47 {
48 ESILibxml2Parser *p = (ESILibxml2Parser *)ctx;
49 p->getClient()->end((const char *)name);
50 }
51
52 void esi_commentSAXFunc(void * ctx, const xmlChar * value)
53 {
54 ESILibxml2Parser *p = (ESILibxml2Parser *)ctx;
55 p->getClient()->parserComment((const char *)value);
56 }
57
58 void esi_charactersSAXFunc(void *ctx, const xmlChar *ch, int len)
59 {
60 ESILibxml2Parser *p = (ESILibxml2Parser *)ctx;
61 p->getClient()->parserDefault((const char *)ch, len);
62 }
63
64 xmlEntityPtr esi_getEntitySAXFunc(void * ctx, const xmlChar * name)
65 {
66 xmlEntityPtr res = xmlGetDocEntity(entity_doc, name);
67
68 if (res == NULL) {
69 const htmlEntityDesc *ent = htmlEntityLookup(name);
70
71 if (ent != NULL) {
72 char tmp[32];
73 snprintf(tmp, 32, "&#%d;", ent->value);
74 res = xmlAddDocEntity(entity_doc, (const xmlChar *)name, XML_INTERNAL_GENERAL_ENTITY, NULL, NULL, (const xmlChar *)tmp);
75 }
76 }
77
78 return res;
79 }
80
81 ESILibxml2Parser::ESILibxml2Parser(ESIParserClient *aClient) : theClient (aClient)
82 {
83 xmlSAXHandler sax;
84 htmlDefaultSAXHandlerInit();
85 memset(&sax, 0, sizeof(sax));
86 sax.startElement = esi_startElementSAXFunc;
87 sax.endElement = esi_endElementSAXFunc;
88 sax.comment = esi_commentSAXFunc;
89 sax.characters = esi_charactersSAXFunc;
90 sax.getEntity = esi_getEntitySAXFunc;
91
92 /* TODO: grab the document encoding from the headers */
93 parser = xmlCreatePushParserCtxt(&sax, static_cast<void *>(this), NULL, 0, NULL);
94 xmlSetFeature(parser, "substitute entities", 0);
95
96 if (entity_doc == NULL)
97 entity_doc = htmlNewDoc(NULL, NULL);
98 }
99
100 ESILibxml2Parser::~ESILibxml2Parser()
101 {
102 xmlFreeParserCtxt(parser);
103 parser = NULL;
104 }
105
106 bool
107 ESILibxml2Parser::parse(char const *dataToParse, size_t const lengthOfData, bool const endOfStream)
108 {
109 return (xmlParseChunk(parser, dataToParse, lengthOfData, endOfStream) == 0);
110 }
111
112 long int
113 ESILibxml2Parser::lineNumber() const
114 {
115 return (long int)xmlSAX2GetLineNumber(parser);
116 }
117
118 char const *
119 ESILibxml2Parser::errorString() const
120 {
121 xmlErrorPtr error = xmlGetLastError();
122
123 if (error == NULL)
124 return NULL;
125
126 return error->message;
127 }
128
129 #endif /* USE_SQUID_ESI */
130