1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker * valid.c : part of the code use to do the DTD handling and the validity
3*6777b538SAndroid Build Coastguard Worker * checking
4*6777b538SAndroid Build Coastguard Worker *
5*6777b538SAndroid Build Coastguard Worker * See Copyright for the status of this software.
6*6777b538SAndroid Build Coastguard Worker *
7*6777b538SAndroid Build Coastguard Worker * [email protected]
8*6777b538SAndroid Build Coastguard Worker */
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
11*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include <string.h>
14*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
17*6777b538SAndroid Build Coastguard Worker #include <libxml/hash.h>
18*6777b538SAndroid Build Coastguard Worker #include <libxml/uri.h>
19*6777b538SAndroid Build Coastguard Worker #include <libxml/valid.h>
20*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h>
21*6777b538SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
22*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
23*6777b538SAndroid Build Coastguard Worker #include <libxml/list.h>
24*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlsave.h>
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker #include "private/error.h"
27*6777b538SAndroid Build Coastguard Worker #include "private/parser.h"
28*6777b538SAndroid Build Coastguard Worker #include "private/regexp.h"
29*6777b538SAndroid Build Coastguard Worker #include "private/save.h"
30*6777b538SAndroid Build Coastguard Worker #include "private/tree.h"
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker static xmlElementPtr
33*6777b538SAndroid Build Coastguard Worker xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name);
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
36*6777b538SAndroid Build Coastguard Worker static int
37*6777b538SAndroid Build Coastguard Worker xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
38*6777b538SAndroid Build Coastguard Worker const xmlChar *value);
39*6777b538SAndroid Build Coastguard Worker #endif
40*6777b538SAndroid Build Coastguard Worker /************************************************************************
41*6777b538SAndroid Build Coastguard Worker * *
42*6777b538SAndroid Build Coastguard Worker * Error handling routines *
43*6777b538SAndroid Build Coastguard Worker * *
44*6777b538SAndroid Build Coastguard Worker ************************************************************************/
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker /**
47*6777b538SAndroid Build Coastguard Worker * xmlVErrMemory:
48*6777b538SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
49*6777b538SAndroid Build Coastguard Worker * @extra: extra information
50*6777b538SAndroid Build Coastguard Worker *
51*6777b538SAndroid Build Coastguard Worker * Handle an out of memory error
52*6777b538SAndroid Build Coastguard Worker */
53*6777b538SAndroid Build Coastguard Worker static void
xmlVErrMemory(xmlValidCtxtPtr ctxt)54*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(xmlValidCtxtPtr ctxt)
55*6777b538SAndroid Build Coastguard Worker {
56*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL) {
57*6777b538SAndroid Build Coastguard Worker if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
58*6777b538SAndroid Build Coastguard Worker xmlCtxtErrMemory(ctxt->userData);
59*6777b538SAndroid Build Coastguard Worker } else {
60*6777b538SAndroid Build Coastguard Worker xmlRaiseMemoryError(NULL, ctxt->error, ctxt->userData,
61*6777b538SAndroid Build Coastguard Worker XML_FROM_VALID, NULL);
62*6777b538SAndroid Build Coastguard Worker }
63*6777b538SAndroid Build Coastguard Worker } else {
64*6777b538SAndroid Build Coastguard Worker xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_VALID, NULL);
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker static void
xmlDoErrValid(xmlValidCtxtPtr ctxt,xmlNodePtr node,xmlParserErrors code,int level,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,int int1,const char * msg,...)69*6777b538SAndroid Build Coastguard Worker xmlDoErrValid(xmlValidCtxtPtr ctxt, xmlNodePtr node,
70*6777b538SAndroid Build Coastguard Worker xmlParserErrors code, int level,
71*6777b538SAndroid Build Coastguard Worker const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
72*6777b538SAndroid Build Coastguard Worker int int1,
73*6777b538SAndroid Build Coastguard Worker const char *msg, ...) {
74*6777b538SAndroid Build Coastguard Worker xmlParserCtxtPtr pctxt = NULL;
75*6777b538SAndroid Build Coastguard Worker va_list ap;
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT))
78*6777b538SAndroid Build Coastguard Worker pctxt = ctxt->userData;
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker va_start(ap, msg);
81*6777b538SAndroid Build Coastguard Worker if (pctxt != NULL) {
82*6777b538SAndroid Build Coastguard Worker xmlCtxtVErr(pctxt, node, XML_FROM_VALID, code, level,
83*6777b538SAndroid Build Coastguard Worker str1, str2, str3, int1, msg, ap);
84*6777b538SAndroid Build Coastguard Worker } else {
85*6777b538SAndroid Build Coastguard Worker xmlGenericErrorFunc channel = NULL;
86*6777b538SAndroid Build Coastguard Worker void *data = NULL;
87*6777b538SAndroid Build Coastguard Worker int res;
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL) {
90*6777b538SAndroid Build Coastguard Worker channel = ctxt->error;
91*6777b538SAndroid Build Coastguard Worker data = ctxt->userData;
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker res = xmlVRaiseError(NULL, channel, data, NULL, node,
94*6777b538SAndroid Build Coastguard Worker XML_FROM_VALID, code, level, NULL, 0,
95*6777b538SAndroid Build Coastguard Worker (const char *) str1, (const char *) str2,
96*6777b538SAndroid Build Coastguard Worker (const char *) str2, int1, 0,
97*6777b538SAndroid Build Coastguard Worker msg, ap);
98*6777b538SAndroid Build Coastguard Worker if (res < 0)
99*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker va_end(ap);
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Worker /**
105*6777b538SAndroid Build Coastguard Worker * xmlErrValid:
106*6777b538SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
107*6777b538SAndroid Build Coastguard Worker * @error: the error number
108*6777b538SAndroid Build Coastguard Worker * @extra: extra information
109*6777b538SAndroid Build Coastguard Worker *
110*6777b538SAndroid Build Coastguard Worker * Handle a validation error
111*6777b538SAndroid Build Coastguard Worker */
112*6777b538SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(3,0)
xmlErrValid(xmlValidCtxtPtr ctxt,xmlParserErrors error,const char * msg,const char * extra)113*6777b538SAndroid Build Coastguard Worker xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error,
114*6777b538SAndroid Build Coastguard Worker const char *msg, const char *extra)
115*6777b538SAndroid Build Coastguard Worker {
116*6777b538SAndroid Build Coastguard Worker xmlDoErrValid(ctxt, NULL, error, XML_ERR_ERROR, (const xmlChar *) extra,
117*6777b538SAndroid Build Coastguard Worker NULL, NULL, 0, msg, extra);
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
121*6777b538SAndroid Build Coastguard Worker /**
122*6777b538SAndroid Build Coastguard Worker * xmlErrValidNode:
123*6777b538SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
124*6777b538SAndroid Build Coastguard Worker * @node: the node raising the error
125*6777b538SAndroid Build Coastguard Worker * @error: the error number
126*6777b538SAndroid Build Coastguard Worker * @str1: extra information
127*6777b538SAndroid Build Coastguard Worker * @str2: extra information
128*6777b538SAndroid Build Coastguard Worker * @str3: extra information
129*6777b538SAndroid Build Coastguard Worker *
130*6777b538SAndroid Build Coastguard Worker * Handle a validation error, provide contextual information
131*6777b538SAndroid Build Coastguard Worker */
132*6777b538SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidNode(xmlValidCtxtPtr ctxt,xmlNodePtr node,xmlParserErrors error,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)133*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(xmlValidCtxtPtr ctxt,
134*6777b538SAndroid Build Coastguard Worker xmlNodePtr node, xmlParserErrors error,
135*6777b538SAndroid Build Coastguard Worker const char *msg, const xmlChar * str1,
136*6777b538SAndroid Build Coastguard Worker const xmlChar * str2, const xmlChar * str3)
137*6777b538SAndroid Build Coastguard Worker {
138*6777b538SAndroid Build Coastguard Worker xmlDoErrValid(ctxt, node, error, XML_ERR_ERROR, str1, str2, str3, 0,
139*6777b538SAndroid Build Coastguard Worker msg, str1, str2, str3);
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
144*6777b538SAndroid Build Coastguard Worker /**
145*6777b538SAndroid Build Coastguard Worker * xmlErrValidNodeNr:
146*6777b538SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
147*6777b538SAndroid Build Coastguard Worker * @node: the node raising the error
148*6777b538SAndroid Build Coastguard Worker * @error: the error number
149*6777b538SAndroid Build Coastguard Worker * @str1: extra information
150*6777b538SAndroid Build Coastguard Worker * @int2: extra information
151*6777b538SAndroid Build Coastguard Worker * @str3: extra information
152*6777b538SAndroid Build Coastguard Worker *
153*6777b538SAndroid Build Coastguard Worker * Handle a validation error, provide contextual information
154*6777b538SAndroid Build Coastguard Worker */
155*6777b538SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,xmlNodePtr node,xmlParserErrors error,const char * msg,const xmlChar * str1,int int2,const xmlChar * str3)156*6777b538SAndroid Build Coastguard Worker xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,
157*6777b538SAndroid Build Coastguard Worker xmlNodePtr node, xmlParserErrors error,
158*6777b538SAndroid Build Coastguard Worker const char *msg, const xmlChar * str1,
159*6777b538SAndroid Build Coastguard Worker int int2, const xmlChar * str3)
160*6777b538SAndroid Build Coastguard Worker {
161*6777b538SAndroid Build Coastguard Worker xmlDoErrValid(ctxt, node, error, XML_ERR_ERROR, str1, str3, NULL, int2,
162*6777b538SAndroid Build Coastguard Worker msg, str1, int2, str3);
163*6777b538SAndroid Build Coastguard Worker }
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Worker /**
166*6777b538SAndroid Build Coastguard Worker * xmlErrValidWarning:
167*6777b538SAndroid Build Coastguard Worker * @ctxt: an XML validation parser context
168*6777b538SAndroid Build Coastguard Worker * @node: the node raising the error
169*6777b538SAndroid Build Coastguard Worker * @error: the error number
170*6777b538SAndroid Build Coastguard Worker * @str1: extra information
171*6777b538SAndroid Build Coastguard Worker * @str2: extra information
172*6777b538SAndroid Build Coastguard Worker * @str3: extra information
173*6777b538SAndroid Build Coastguard Worker *
174*6777b538SAndroid Build Coastguard Worker * Handle a validation error, provide contextual information
175*6777b538SAndroid Build Coastguard Worker */
176*6777b538SAndroid Build Coastguard Worker static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidWarning(xmlValidCtxtPtr ctxt,xmlNodePtr node,xmlParserErrors error,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)177*6777b538SAndroid Build Coastguard Worker xmlErrValidWarning(xmlValidCtxtPtr ctxt,
178*6777b538SAndroid Build Coastguard Worker xmlNodePtr node, xmlParserErrors error,
179*6777b538SAndroid Build Coastguard Worker const char *msg, const xmlChar * str1,
180*6777b538SAndroid Build Coastguard Worker const xmlChar * str2, const xmlChar * str3)
181*6777b538SAndroid Build Coastguard Worker {
182*6777b538SAndroid Build Coastguard Worker xmlDoErrValid(ctxt, node, error, XML_ERR_WARNING, str1, str2, str3, 0,
183*6777b538SAndroid Build Coastguard Worker msg, str1, str2, str3);
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
189*6777b538SAndroid Build Coastguard Worker /*
190*6777b538SAndroid Build Coastguard Worker * If regexp are enabled we can do continuous validation without the
191*6777b538SAndroid Build Coastguard Worker * need of a tree to validate the content model. this is done in each
192*6777b538SAndroid Build Coastguard Worker * callbacks.
193*6777b538SAndroid Build Coastguard Worker * Each xmlValidState represent the validation state associated to the
194*6777b538SAndroid Build Coastguard Worker * set of nodes currently open from the document root to the current element.
195*6777b538SAndroid Build Coastguard Worker */
196*6777b538SAndroid Build Coastguard Worker
197*6777b538SAndroid Build Coastguard Worker
198*6777b538SAndroid Build Coastguard Worker typedef struct _xmlValidState {
199*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl; /* pointer to the content model */
200*6777b538SAndroid Build Coastguard Worker xmlNodePtr node; /* pointer to the current node */
201*6777b538SAndroid Build Coastguard Worker xmlRegExecCtxtPtr exec; /* regexp runtime */
202*6777b538SAndroid Build Coastguard Worker } _xmlValidState;
203*6777b538SAndroid Build Coastguard Worker
204*6777b538SAndroid Build Coastguard Worker
205*6777b538SAndroid Build Coastguard Worker static int
vstateVPush(xmlValidCtxtPtr ctxt,xmlElementPtr elemDecl,xmlNodePtr node)206*6777b538SAndroid Build Coastguard Worker vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
207*6777b538SAndroid Build Coastguard Worker if ((ctxt->vstateMax == 0) || (ctxt->vstateTab == NULL)) {
208*6777b538SAndroid Build Coastguard Worker ctxt->vstateMax = 10;
209*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
210*6777b538SAndroid Build Coastguard Worker sizeof(ctxt->vstateTab[0]));
211*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateTab == NULL) {
212*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
213*6777b538SAndroid Build Coastguard Worker return(-1);
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker }
216*6777b538SAndroid Build Coastguard Worker
217*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateNr >= ctxt->vstateMax) {
218*6777b538SAndroid Build Coastguard Worker xmlValidState *tmp;
219*6777b538SAndroid Build Coastguard Worker
220*6777b538SAndroid Build Coastguard Worker tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
221*6777b538SAndroid Build Coastguard Worker 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
222*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
223*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
224*6777b538SAndroid Build Coastguard Worker return(-1);
225*6777b538SAndroid Build Coastguard Worker }
226*6777b538SAndroid Build Coastguard Worker ctxt->vstateMax *= 2;
227*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab = tmp;
228*6777b538SAndroid Build Coastguard Worker }
229*6777b538SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr];
230*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl;
231*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].node = node;
232*6777b538SAndroid Build Coastguard Worker if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
233*6777b538SAndroid Build Coastguard Worker if (elemDecl->contModel == NULL)
234*6777b538SAndroid Build Coastguard Worker xmlValidBuildContentModel(ctxt, elemDecl);
235*6777b538SAndroid Build Coastguard Worker if (elemDecl->contModel != NULL) {
236*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].exec =
237*6777b538SAndroid Build Coastguard Worker xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
238*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateTab[ctxt->vstateNr].exec == NULL) {
239*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
240*6777b538SAndroid Build Coastguard Worker return(-1);
241*6777b538SAndroid Build Coastguard Worker }
242*6777b538SAndroid Build Coastguard Worker } else {
243*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
244*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
245*6777b538SAndroid Build Coastguard Worker XML_ERR_INTERNAL_ERROR,
246*6777b538SAndroid Build Coastguard Worker "Failed to build content model regexp for %s\n",
247*6777b538SAndroid Build Coastguard Worker node->name, NULL, NULL);
248*6777b538SAndroid Build Coastguard Worker }
249*6777b538SAndroid Build Coastguard Worker }
250*6777b538SAndroid Build Coastguard Worker return(ctxt->vstateNr++);
251*6777b538SAndroid Build Coastguard Worker }
252*6777b538SAndroid Build Coastguard Worker
253*6777b538SAndroid Build Coastguard Worker static int
vstateVPop(xmlValidCtxtPtr ctxt)254*6777b538SAndroid Build Coastguard Worker vstateVPop(xmlValidCtxtPtr ctxt) {
255*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateNr < 1) return(-1);
258*6777b538SAndroid Build Coastguard Worker ctxt->vstateNr--;
259*6777b538SAndroid Build Coastguard Worker elemDecl = ctxt->vstateTab[ctxt->vstateNr].elemDecl;
260*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].elemDecl = NULL;
261*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].node = NULL;
262*6777b538SAndroid Build Coastguard Worker if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
263*6777b538SAndroid Build Coastguard Worker xmlRegFreeExecCtxt(ctxt->vstateTab[ctxt->vstateNr].exec);
264*6777b538SAndroid Build Coastguard Worker }
265*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
266*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateNr >= 1)
267*6777b538SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr - 1];
268*6777b538SAndroid Build Coastguard Worker else
269*6777b538SAndroid Build Coastguard Worker ctxt->vstate = NULL;
270*6777b538SAndroid Build Coastguard Worker return(ctxt->vstateNr);
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker #else /* not LIBXML_REGEXP_ENABLED */
274*6777b538SAndroid Build Coastguard Worker /*
275*6777b538SAndroid Build Coastguard Worker * If regexp are not enabled, it uses a home made algorithm less
276*6777b538SAndroid Build Coastguard Worker * complex and easier to
277*6777b538SAndroid Build Coastguard Worker * debug/maintain than a generic NFA -> DFA state based algo. The
278*6777b538SAndroid Build Coastguard Worker * only restriction is on the deepness of the tree limited by the
279*6777b538SAndroid Build Coastguard Worker * size of the occurs bitfield
280*6777b538SAndroid Build Coastguard Worker *
281*6777b538SAndroid Build Coastguard Worker * this is the content of a saved state for rollbacks
282*6777b538SAndroid Build Coastguard Worker */
283*6777b538SAndroid Build Coastguard Worker
284*6777b538SAndroid Build Coastguard Worker #define ROLLBACK_OR 0
285*6777b538SAndroid Build Coastguard Worker #define ROLLBACK_PARENT 1
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker typedef struct _xmlValidState {
288*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr cont; /* pointer to the content model subtree */
289*6777b538SAndroid Build Coastguard Worker xmlNodePtr node; /* pointer to the current node in the list */
290*6777b538SAndroid Build Coastguard Worker long occurs;/* bitfield for multiple occurrences */
291*6777b538SAndroid Build Coastguard Worker unsigned char depth; /* current depth in the overall tree */
292*6777b538SAndroid Build Coastguard Worker unsigned char state; /* ROLLBACK_XXX */
293*6777b538SAndroid Build Coastguard Worker } _xmlValidState;
294*6777b538SAndroid Build Coastguard Worker
295*6777b538SAndroid Build Coastguard Worker #define MAX_RECURSE 25000
296*6777b538SAndroid Build Coastguard Worker #define MAX_DEPTH ((sizeof(_xmlValidState.occurs)) * 8)
297*6777b538SAndroid Build Coastguard Worker #define CONT ctxt->vstate->cont
298*6777b538SAndroid Build Coastguard Worker #define NODE ctxt->vstate->node
299*6777b538SAndroid Build Coastguard Worker #define DEPTH ctxt->vstate->depth
300*6777b538SAndroid Build Coastguard Worker #define OCCURS ctxt->vstate->occurs
301*6777b538SAndroid Build Coastguard Worker #define STATE ctxt->vstate->state
302*6777b538SAndroid Build Coastguard Worker
303*6777b538SAndroid Build Coastguard Worker #define OCCURRENCE (ctxt->vstate->occurs & (1 << DEPTH))
304*6777b538SAndroid Build Coastguard Worker #define PARENT_OCCURRENCE (ctxt->vstate->occurs & ((1 << DEPTH) - 1))
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker #define SET_OCCURRENCE ctxt->vstate->occurs |= (1 << DEPTH)
307*6777b538SAndroid Build Coastguard Worker #define RESET_OCCURRENCE ctxt->vstate->occurs &= ((1 << DEPTH) - 1)
308*6777b538SAndroid Build Coastguard Worker
309*6777b538SAndroid Build Coastguard Worker static int
vstateVPush(xmlValidCtxtPtr ctxt,xmlElementContentPtr cont,xmlNodePtr node,unsigned char depth,long occurs,unsigned char state)310*6777b538SAndroid Build Coastguard Worker vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont,
311*6777b538SAndroid Build Coastguard Worker xmlNodePtr node, unsigned char depth, long occurs,
312*6777b538SAndroid Build Coastguard Worker unsigned char state) {
313*6777b538SAndroid Build Coastguard Worker int i = ctxt->vstateNr - 1;
314*6777b538SAndroid Build Coastguard Worker
315*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateNr > MAX_RECURSE) {
316*6777b538SAndroid Build Coastguard Worker return(-1);
317*6777b538SAndroid Build Coastguard Worker }
318*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateTab == NULL) {
319*6777b538SAndroid Build Coastguard Worker ctxt->vstateMax = 8;
320*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab = (xmlValidState *) xmlMalloc(
321*6777b538SAndroid Build Coastguard Worker ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
322*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateTab == NULL) {
323*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
324*6777b538SAndroid Build Coastguard Worker return(-1);
325*6777b538SAndroid Build Coastguard Worker }
326*6777b538SAndroid Build Coastguard Worker }
327*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateNr >= ctxt->vstateMax) {
328*6777b538SAndroid Build Coastguard Worker xmlValidState *tmp;
329*6777b538SAndroid Build Coastguard Worker
330*6777b538SAndroid Build Coastguard Worker tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
331*6777b538SAndroid Build Coastguard Worker 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
332*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
333*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
334*6777b538SAndroid Build Coastguard Worker return(-1);
335*6777b538SAndroid Build Coastguard Worker }
336*6777b538SAndroid Build Coastguard Worker ctxt->vstateMax *= 2;
337*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab = tmp;
338*6777b538SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[0];
339*6777b538SAndroid Build Coastguard Worker }
340*6777b538SAndroid Build Coastguard Worker /*
341*6777b538SAndroid Build Coastguard Worker * Don't push on the stack a state already here
342*6777b538SAndroid Build Coastguard Worker */
343*6777b538SAndroid Build Coastguard Worker if ((i >= 0) && (ctxt->vstateTab[i].cont == cont) &&
344*6777b538SAndroid Build Coastguard Worker (ctxt->vstateTab[i].node == node) &&
345*6777b538SAndroid Build Coastguard Worker (ctxt->vstateTab[i].depth == depth) &&
346*6777b538SAndroid Build Coastguard Worker (ctxt->vstateTab[i].occurs == occurs) &&
347*6777b538SAndroid Build Coastguard Worker (ctxt->vstateTab[i].state == state))
348*6777b538SAndroid Build Coastguard Worker return(ctxt->vstateNr);
349*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].cont = cont;
350*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].node = node;
351*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].depth = depth;
352*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].occurs = occurs;
353*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab[ctxt->vstateNr].state = state;
354*6777b538SAndroid Build Coastguard Worker return(ctxt->vstateNr++);
355*6777b538SAndroid Build Coastguard Worker }
356*6777b538SAndroid Build Coastguard Worker
357*6777b538SAndroid Build Coastguard Worker static int
vstateVPop(xmlValidCtxtPtr ctxt)358*6777b538SAndroid Build Coastguard Worker vstateVPop(xmlValidCtxtPtr ctxt) {
359*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateNr <= 1) return(-1);
360*6777b538SAndroid Build Coastguard Worker ctxt->vstateNr--;
361*6777b538SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[0];
362*6777b538SAndroid Build Coastguard Worker ctxt->vstate->cont = ctxt->vstateTab[ctxt->vstateNr].cont;
363*6777b538SAndroid Build Coastguard Worker ctxt->vstate->node = ctxt->vstateTab[ctxt->vstateNr].node;
364*6777b538SAndroid Build Coastguard Worker ctxt->vstate->depth = ctxt->vstateTab[ctxt->vstateNr].depth;
365*6777b538SAndroid Build Coastguard Worker ctxt->vstate->occurs = ctxt->vstateTab[ctxt->vstateNr].occurs;
366*6777b538SAndroid Build Coastguard Worker ctxt->vstate->state = ctxt->vstateTab[ctxt->vstateNr].state;
367*6777b538SAndroid Build Coastguard Worker return(ctxt->vstateNr);
368*6777b538SAndroid Build Coastguard Worker }
369*6777b538SAndroid Build Coastguard Worker
370*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
371*6777b538SAndroid Build Coastguard Worker
372*6777b538SAndroid Build Coastguard Worker static int
nodeVPush(xmlValidCtxtPtr ctxt,xmlNodePtr value)373*6777b538SAndroid Build Coastguard Worker nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value)
374*6777b538SAndroid Build Coastguard Worker {
375*6777b538SAndroid Build Coastguard Worker if (ctxt->nodeMax <= 0) {
376*6777b538SAndroid Build Coastguard Worker ctxt->nodeMax = 4;
377*6777b538SAndroid Build Coastguard Worker ctxt->nodeTab =
378*6777b538SAndroid Build Coastguard Worker (xmlNodePtr *) xmlMalloc(ctxt->nodeMax *
379*6777b538SAndroid Build Coastguard Worker sizeof(ctxt->nodeTab[0]));
380*6777b538SAndroid Build Coastguard Worker if (ctxt->nodeTab == NULL) {
381*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
382*6777b538SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
383*6777b538SAndroid Build Coastguard Worker return (0);
384*6777b538SAndroid Build Coastguard Worker }
385*6777b538SAndroid Build Coastguard Worker }
386*6777b538SAndroid Build Coastguard Worker if (ctxt->nodeNr >= ctxt->nodeMax) {
387*6777b538SAndroid Build Coastguard Worker xmlNodePtr *tmp;
388*6777b538SAndroid Build Coastguard Worker tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
389*6777b538SAndroid Build Coastguard Worker ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0]));
390*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
391*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
392*6777b538SAndroid Build Coastguard Worker return (0);
393*6777b538SAndroid Build Coastguard Worker }
394*6777b538SAndroid Build Coastguard Worker ctxt->nodeMax *= 2;
395*6777b538SAndroid Build Coastguard Worker ctxt->nodeTab = tmp;
396*6777b538SAndroid Build Coastguard Worker }
397*6777b538SAndroid Build Coastguard Worker ctxt->nodeTab[ctxt->nodeNr] = value;
398*6777b538SAndroid Build Coastguard Worker ctxt->node = value;
399*6777b538SAndroid Build Coastguard Worker return (ctxt->nodeNr++);
400*6777b538SAndroid Build Coastguard Worker }
401*6777b538SAndroid Build Coastguard Worker static xmlNodePtr
nodeVPop(xmlValidCtxtPtr ctxt)402*6777b538SAndroid Build Coastguard Worker nodeVPop(xmlValidCtxtPtr ctxt)
403*6777b538SAndroid Build Coastguard Worker {
404*6777b538SAndroid Build Coastguard Worker xmlNodePtr ret;
405*6777b538SAndroid Build Coastguard Worker
406*6777b538SAndroid Build Coastguard Worker if (ctxt->nodeNr <= 0)
407*6777b538SAndroid Build Coastguard Worker return (NULL);
408*6777b538SAndroid Build Coastguard Worker ctxt->nodeNr--;
409*6777b538SAndroid Build Coastguard Worker if (ctxt->nodeNr > 0)
410*6777b538SAndroid Build Coastguard Worker ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
411*6777b538SAndroid Build Coastguard Worker else
412*6777b538SAndroid Build Coastguard Worker ctxt->node = NULL;
413*6777b538SAndroid Build Coastguard Worker ret = ctxt->nodeTab[ctxt->nodeNr];
414*6777b538SAndroid Build Coastguard Worker ctxt->nodeTab[ctxt->nodeNr] = NULL;
415*6777b538SAndroid Build Coastguard Worker return (ret);
416*6777b538SAndroid Build Coastguard Worker }
417*6777b538SAndroid Build Coastguard Worker
418*6777b538SAndroid Build Coastguard Worker /* TODO: use hash table for accesses to elem and attribute definitions */
419*6777b538SAndroid Build Coastguard Worker
420*6777b538SAndroid Build Coastguard Worker
421*6777b538SAndroid Build Coastguard Worker #define CHECK_DTD \
422*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(0); \
423*6777b538SAndroid Build Coastguard Worker else if ((doc->intSubset == NULL) && \
424*6777b538SAndroid Build Coastguard Worker (doc->extSubset == NULL)) return(0)
425*6777b538SAndroid Build Coastguard Worker
426*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
427*6777b538SAndroid Build Coastguard Worker
428*6777b538SAndroid Build Coastguard Worker /************************************************************************
429*6777b538SAndroid Build Coastguard Worker * *
430*6777b538SAndroid Build Coastguard Worker * Content model validation based on the regexps *
431*6777b538SAndroid Build Coastguard Worker * *
432*6777b538SAndroid Build Coastguard Worker ************************************************************************/
433*6777b538SAndroid Build Coastguard Worker
434*6777b538SAndroid Build Coastguard Worker /**
435*6777b538SAndroid Build Coastguard Worker * xmlValidBuildAContentModel:
436*6777b538SAndroid Build Coastguard Worker * @content: the content model
437*6777b538SAndroid Build Coastguard Worker * @ctxt: the schema parser context
438*6777b538SAndroid Build Coastguard Worker * @name: the element name whose content is being built
439*6777b538SAndroid Build Coastguard Worker *
440*6777b538SAndroid Build Coastguard Worker * Generate the automata sequence needed for that type
441*6777b538SAndroid Build Coastguard Worker *
442*6777b538SAndroid Build Coastguard Worker * Returns 1 if successful or 0 in case of error.
443*6777b538SAndroid Build Coastguard Worker */
444*6777b538SAndroid Build Coastguard Worker static int
xmlValidBuildAContentModel(xmlElementContentPtr content,xmlValidCtxtPtr ctxt,const xmlChar * name)445*6777b538SAndroid Build Coastguard Worker xmlValidBuildAContentModel(xmlElementContentPtr content,
446*6777b538SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt,
447*6777b538SAndroid Build Coastguard Worker const xmlChar *name) {
448*6777b538SAndroid Build Coastguard Worker if (content == NULL) {
449*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
450*6777b538SAndroid Build Coastguard Worker "Found NULL content in content model of %s\n",
451*6777b538SAndroid Build Coastguard Worker name, NULL, NULL);
452*6777b538SAndroid Build Coastguard Worker return(0);
453*6777b538SAndroid Build Coastguard Worker }
454*6777b538SAndroid Build Coastguard Worker switch (content->type) {
455*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
456*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR,
457*6777b538SAndroid Build Coastguard Worker "Found PCDATA in content model of %s\n",
458*6777b538SAndroid Build Coastguard Worker name, NULL, NULL);
459*6777b538SAndroid Build Coastguard Worker return(0);
460*6777b538SAndroid Build Coastguard Worker break;
461*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT: {
462*6777b538SAndroid Build Coastguard Worker xmlAutomataStatePtr oldstate = ctxt->state;
463*6777b538SAndroid Build Coastguard Worker xmlChar fn[50];
464*6777b538SAndroid Build Coastguard Worker xmlChar *fullname;
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker fullname = xmlBuildQName(content->name, content->prefix, fn, 50);
467*6777b538SAndroid Build Coastguard Worker if (fullname == NULL) {
468*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
469*6777b538SAndroid Build Coastguard Worker return(0);
470*6777b538SAndroid Build Coastguard Worker }
471*6777b538SAndroid Build Coastguard Worker
472*6777b538SAndroid Build Coastguard Worker switch (content->ocur) {
473*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
474*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewTransition(ctxt->am,
475*6777b538SAndroid Build Coastguard Worker ctxt->state, NULL, fullname, NULL);
476*6777b538SAndroid Build Coastguard Worker break;
477*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
478*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewTransition(ctxt->am,
479*6777b538SAndroid Build Coastguard Worker ctxt->state, NULL, fullname, NULL);
480*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
481*6777b538SAndroid Build Coastguard Worker break;
482*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
483*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewTransition(ctxt->am,
484*6777b538SAndroid Build Coastguard Worker ctxt->state, NULL, fullname, NULL);
485*6777b538SAndroid Build Coastguard Worker xmlAutomataNewTransition(ctxt->am, ctxt->state,
486*6777b538SAndroid Build Coastguard Worker ctxt->state, fullname, NULL);
487*6777b538SAndroid Build Coastguard Worker break;
488*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
489*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
490*6777b538SAndroid Build Coastguard Worker ctxt->state, NULL);
491*6777b538SAndroid Build Coastguard Worker xmlAutomataNewTransition(ctxt->am,
492*6777b538SAndroid Build Coastguard Worker ctxt->state, ctxt->state, fullname, NULL);
493*6777b538SAndroid Build Coastguard Worker break;
494*6777b538SAndroid Build Coastguard Worker }
495*6777b538SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != content->name))
496*6777b538SAndroid Build Coastguard Worker xmlFree(fullname);
497*6777b538SAndroid Build Coastguard Worker break;
498*6777b538SAndroid Build Coastguard Worker }
499*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ: {
500*6777b538SAndroid Build Coastguard Worker xmlAutomataStatePtr oldstate, oldend;
501*6777b538SAndroid Build Coastguard Worker xmlElementContentOccur ocur;
502*6777b538SAndroid Build Coastguard Worker
503*6777b538SAndroid Build Coastguard Worker /*
504*6777b538SAndroid Build Coastguard Worker * Simply iterate over the content
505*6777b538SAndroid Build Coastguard Worker */
506*6777b538SAndroid Build Coastguard Worker oldstate = ctxt->state;
507*6777b538SAndroid Build Coastguard Worker ocur = content->ocur;
508*6777b538SAndroid Build Coastguard Worker if (ocur != XML_ELEMENT_CONTENT_ONCE) {
509*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
510*6777b538SAndroid Build Coastguard Worker oldstate = ctxt->state;
511*6777b538SAndroid Build Coastguard Worker }
512*6777b538SAndroid Build Coastguard Worker do {
513*6777b538SAndroid Build Coastguard Worker xmlValidBuildAContentModel(content->c1, ctxt, name);
514*6777b538SAndroid Build Coastguard Worker content = content->c2;
515*6777b538SAndroid Build Coastguard Worker } while ((content->type == XML_ELEMENT_CONTENT_SEQ) &&
516*6777b538SAndroid Build Coastguard Worker (content->ocur == XML_ELEMENT_CONTENT_ONCE));
517*6777b538SAndroid Build Coastguard Worker xmlValidBuildAContentModel(content, ctxt, name);
518*6777b538SAndroid Build Coastguard Worker oldend = ctxt->state;
519*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
520*6777b538SAndroid Build Coastguard Worker switch (ocur) {
521*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
522*6777b538SAndroid Build Coastguard Worker break;
523*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
524*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
525*6777b538SAndroid Build Coastguard Worker break;
526*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
527*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
528*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
529*6777b538SAndroid Build Coastguard Worker break;
530*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
531*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
532*6777b538SAndroid Build Coastguard Worker break;
533*6777b538SAndroid Build Coastguard Worker }
534*6777b538SAndroid Build Coastguard Worker break;
535*6777b538SAndroid Build Coastguard Worker }
536*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR: {
537*6777b538SAndroid Build Coastguard Worker xmlAutomataStatePtr oldstate, oldend;
538*6777b538SAndroid Build Coastguard Worker xmlElementContentOccur ocur;
539*6777b538SAndroid Build Coastguard Worker
540*6777b538SAndroid Build Coastguard Worker ocur = content->ocur;
541*6777b538SAndroid Build Coastguard Worker if ((ocur == XML_ELEMENT_CONTENT_PLUS) ||
542*6777b538SAndroid Build Coastguard Worker (ocur == XML_ELEMENT_CONTENT_MULT)) {
543*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
544*6777b538SAndroid Build Coastguard Worker ctxt->state, NULL);
545*6777b538SAndroid Build Coastguard Worker }
546*6777b538SAndroid Build Coastguard Worker oldstate = ctxt->state;
547*6777b538SAndroid Build Coastguard Worker oldend = xmlAutomataNewState(ctxt->am);
548*6777b538SAndroid Build Coastguard Worker
549*6777b538SAndroid Build Coastguard Worker /*
550*6777b538SAndroid Build Coastguard Worker * iterate over the subtypes and remerge the end with an
551*6777b538SAndroid Build Coastguard Worker * epsilon transition
552*6777b538SAndroid Build Coastguard Worker */
553*6777b538SAndroid Build Coastguard Worker do {
554*6777b538SAndroid Build Coastguard Worker ctxt->state = oldstate;
555*6777b538SAndroid Build Coastguard Worker xmlValidBuildAContentModel(content->c1, ctxt, name);
556*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
557*6777b538SAndroid Build Coastguard Worker content = content->c2;
558*6777b538SAndroid Build Coastguard Worker } while ((content->type == XML_ELEMENT_CONTENT_OR) &&
559*6777b538SAndroid Build Coastguard Worker (content->ocur == XML_ELEMENT_CONTENT_ONCE));
560*6777b538SAndroid Build Coastguard Worker ctxt->state = oldstate;
561*6777b538SAndroid Build Coastguard Worker xmlValidBuildAContentModel(content, ctxt, name);
562*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend);
563*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL);
564*6777b538SAndroid Build Coastguard Worker switch (ocur) {
565*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
566*6777b538SAndroid Build Coastguard Worker break;
567*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
568*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
569*6777b538SAndroid Build Coastguard Worker break;
570*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
571*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
572*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
573*6777b538SAndroid Build Coastguard Worker break;
574*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
575*6777b538SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate);
576*6777b538SAndroid Build Coastguard Worker break;
577*6777b538SAndroid Build Coastguard Worker }
578*6777b538SAndroid Build Coastguard Worker break;
579*6777b538SAndroid Build Coastguard Worker }
580*6777b538SAndroid Build Coastguard Worker default:
581*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
582*6777b538SAndroid Build Coastguard Worker "ContentModel broken for element %s\n",
583*6777b538SAndroid Build Coastguard Worker (const char *) name);
584*6777b538SAndroid Build Coastguard Worker return(0);
585*6777b538SAndroid Build Coastguard Worker }
586*6777b538SAndroid Build Coastguard Worker return(1);
587*6777b538SAndroid Build Coastguard Worker }
588*6777b538SAndroid Build Coastguard Worker /**
589*6777b538SAndroid Build Coastguard Worker * xmlValidBuildContentModel:
590*6777b538SAndroid Build Coastguard Worker * @ctxt: a validation context
591*6777b538SAndroid Build Coastguard Worker * @elem: an element declaration node
592*6777b538SAndroid Build Coastguard Worker *
593*6777b538SAndroid Build Coastguard Worker * (Re)Build the automata associated to the content model of this
594*6777b538SAndroid Build Coastguard Worker * element
595*6777b538SAndroid Build Coastguard Worker *
596*6777b538SAndroid Build Coastguard Worker * Returns 1 in case of success, 0 in case of error
597*6777b538SAndroid Build Coastguard Worker */
598*6777b538SAndroid Build Coastguard Worker int
xmlValidBuildContentModel(xmlValidCtxtPtr ctxt,xmlElementPtr elem)599*6777b538SAndroid Build Coastguard Worker xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
600*6777b538SAndroid Build Coastguard Worker int ret = 0;
601*6777b538SAndroid Build Coastguard Worker
602*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (elem == NULL))
603*6777b538SAndroid Build Coastguard Worker return(0);
604*6777b538SAndroid Build Coastguard Worker if (elem->type != XML_ELEMENT_DECL)
605*6777b538SAndroid Build Coastguard Worker return(0);
606*6777b538SAndroid Build Coastguard Worker if (elem->etype != XML_ELEMENT_TYPE_ELEMENT)
607*6777b538SAndroid Build Coastguard Worker return(1);
608*6777b538SAndroid Build Coastguard Worker /* TODO: should we rebuild in this case ? */
609*6777b538SAndroid Build Coastguard Worker if (elem->contModel != NULL) {
610*6777b538SAndroid Build Coastguard Worker if (!xmlRegexpIsDeterminist(elem->contModel)) {
611*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
612*6777b538SAndroid Build Coastguard Worker return(0);
613*6777b538SAndroid Build Coastguard Worker }
614*6777b538SAndroid Build Coastguard Worker return(1);
615*6777b538SAndroid Build Coastguard Worker }
616*6777b538SAndroid Build Coastguard Worker
617*6777b538SAndroid Build Coastguard Worker ctxt->am = xmlNewAutomata();
618*6777b538SAndroid Build Coastguard Worker if (ctxt->am == NULL) {
619*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
620*6777b538SAndroid Build Coastguard Worker return(0);
621*6777b538SAndroid Build Coastguard Worker }
622*6777b538SAndroid Build Coastguard Worker ctxt->state = xmlAutomataGetInitState(ctxt->am);
623*6777b538SAndroid Build Coastguard Worker xmlValidBuildAContentModel(elem->content, ctxt, elem->name);
624*6777b538SAndroid Build Coastguard Worker xmlAutomataSetFinalState(ctxt->am, ctxt->state);
625*6777b538SAndroid Build Coastguard Worker elem->contModel = xmlAutomataCompile(ctxt->am);
626*6777b538SAndroid Build Coastguard Worker if (elem->contModel == NULL) {
627*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
628*6777b538SAndroid Build Coastguard Worker goto done;
629*6777b538SAndroid Build Coastguard Worker }
630*6777b538SAndroid Build Coastguard Worker if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
631*6777b538SAndroid Build Coastguard Worker char expr[5000];
632*6777b538SAndroid Build Coastguard Worker expr[0] = 0;
633*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(expr, 5000, elem->content, 1);
634*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem,
635*6777b538SAndroid Build Coastguard Worker XML_DTD_CONTENT_NOT_DETERMINIST,
636*6777b538SAndroid Build Coastguard Worker "Content model of %s is not deterministic: %s\n",
637*6777b538SAndroid Build Coastguard Worker elem->name, BAD_CAST expr, NULL);
638*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
639*6777b538SAndroid Build Coastguard Worker goto done;
640*6777b538SAndroid Build Coastguard Worker }
641*6777b538SAndroid Build Coastguard Worker
642*6777b538SAndroid Build Coastguard Worker ret = 1;
643*6777b538SAndroid Build Coastguard Worker
644*6777b538SAndroid Build Coastguard Worker done:
645*6777b538SAndroid Build Coastguard Worker ctxt->state = NULL;
646*6777b538SAndroid Build Coastguard Worker xmlFreeAutomata(ctxt->am);
647*6777b538SAndroid Build Coastguard Worker ctxt->am = NULL;
648*6777b538SAndroid Build Coastguard Worker return(ret);
649*6777b538SAndroid Build Coastguard Worker }
650*6777b538SAndroid Build Coastguard Worker
651*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
652*6777b538SAndroid Build Coastguard Worker
653*6777b538SAndroid Build Coastguard Worker /****************************************************************
654*6777b538SAndroid Build Coastguard Worker * *
655*6777b538SAndroid Build Coastguard Worker * Util functions for data allocation/deallocation *
656*6777b538SAndroid Build Coastguard Worker * *
657*6777b538SAndroid Build Coastguard Worker ****************************************************************/
658*6777b538SAndroid Build Coastguard Worker
659*6777b538SAndroid Build Coastguard Worker /**
660*6777b538SAndroid Build Coastguard Worker * xmlNewValidCtxt:
661*6777b538SAndroid Build Coastguard Worker *
662*6777b538SAndroid Build Coastguard Worker * Allocate a validation context structure.
663*6777b538SAndroid Build Coastguard Worker *
664*6777b538SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new validation context structure
665*6777b538SAndroid Build Coastguard Worker */
xmlNewValidCtxt(void)666*6777b538SAndroid Build Coastguard Worker xmlValidCtxtPtr xmlNewValidCtxt(void) {
667*6777b538SAndroid Build Coastguard Worker xmlValidCtxtPtr ret;
668*6777b538SAndroid Build Coastguard Worker
669*6777b538SAndroid Build Coastguard Worker if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL)
670*6777b538SAndroid Build Coastguard Worker return (NULL);
671*6777b538SAndroid Build Coastguard Worker
672*6777b538SAndroid Build Coastguard Worker (void) memset(ret, 0, sizeof (xmlValidCtxt));
673*6777b538SAndroid Build Coastguard Worker
674*6777b538SAndroid Build Coastguard Worker return (ret);
675*6777b538SAndroid Build Coastguard Worker }
676*6777b538SAndroid Build Coastguard Worker
677*6777b538SAndroid Build Coastguard Worker /**
678*6777b538SAndroid Build Coastguard Worker * xmlFreeValidCtxt:
679*6777b538SAndroid Build Coastguard Worker * @cur: the validation context to free
680*6777b538SAndroid Build Coastguard Worker *
681*6777b538SAndroid Build Coastguard Worker * Free a validation context structure.
682*6777b538SAndroid Build Coastguard Worker */
683*6777b538SAndroid Build Coastguard Worker void
xmlFreeValidCtxt(xmlValidCtxtPtr cur)684*6777b538SAndroid Build Coastguard Worker xmlFreeValidCtxt(xmlValidCtxtPtr cur) {
685*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
686*6777b538SAndroid Build Coastguard Worker return;
687*6777b538SAndroid Build Coastguard Worker if (cur->vstateTab != NULL)
688*6777b538SAndroid Build Coastguard Worker xmlFree(cur->vstateTab);
689*6777b538SAndroid Build Coastguard Worker if (cur->nodeTab != NULL)
690*6777b538SAndroid Build Coastguard Worker xmlFree(cur->nodeTab);
691*6777b538SAndroid Build Coastguard Worker xmlFree(cur);
692*6777b538SAndroid Build Coastguard Worker }
693*6777b538SAndroid Build Coastguard Worker
694*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
695*6777b538SAndroid Build Coastguard Worker
696*6777b538SAndroid Build Coastguard Worker /**
697*6777b538SAndroid Build Coastguard Worker * xmlNewDocElementContent:
698*6777b538SAndroid Build Coastguard Worker * @doc: the document
699*6777b538SAndroid Build Coastguard Worker * @name: the subelement name or NULL
700*6777b538SAndroid Build Coastguard Worker * @type: the type of element content decl
701*6777b538SAndroid Build Coastguard Worker *
702*6777b538SAndroid Build Coastguard Worker * Allocate an element content structure for the document.
703*6777b538SAndroid Build Coastguard Worker *
704*6777b538SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new element content structure
705*6777b538SAndroid Build Coastguard Worker */
706*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr
xmlNewDocElementContent(xmlDocPtr doc,const xmlChar * name,xmlElementContentType type)707*6777b538SAndroid Build Coastguard Worker xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name,
708*6777b538SAndroid Build Coastguard Worker xmlElementContentType type) {
709*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr ret;
710*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
711*6777b538SAndroid Build Coastguard Worker
712*6777b538SAndroid Build Coastguard Worker if (doc != NULL)
713*6777b538SAndroid Build Coastguard Worker dict = doc->dict;
714*6777b538SAndroid Build Coastguard Worker
715*6777b538SAndroid Build Coastguard Worker switch(type) {
716*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
717*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
718*6777b538SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
719*6777b538SAndroid Build Coastguard Worker "xmlNewElementContent : name == NULL !\n",
720*6777b538SAndroid Build Coastguard Worker NULL);
721*6777b538SAndroid Build Coastguard Worker }
722*6777b538SAndroid Build Coastguard Worker break;
723*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
724*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
725*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
726*6777b538SAndroid Build Coastguard Worker if (name != NULL) {
727*6777b538SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
728*6777b538SAndroid Build Coastguard Worker "xmlNewElementContent : name != NULL !\n",
729*6777b538SAndroid Build Coastguard Worker NULL);
730*6777b538SAndroid Build Coastguard Worker }
731*6777b538SAndroid Build Coastguard Worker break;
732*6777b538SAndroid Build Coastguard Worker default:
733*6777b538SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
734*6777b538SAndroid Build Coastguard Worker "Internal: ELEMENT content corrupted invalid type\n",
735*6777b538SAndroid Build Coastguard Worker NULL);
736*6777b538SAndroid Build Coastguard Worker return(NULL);
737*6777b538SAndroid Build Coastguard Worker }
738*6777b538SAndroid Build Coastguard Worker ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
739*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
740*6777b538SAndroid Build Coastguard Worker return(NULL);
741*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlElementContent));
742*6777b538SAndroid Build Coastguard Worker ret->type = type;
743*6777b538SAndroid Build Coastguard Worker ret->ocur = XML_ELEMENT_CONTENT_ONCE;
744*6777b538SAndroid Build Coastguard Worker if (name != NULL) {
745*6777b538SAndroid Build Coastguard Worker int l;
746*6777b538SAndroid Build Coastguard Worker const xmlChar *tmp;
747*6777b538SAndroid Build Coastguard Worker
748*6777b538SAndroid Build Coastguard Worker tmp = xmlSplitQName3(name, &l);
749*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
750*6777b538SAndroid Build Coastguard Worker if (dict == NULL)
751*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(name);
752*6777b538SAndroid Build Coastguard Worker else
753*6777b538SAndroid Build Coastguard Worker ret->name = xmlDictLookup(dict, name, -1);
754*6777b538SAndroid Build Coastguard Worker } else {
755*6777b538SAndroid Build Coastguard Worker if (dict == NULL) {
756*6777b538SAndroid Build Coastguard Worker ret->prefix = xmlStrndup(name, l);
757*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(tmp);
758*6777b538SAndroid Build Coastguard Worker } else {
759*6777b538SAndroid Build Coastguard Worker ret->prefix = xmlDictLookup(dict, name, l);
760*6777b538SAndroid Build Coastguard Worker ret->name = xmlDictLookup(dict, tmp, -1);
761*6777b538SAndroid Build Coastguard Worker }
762*6777b538SAndroid Build Coastguard Worker if (ret->prefix == NULL)
763*6777b538SAndroid Build Coastguard Worker goto error;
764*6777b538SAndroid Build Coastguard Worker }
765*6777b538SAndroid Build Coastguard Worker if (ret->name == NULL)
766*6777b538SAndroid Build Coastguard Worker goto error;
767*6777b538SAndroid Build Coastguard Worker }
768*6777b538SAndroid Build Coastguard Worker return(ret);
769*6777b538SAndroid Build Coastguard Worker
770*6777b538SAndroid Build Coastguard Worker error:
771*6777b538SAndroid Build Coastguard Worker xmlFreeDocElementContent(doc, ret);
772*6777b538SAndroid Build Coastguard Worker return(NULL);
773*6777b538SAndroid Build Coastguard Worker }
774*6777b538SAndroid Build Coastguard Worker
775*6777b538SAndroid Build Coastguard Worker /**
776*6777b538SAndroid Build Coastguard Worker * xmlNewElementContent:
777*6777b538SAndroid Build Coastguard Worker * @name: the subelement name or NULL
778*6777b538SAndroid Build Coastguard Worker * @type: the type of element content decl
779*6777b538SAndroid Build Coastguard Worker *
780*6777b538SAndroid Build Coastguard Worker * Allocate an element content structure.
781*6777b538SAndroid Build Coastguard Worker * Deprecated in favor of xmlNewDocElementContent
782*6777b538SAndroid Build Coastguard Worker *
783*6777b538SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new element content structure
784*6777b538SAndroid Build Coastguard Worker */
785*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr
xmlNewElementContent(const xmlChar * name,xmlElementContentType type)786*6777b538SAndroid Build Coastguard Worker xmlNewElementContent(const xmlChar *name, xmlElementContentType type) {
787*6777b538SAndroid Build Coastguard Worker return(xmlNewDocElementContent(NULL, name, type));
788*6777b538SAndroid Build Coastguard Worker }
789*6777b538SAndroid Build Coastguard Worker
790*6777b538SAndroid Build Coastguard Worker /**
791*6777b538SAndroid Build Coastguard Worker * xmlCopyDocElementContent:
792*6777b538SAndroid Build Coastguard Worker * @doc: the document owning the element declaration
793*6777b538SAndroid Build Coastguard Worker * @cur: An element content pointer.
794*6777b538SAndroid Build Coastguard Worker *
795*6777b538SAndroid Build Coastguard Worker * Build a copy of an element content description.
796*6777b538SAndroid Build Coastguard Worker *
797*6777b538SAndroid Build Coastguard Worker * Returns the new xmlElementContentPtr or NULL in case of error.
798*6777b538SAndroid Build Coastguard Worker */
799*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr
xmlCopyDocElementContent(xmlDocPtr doc,xmlElementContentPtr cur)800*6777b538SAndroid Build Coastguard Worker xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
801*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr ret = NULL, prev = NULL, tmp;
802*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
803*6777b538SAndroid Build Coastguard Worker
804*6777b538SAndroid Build Coastguard Worker if (cur == NULL) return(NULL);
805*6777b538SAndroid Build Coastguard Worker
806*6777b538SAndroid Build Coastguard Worker if (doc != NULL)
807*6777b538SAndroid Build Coastguard Worker dict = doc->dict;
808*6777b538SAndroid Build Coastguard Worker
809*6777b538SAndroid Build Coastguard Worker ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
810*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
811*6777b538SAndroid Build Coastguard Worker return(NULL);
812*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlElementContent));
813*6777b538SAndroid Build Coastguard Worker ret->type = cur->type;
814*6777b538SAndroid Build Coastguard Worker ret->ocur = cur->ocur;
815*6777b538SAndroid Build Coastguard Worker if (cur->name != NULL) {
816*6777b538SAndroid Build Coastguard Worker if (dict)
817*6777b538SAndroid Build Coastguard Worker ret->name = xmlDictLookup(dict, cur->name, -1);
818*6777b538SAndroid Build Coastguard Worker else
819*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(cur->name);
820*6777b538SAndroid Build Coastguard Worker if (ret->name == NULL)
821*6777b538SAndroid Build Coastguard Worker goto error;
822*6777b538SAndroid Build Coastguard Worker }
823*6777b538SAndroid Build Coastguard Worker
824*6777b538SAndroid Build Coastguard Worker if (cur->prefix != NULL) {
825*6777b538SAndroid Build Coastguard Worker if (dict)
826*6777b538SAndroid Build Coastguard Worker ret->prefix = xmlDictLookup(dict, cur->prefix, -1);
827*6777b538SAndroid Build Coastguard Worker else
828*6777b538SAndroid Build Coastguard Worker ret->prefix = xmlStrdup(cur->prefix);
829*6777b538SAndroid Build Coastguard Worker if (ret->prefix == NULL)
830*6777b538SAndroid Build Coastguard Worker goto error;
831*6777b538SAndroid Build Coastguard Worker }
832*6777b538SAndroid Build Coastguard Worker if (cur->c1 != NULL) {
833*6777b538SAndroid Build Coastguard Worker ret->c1 = xmlCopyDocElementContent(doc, cur->c1);
834*6777b538SAndroid Build Coastguard Worker if (ret->c1 == NULL)
835*6777b538SAndroid Build Coastguard Worker goto error;
836*6777b538SAndroid Build Coastguard Worker ret->c1->parent = ret;
837*6777b538SAndroid Build Coastguard Worker }
838*6777b538SAndroid Build Coastguard Worker if (cur->c2 != NULL) {
839*6777b538SAndroid Build Coastguard Worker prev = ret;
840*6777b538SAndroid Build Coastguard Worker cur = cur->c2;
841*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
842*6777b538SAndroid Build Coastguard Worker tmp = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent));
843*6777b538SAndroid Build Coastguard Worker if (tmp == NULL)
844*6777b538SAndroid Build Coastguard Worker goto error;
845*6777b538SAndroid Build Coastguard Worker memset(tmp, 0, sizeof(xmlElementContent));
846*6777b538SAndroid Build Coastguard Worker tmp->type = cur->type;
847*6777b538SAndroid Build Coastguard Worker tmp->ocur = cur->ocur;
848*6777b538SAndroid Build Coastguard Worker prev->c2 = tmp;
849*6777b538SAndroid Build Coastguard Worker tmp->parent = prev;
850*6777b538SAndroid Build Coastguard Worker if (cur->name != NULL) {
851*6777b538SAndroid Build Coastguard Worker if (dict)
852*6777b538SAndroid Build Coastguard Worker tmp->name = xmlDictLookup(dict, cur->name, -1);
853*6777b538SAndroid Build Coastguard Worker else
854*6777b538SAndroid Build Coastguard Worker tmp->name = xmlStrdup(cur->name);
855*6777b538SAndroid Build Coastguard Worker if (tmp->name == NULL)
856*6777b538SAndroid Build Coastguard Worker goto error;
857*6777b538SAndroid Build Coastguard Worker }
858*6777b538SAndroid Build Coastguard Worker
859*6777b538SAndroid Build Coastguard Worker if (cur->prefix != NULL) {
860*6777b538SAndroid Build Coastguard Worker if (dict)
861*6777b538SAndroid Build Coastguard Worker tmp->prefix = xmlDictLookup(dict, cur->prefix, -1);
862*6777b538SAndroid Build Coastguard Worker else
863*6777b538SAndroid Build Coastguard Worker tmp->prefix = xmlStrdup(cur->prefix);
864*6777b538SAndroid Build Coastguard Worker if (tmp->prefix == NULL)
865*6777b538SAndroid Build Coastguard Worker goto error;
866*6777b538SAndroid Build Coastguard Worker }
867*6777b538SAndroid Build Coastguard Worker if (cur->c1 != NULL) {
868*6777b538SAndroid Build Coastguard Worker tmp->c1 = xmlCopyDocElementContent(doc,cur->c1);
869*6777b538SAndroid Build Coastguard Worker if (tmp->c1 == NULL)
870*6777b538SAndroid Build Coastguard Worker goto error;
871*6777b538SAndroid Build Coastguard Worker tmp->c1->parent = tmp;
872*6777b538SAndroid Build Coastguard Worker }
873*6777b538SAndroid Build Coastguard Worker prev = tmp;
874*6777b538SAndroid Build Coastguard Worker cur = cur->c2;
875*6777b538SAndroid Build Coastguard Worker }
876*6777b538SAndroid Build Coastguard Worker }
877*6777b538SAndroid Build Coastguard Worker return(ret);
878*6777b538SAndroid Build Coastguard Worker
879*6777b538SAndroid Build Coastguard Worker error:
880*6777b538SAndroid Build Coastguard Worker xmlFreeElementContent(ret);
881*6777b538SAndroid Build Coastguard Worker return(NULL);
882*6777b538SAndroid Build Coastguard Worker }
883*6777b538SAndroid Build Coastguard Worker
884*6777b538SAndroid Build Coastguard Worker /**
885*6777b538SAndroid Build Coastguard Worker * xmlCopyElementContent:
886*6777b538SAndroid Build Coastguard Worker * @cur: An element content pointer.
887*6777b538SAndroid Build Coastguard Worker *
888*6777b538SAndroid Build Coastguard Worker * Build a copy of an element content description.
889*6777b538SAndroid Build Coastguard Worker * Deprecated, use xmlCopyDocElementContent instead
890*6777b538SAndroid Build Coastguard Worker *
891*6777b538SAndroid Build Coastguard Worker * Returns the new xmlElementContentPtr or NULL in case of error.
892*6777b538SAndroid Build Coastguard Worker */
893*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr
xmlCopyElementContent(xmlElementContentPtr cur)894*6777b538SAndroid Build Coastguard Worker xmlCopyElementContent(xmlElementContentPtr cur) {
895*6777b538SAndroid Build Coastguard Worker return(xmlCopyDocElementContent(NULL, cur));
896*6777b538SAndroid Build Coastguard Worker }
897*6777b538SAndroid Build Coastguard Worker
898*6777b538SAndroid Build Coastguard Worker /**
899*6777b538SAndroid Build Coastguard Worker * xmlFreeDocElementContent:
900*6777b538SAndroid Build Coastguard Worker * @doc: the document owning the element declaration
901*6777b538SAndroid Build Coastguard Worker * @cur: the element content tree to free
902*6777b538SAndroid Build Coastguard Worker *
903*6777b538SAndroid Build Coastguard Worker * Free an element content structure. The whole subtree is removed.
904*6777b538SAndroid Build Coastguard Worker */
905*6777b538SAndroid Build Coastguard Worker void
xmlFreeDocElementContent(xmlDocPtr doc,xmlElementContentPtr cur)906*6777b538SAndroid Build Coastguard Worker xmlFreeDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) {
907*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
908*6777b538SAndroid Build Coastguard Worker size_t depth = 0;
909*6777b538SAndroid Build Coastguard Worker
910*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
911*6777b538SAndroid Build Coastguard Worker return;
912*6777b538SAndroid Build Coastguard Worker if (doc != NULL)
913*6777b538SAndroid Build Coastguard Worker dict = doc->dict;
914*6777b538SAndroid Build Coastguard Worker
915*6777b538SAndroid Build Coastguard Worker while (1) {
916*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr parent;
917*6777b538SAndroid Build Coastguard Worker
918*6777b538SAndroid Build Coastguard Worker while ((cur->c1 != NULL) || (cur->c2 != NULL)) {
919*6777b538SAndroid Build Coastguard Worker cur = (cur->c1 != NULL) ? cur->c1 : cur->c2;
920*6777b538SAndroid Build Coastguard Worker depth += 1;
921*6777b538SAndroid Build Coastguard Worker }
922*6777b538SAndroid Build Coastguard Worker
923*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
924*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
925*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
926*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
927*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
928*6777b538SAndroid Build Coastguard Worker break;
929*6777b538SAndroid Build Coastguard Worker default:
930*6777b538SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
931*6777b538SAndroid Build Coastguard Worker "Internal: ELEMENT content corrupted invalid type\n",
932*6777b538SAndroid Build Coastguard Worker NULL);
933*6777b538SAndroid Build Coastguard Worker return;
934*6777b538SAndroid Build Coastguard Worker }
935*6777b538SAndroid Build Coastguard Worker if (dict) {
936*6777b538SAndroid Build Coastguard Worker if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
937*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) cur->name);
938*6777b538SAndroid Build Coastguard Worker if ((cur->prefix != NULL) && (!xmlDictOwns(dict, cur->prefix)))
939*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) cur->prefix);
940*6777b538SAndroid Build Coastguard Worker } else {
941*6777b538SAndroid Build Coastguard Worker if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
942*6777b538SAndroid Build Coastguard Worker if (cur->prefix != NULL) xmlFree((xmlChar *) cur->prefix);
943*6777b538SAndroid Build Coastguard Worker }
944*6777b538SAndroid Build Coastguard Worker parent = cur->parent;
945*6777b538SAndroid Build Coastguard Worker if ((depth == 0) || (parent == NULL)) {
946*6777b538SAndroid Build Coastguard Worker xmlFree(cur);
947*6777b538SAndroid Build Coastguard Worker break;
948*6777b538SAndroid Build Coastguard Worker }
949*6777b538SAndroid Build Coastguard Worker if (cur == parent->c1)
950*6777b538SAndroid Build Coastguard Worker parent->c1 = NULL;
951*6777b538SAndroid Build Coastguard Worker else
952*6777b538SAndroid Build Coastguard Worker parent->c2 = NULL;
953*6777b538SAndroid Build Coastguard Worker xmlFree(cur);
954*6777b538SAndroid Build Coastguard Worker
955*6777b538SAndroid Build Coastguard Worker if (parent->c2 != NULL) {
956*6777b538SAndroid Build Coastguard Worker cur = parent->c2;
957*6777b538SAndroid Build Coastguard Worker } else {
958*6777b538SAndroid Build Coastguard Worker depth -= 1;
959*6777b538SAndroid Build Coastguard Worker cur = parent;
960*6777b538SAndroid Build Coastguard Worker }
961*6777b538SAndroid Build Coastguard Worker }
962*6777b538SAndroid Build Coastguard Worker }
963*6777b538SAndroid Build Coastguard Worker
964*6777b538SAndroid Build Coastguard Worker /**
965*6777b538SAndroid Build Coastguard Worker * xmlFreeElementContent:
966*6777b538SAndroid Build Coastguard Worker * @cur: the element content tree to free
967*6777b538SAndroid Build Coastguard Worker *
968*6777b538SAndroid Build Coastguard Worker * Free an element content structure. The whole subtree is removed.
969*6777b538SAndroid Build Coastguard Worker * Deprecated, use xmlFreeDocElementContent instead
970*6777b538SAndroid Build Coastguard Worker */
971*6777b538SAndroid Build Coastguard Worker void
xmlFreeElementContent(xmlElementContentPtr cur)972*6777b538SAndroid Build Coastguard Worker xmlFreeElementContent(xmlElementContentPtr cur) {
973*6777b538SAndroid Build Coastguard Worker xmlFreeDocElementContent(NULL, cur);
974*6777b538SAndroid Build Coastguard Worker }
975*6777b538SAndroid Build Coastguard Worker
976*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
977*6777b538SAndroid Build Coastguard Worker /**
978*6777b538SAndroid Build Coastguard Worker * xmlSprintfElementContent:
979*6777b538SAndroid Build Coastguard Worker * @buf: an output buffer
980*6777b538SAndroid Build Coastguard Worker * @content: An element table
981*6777b538SAndroid Build Coastguard Worker * @englob: 1 if one must print the englobing parenthesis, 0 otherwise
982*6777b538SAndroid Build Coastguard Worker *
983*6777b538SAndroid Build Coastguard Worker * Deprecated, unsafe, use xmlSnprintfElementContent
984*6777b538SAndroid Build Coastguard Worker */
985*6777b538SAndroid Build Coastguard Worker void
xmlSprintfElementContent(char * buf ATTRIBUTE_UNUSED,xmlElementContentPtr content ATTRIBUTE_UNUSED,int englob ATTRIBUTE_UNUSED)986*6777b538SAndroid Build Coastguard Worker xmlSprintfElementContent(char *buf ATTRIBUTE_UNUSED,
987*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr content ATTRIBUTE_UNUSED,
988*6777b538SAndroid Build Coastguard Worker int englob ATTRIBUTE_UNUSED) {
989*6777b538SAndroid Build Coastguard Worker }
990*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
991*6777b538SAndroid Build Coastguard Worker
992*6777b538SAndroid Build Coastguard Worker /**
993*6777b538SAndroid Build Coastguard Worker * xmlSnprintfElementContent:
994*6777b538SAndroid Build Coastguard Worker * @buf: an output buffer
995*6777b538SAndroid Build Coastguard Worker * @size: the buffer size
996*6777b538SAndroid Build Coastguard Worker * @content: An element table
997*6777b538SAndroid Build Coastguard Worker * @englob: 1 if one must print the englobing parenthesis, 0 otherwise
998*6777b538SAndroid Build Coastguard Worker *
999*6777b538SAndroid Build Coastguard Worker * This will dump the content of the element content definition
1000*6777b538SAndroid Build Coastguard Worker * Intended just for the debug routine
1001*6777b538SAndroid Build Coastguard Worker */
1002*6777b538SAndroid Build Coastguard Worker void
xmlSnprintfElementContent(char * buf,int size,xmlElementContentPtr content,int englob)1003*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob) {
1004*6777b538SAndroid Build Coastguard Worker int len;
1005*6777b538SAndroid Build Coastguard Worker
1006*6777b538SAndroid Build Coastguard Worker if (content == NULL) return;
1007*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1008*6777b538SAndroid Build Coastguard Worker if (size - len < 50) {
1009*6777b538SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
1010*6777b538SAndroid Build Coastguard Worker strcat(buf, " ...");
1011*6777b538SAndroid Build Coastguard Worker return;
1012*6777b538SAndroid Build Coastguard Worker }
1013*6777b538SAndroid Build Coastguard Worker if (englob) strcat(buf, "(");
1014*6777b538SAndroid Build Coastguard Worker switch (content->type) {
1015*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
1016*6777b538SAndroid Build Coastguard Worker strcat(buf, "#PCDATA");
1017*6777b538SAndroid Build Coastguard Worker break;
1018*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT: {
1019*6777b538SAndroid Build Coastguard Worker int qnameLen = xmlStrlen(content->name);
1020*6777b538SAndroid Build Coastguard Worker
1021*6777b538SAndroid Build Coastguard Worker if (content->prefix != NULL)
1022*6777b538SAndroid Build Coastguard Worker qnameLen += xmlStrlen(content->prefix) + 1;
1023*6777b538SAndroid Build Coastguard Worker if (size - len < qnameLen + 10) {
1024*6777b538SAndroid Build Coastguard Worker strcat(buf, " ...");
1025*6777b538SAndroid Build Coastguard Worker return;
1026*6777b538SAndroid Build Coastguard Worker }
1027*6777b538SAndroid Build Coastguard Worker if (content->prefix != NULL) {
1028*6777b538SAndroid Build Coastguard Worker strcat(buf, (char *) content->prefix);
1029*6777b538SAndroid Build Coastguard Worker strcat(buf, ":");
1030*6777b538SAndroid Build Coastguard Worker }
1031*6777b538SAndroid Build Coastguard Worker if (content->name != NULL)
1032*6777b538SAndroid Build Coastguard Worker strcat(buf, (char *) content->name);
1033*6777b538SAndroid Build Coastguard Worker break;
1034*6777b538SAndroid Build Coastguard Worker }
1035*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
1036*6777b538SAndroid Build Coastguard Worker if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
1037*6777b538SAndroid Build Coastguard Worker (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1038*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c1, 1);
1039*6777b538SAndroid Build Coastguard Worker else
1040*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c1, 0);
1041*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1042*6777b538SAndroid Build Coastguard Worker if (size - len < 50) {
1043*6777b538SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
1044*6777b538SAndroid Build Coastguard Worker strcat(buf, " ...");
1045*6777b538SAndroid Build Coastguard Worker return;
1046*6777b538SAndroid Build Coastguard Worker }
1047*6777b538SAndroid Build Coastguard Worker strcat(buf, " , ");
1048*6777b538SAndroid Build Coastguard Worker if (((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
1049*6777b538SAndroid Build Coastguard Worker (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
1050*6777b538SAndroid Build Coastguard Worker (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
1051*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c2, 1);
1052*6777b538SAndroid Build Coastguard Worker else
1053*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c2, 0);
1054*6777b538SAndroid Build Coastguard Worker break;
1055*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
1056*6777b538SAndroid Build Coastguard Worker if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
1057*6777b538SAndroid Build Coastguard Worker (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1058*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c1, 1);
1059*6777b538SAndroid Build Coastguard Worker else
1060*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c1, 0);
1061*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1062*6777b538SAndroid Build Coastguard Worker if (size - len < 50) {
1063*6777b538SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
1064*6777b538SAndroid Build Coastguard Worker strcat(buf, " ...");
1065*6777b538SAndroid Build Coastguard Worker return;
1066*6777b538SAndroid Build Coastguard Worker }
1067*6777b538SAndroid Build Coastguard Worker strcat(buf, " | ");
1068*6777b538SAndroid Build Coastguard Worker if (((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
1069*6777b538SAndroid Build Coastguard Worker (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) &&
1070*6777b538SAndroid Build Coastguard Worker (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT))
1071*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c2, 1);
1072*6777b538SAndroid Build Coastguard Worker else
1073*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(buf, size, content->c2, 0);
1074*6777b538SAndroid Build Coastguard Worker break;
1075*6777b538SAndroid Build Coastguard Worker }
1076*6777b538SAndroid Build Coastguard Worker if (size - strlen(buf) <= 2) return;
1077*6777b538SAndroid Build Coastguard Worker if (englob)
1078*6777b538SAndroid Build Coastguard Worker strcat(buf, ")");
1079*6777b538SAndroid Build Coastguard Worker switch (content->ocur) {
1080*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
1081*6777b538SAndroid Build Coastguard Worker break;
1082*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
1083*6777b538SAndroid Build Coastguard Worker strcat(buf, "?");
1084*6777b538SAndroid Build Coastguard Worker break;
1085*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
1086*6777b538SAndroid Build Coastguard Worker strcat(buf, "*");
1087*6777b538SAndroid Build Coastguard Worker break;
1088*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
1089*6777b538SAndroid Build Coastguard Worker strcat(buf, "+");
1090*6777b538SAndroid Build Coastguard Worker break;
1091*6777b538SAndroid Build Coastguard Worker }
1092*6777b538SAndroid Build Coastguard Worker }
1093*6777b538SAndroid Build Coastguard Worker
1094*6777b538SAndroid Build Coastguard Worker /****************************************************************
1095*6777b538SAndroid Build Coastguard Worker * *
1096*6777b538SAndroid Build Coastguard Worker * Registration of DTD declarations *
1097*6777b538SAndroid Build Coastguard Worker * *
1098*6777b538SAndroid Build Coastguard Worker ****************************************************************/
1099*6777b538SAndroid Build Coastguard Worker
1100*6777b538SAndroid Build Coastguard Worker /**
1101*6777b538SAndroid Build Coastguard Worker * xmlFreeElement:
1102*6777b538SAndroid Build Coastguard Worker * @elem: An element
1103*6777b538SAndroid Build Coastguard Worker *
1104*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an element definition
1105*6777b538SAndroid Build Coastguard Worker */
1106*6777b538SAndroid Build Coastguard Worker static void
xmlFreeElement(xmlElementPtr elem)1107*6777b538SAndroid Build Coastguard Worker xmlFreeElement(xmlElementPtr elem) {
1108*6777b538SAndroid Build Coastguard Worker if (elem == NULL) return;
1109*6777b538SAndroid Build Coastguard Worker xmlUnlinkNode((xmlNodePtr) elem);
1110*6777b538SAndroid Build Coastguard Worker xmlFreeDocElementContent(elem->doc, elem->content);
1111*6777b538SAndroid Build Coastguard Worker if (elem->name != NULL)
1112*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) elem->name);
1113*6777b538SAndroid Build Coastguard Worker if (elem->prefix != NULL)
1114*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) elem->prefix);
1115*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
1116*6777b538SAndroid Build Coastguard Worker if (elem->contModel != NULL)
1117*6777b538SAndroid Build Coastguard Worker xmlRegFreeRegexp(elem->contModel);
1118*6777b538SAndroid Build Coastguard Worker #endif
1119*6777b538SAndroid Build Coastguard Worker xmlFree(elem);
1120*6777b538SAndroid Build Coastguard Worker }
1121*6777b538SAndroid Build Coastguard Worker
1122*6777b538SAndroid Build Coastguard Worker
1123*6777b538SAndroid Build Coastguard Worker /**
1124*6777b538SAndroid Build Coastguard Worker * xmlAddElementDecl:
1125*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
1126*6777b538SAndroid Build Coastguard Worker * @dtd: pointer to the DTD
1127*6777b538SAndroid Build Coastguard Worker * @name: the entity name
1128*6777b538SAndroid Build Coastguard Worker * @type: the element type
1129*6777b538SAndroid Build Coastguard Worker * @content: the element content tree or NULL
1130*6777b538SAndroid Build Coastguard Worker *
1131*6777b538SAndroid Build Coastguard Worker * Register a new element declaration
1132*6777b538SAndroid Build Coastguard Worker *
1133*6777b538SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the entity
1134*6777b538SAndroid Build Coastguard Worker */
1135*6777b538SAndroid Build Coastguard Worker xmlElementPtr
xmlAddElementDecl(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * name,xmlElementTypeVal type,xmlElementContentPtr content)1136*6777b538SAndroid Build Coastguard Worker xmlAddElementDecl(xmlValidCtxtPtr ctxt,
1137*6777b538SAndroid Build Coastguard Worker xmlDtdPtr dtd, const xmlChar *name,
1138*6777b538SAndroid Build Coastguard Worker xmlElementTypeVal type,
1139*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr content) {
1140*6777b538SAndroid Build Coastguard Worker xmlElementPtr ret;
1141*6777b538SAndroid Build Coastguard Worker xmlElementTablePtr table;
1142*6777b538SAndroid Build Coastguard Worker xmlAttributePtr oldAttributes = NULL;
1143*6777b538SAndroid Build Coastguard Worker const xmlChar *localName;
1144*6777b538SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
1145*6777b538SAndroid Build Coastguard Worker
1146*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) {
1147*6777b538SAndroid Build Coastguard Worker return(NULL);
1148*6777b538SAndroid Build Coastguard Worker }
1149*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
1150*6777b538SAndroid Build Coastguard Worker return(NULL);
1151*6777b538SAndroid Build Coastguard Worker }
1152*6777b538SAndroid Build Coastguard Worker
1153*6777b538SAndroid Build Coastguard Worker switch (type) {
1154*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
1155*6777b538SAndroid Build Coastguard Worker if (content != NULL) {
1156*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
1157*6777b538SAndroid Build Coastguard Worker "xmlAddElementDecl: content != NULL for EMPTY\n",
1158*6777b538SAndroid Build Coastguard Worker NULL);
1159*6777b538SAndroid Build Coastguard Worker return(NULL);
1160*6777b538SAndroid Build Coastguard Worker }
1161*6777b538SAndroid Build Coastguard Worker break;
1162*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
1163*6777b538SAndroid Build Coastguard Worker if (content != NULL) {
1164*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
1165*6777b538SAndroid Build Coastguard Worker "xmlAddElementDecl: content != NULL for ANY\n",
1166*6777b538SAndroid Build Coastguard Worker NULL);
1167*6777b538SAndroid Build Coastguard Worker return(NULL);
1168*6777b538SAndroid Build Coastguard Worker }
1169*6777b538SAndroid Build Coastguard Worker break;
1170*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
1171*6777b538SAndroid Build Coastguard Worker if (content == NULL) {
1172*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
1173*6777b538SAndroid Build Coastguard Worker "xmlAddElementDecl: content == NULL for MIXED\n",
1174*6777b538SAndroid Build Coastguard Worker NULL);
1175*6777b538SAndroid Build Coastguard Worker return(NULL);
1176*6777b538SAndroid Build Coastguard Worker }
1177*6777b538SAndroid Build Coastguard Worker break;
1178*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT:
1179*6777b538SAndroid Build Coastguard Worker if (content == NULL) {
1180*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR,
1181*6777b538SAndroid Build Coastguard Worker "xmlAddElementDecl: content == NULL for ELEMENT\n",
1182*6777b538SAndroid Build Coastguard Worker NULL);
1183*6777b538SAndroid Build Coastguard Worker return(NULL);
1184*6777b538SAndroid Build Coastguard Worker }
1185*6777b538SAndroid Build Coastguard Worker break;
1186*6777b538SAndroid Build Coastguard Worker default:
1187*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1188*6777b538SAndroid Build Coastguard Worker "Internal: ELEMENT decl corrupted invalid type\n",
1189*6777b538SAndroid Build Coastguard Worker NULL);
1190*6777b538SAndroid Build Coastguard Worker return(NULL);
1191*6777b538SAndroid Build Coastguard Worker }
1192*6777b538SAndroid Build Coastguard Worker
1193*6777b538SAndroid Build Coastguard Worker /*
1194*6777b538SAndroid Build Coastguard Worker * check if name is a QName
1195*6777b538SAndroid Build Coastguard Worker */
1196*6777b538SAndroid Build Coastguard Worker localName = xmlSplitQName4(name, &prefix);
1197*6777b538SAndroid Build Coastguard Worker if (localName == NULL)
1198*6777b538SAndroid Build Coastguard Worker goto mem_error;
1199*6777b538SAndroid Build Coastguard Worker
1200*6777b538SAndroid Build Coastguard Worker /*
1201*6777b538SAndroid Build Coastguard Worker * Create the Element table if needed.
1202*6777b538SAndroid Build Coastguard Worker */
1203*6777b538SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
1204*6777b538SAndroid Build Coastguard Worker if (table == NULL) {
1205*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
1206*6777b538SAndroid Build Coastguard Worker
1207*6777b538SAndroid Build Coastguard Worker if (dtd->doc != NULL)
1208*6777b538SAndroid Build Coastguard Worker dict = dtd->doc->dict;
1209*6777b538SAndroid Build Coastguard Worker table = xmlHashCreateDict(0, dict);
1210*6777b538SAndroid Build Coastguard Worker if (table == NULL)
1211*6777b538SAndroid Build Coastguard Worker goto mem_error;
1212*6777b538SAndroid Build Coastguard Worker dtd->elements = (void *) table;
1213*6777b538SAndroid Build Coastguard Worker }
1214*6777b538SAndroid Build Coastguard Worker
1215*6777b538SAndroid Build Coastguard Worker /*
1216*6777b538SAndroid Build Coastguard Worker * lookup old attributes inserted on an undefined element in the
1217*6777b538SAndroid Build Coastguard Worker * internal subset.
1218*6777b538SAndroid Build Coastguard Worker */
1219*6777b538SAndroid Build Coastguard Worker if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
1220*6777b538SAndroid Build Coastguard Worker ret = xmlHashLookup2(dtd->doc->intSubset->elements, localName, prefix);
1221*6777b538SAndroid Build Coastguard Worker if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
1222*6777b538SAndroid Build Coastguard Worker oldAttributes = ret->attributes;
1223*6777b538SAndroid Build Coastguard Worker ret->attributes = NULL;
1224*6777b538SAndroid Build Coastguard Worker xmlHashRemoveEntry2(dtd->doc->intSubset->elements, localName, prefix,
1225*6777b538SAndroid Build Coastguard Worker NULL);
1226*6777b538SAndroid Build Coastguard Worker xmlFreeElement(ret);
1227*6777b538SAndroid Build Coastguard Worker }
1228*6777b538SAndroid Build Coastguard Worker }
1229*6777b538SAndroid Build Coastguard Worker
1230*6777b538SAndroid Build Coastguard Worker /*
1231*6777b538SAndroid Build Coastguard Worker * The element may already be present if one of its attribute
1232*6777b538SAndroid Build Coastguard Worker * was registered first
1233*6777b538SAndroid Build Coastguard Worker */
1234*6777b538SAndroid Build Coastguard Worker ret = xmlHashLookup2(table, localName, prefix);
1235*6777b538SAndroid Build Coastguard Worker if (ret != NULL) {
1236*6777b538SAndroid Build Coastguard Worker if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
1237*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1238*6777b538SAndroid Build Coastguard Worker /*
1239*6777b538SAndroid Build Coastguard Worker * The element is already defined in this DTD.
1240*6777b538SAndroid Build Coastguard Worker */
1241*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED,
1242*6777b538SAndroid Build Coastguard Worker "Redefinition of element %s\n",
1243*6777b538SAndroid Build Coastguard Worker name, NULL, NULL);
1244*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1245*6777b538SAndroid Build Coastguard Worker if (prefix != NULL)
1246*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
1247*6777b538SAndroid Build Coastguard Worker return(NULL);
1248*6777b538SAndroid Build Coastguard Worker }
1249*6777b538SAndroid Build Coastguard Worker if (prefix != NULL) {
1250*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
1251*6777b538SAndroid Build Coastguard Worker prefix = NULL;
1252*6777b538SAndroid Build Coastguard Worker }
1253*6777b538SAndroid Build Coastguard Worker } else {
1254*6777b538SAndroid Build Coastguard Worker int res;
1255*6777b538SAndroid Build Coastguard Worker
1256*6777b538SAndroid Build Coastguard Worker ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
1257*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1258*6777b538SAndroid Build Coastguard Worker goto mem_error;
1259*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlElement));
1260*6777b538SAndroid Build Coastguard Worker ret->type = XML_ELEMENT_DECL;
1261*6777b538SAndroid Build Coastguard Worker
1262*6777b538SAndroid Build Coastguard Worker /*
1263*6777b538SAndroid Build Coastguard Worker * fill the structure.
1264*6777b538SAndroid Build Coastguard Worker */
1265*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(localName);
1266*6777b538SAndroid Build Coastguard Worker if (ret->name == NULL) {
1267*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
1268*6777b538SAndroid Build Coastguard Worker goto mem_error;
1269*6777b538SAndroid Build Coastguard Worker }
1270*6777b538SAndroid Build Coastguard Worker ret->prefix = prefix;
1271*6777b538SAndroid Build Coastguard Worker prefix = NULL;
1272*6777b538SAndroid Build Coastguard Worker
1273*6777b538SAndroid Build Coastguard Worker /*
1274*6777b538SAndroid Build Coastguard Worker * Validity Check:
1275*6777b538SAndroid Build Coastguard Worker * Insertion must not fail
1276*6777b538SAndroid Build Coastguard Worker */
1277*6777b538SAndroid Build Coastguard Worker res = xmlHashAdd2(table, localName, ret->prefix, ret);
1278*6777b538SAndroid Build Coastguard Worker if (res <= 0) {
1279*6777b538SAndroid Build Coastguard Worker xmlFreeElement(ret);
1280*6777b538SAndroid Build Coastguard Worker goto mem_error;
1281*6777b538SAndroid Build Coastguard Worker }
1282*6777b538SAndroid Build Coastguard Worker /*
1283*6777b538SAndroid Build Coastguard Worker * For new element, may have attributes from earlier
1284*6777b538SAndroid Build Coastguard Worker * definition in internal subset
1285*6777b538SAndroid Build Coastguard Worker */
1286*6777b538SAndroid Build Coastguard Worker ret->attributes = oldAttributes;
1287*6777b538SAndroid Build Coastguard Worker }
1288*6777b538SAndroid Build Coastguard Worker
1289*6777b538SAndroid Build Coastguard Worker /*
1290*6777b538SAndroid Build Coastguard Worker * Finish to fill the structure.
1291*6777b538SAndroid Build Coastguard Worker */
1292*6777b538SAndroid Build Coastguard Worker ret->etype = type;
1293*6777b538SAndroid Build Coastguard Worker /*
1294*6777b538SAndroid Build Coastguard Worker * Avoid a stupid copy when called by the parser
1295*6777b538SAndroid Build Coastguard Worker * and flag it by setting a special parent value
1296*6777b538SAndroid Build Coastguard Worker * so the parser doesn't unallocate it.
1297*6777b538SAndroid Build Coastguard Worker */
1298*6777b538SAndroid Build Coastguard Worker if (content != NULL) {
1299*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) {
1300*6777b538SAndroid Build Coastguard Worker ret->content = content;
1301*6777b538SAndroid Build Coastguard Worker content->parent = (xmlElementContentPtr) 1;
1302*6777b538SAndroid Build Coastguard Worker } else if (content != NULL){
1303*6777b538SAndroid Build Coastguard Worker ret->content = xmlCopyDocElementContent(dtd->doc, content);
1304*6777b538SAndroid Build Coastguard Worker if (ret->content == NULL)
1305*6777b538SAndroid Build Coastguard Worker goto mem_error;
1306*6777b538SAndroid Build Coastguard Worker }
1307*6777b538SAndroid Build Coastguard Worker }
1308*6777b538SAndroid Build Coastguard Worker
1309*6777b538SAndroid Build Coastguard Worker /*
1310*6777b538SAndroid Build Coastguard Worker * Link it to the DTD
1311*6777b538SAndroid Build Coastguard Worker */
1312*6777b538SAndroid Build Coastguard Worker ret->parent = dtd;
1313*6777b538SAndroid Build Coastguard Worker ret->doc = dtd->doc;
1314*6777b538SAndroid Build Coastguard Worker if (dtd->last == NULL) {
1315*6777b538SAndroid Build Coastguard Worker dtd->children = dtd->last = (xmlNodePtr) ret;
1316*6777b538SAndroid Build Coastguard Worker } else {
1317*6777b538SAndroid Build Coastguard Worker dtd->last->next = (xmlNodePtr) ret;
1318*6777b538SAndroid Build Coastguard Worker ret->prev = dtd->last;
1319*6777b538SAndroid Build Coastguard Worker dtd->last = (xmlNodePtr) ret;
1320*6777b538SAndroid Build Coastguard Worker }
1321*6777b538SAndroid Build Coastguard Worker if (prefix != NULL)
1322*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
1323*6777b538SAndroid Build Coastguard Worker return(ret);
1324*6777b538SAndroid Build Coastguard Worker
1325*6777b538SAndroid Build Coastguard Worker mem_error:
1326*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
1327*6777b538SAndroid Build Coastguard Worker if (prefix != NULL)
1328*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
1329*6777b538SAndroid Build Coastguard Worker return(NULL);
1330*6777b538SAndroid Build Coastguard Worker }
1331*6777b538SAndroid Build Coastguard Worker
1332*6777b538SAndroid Build Coastguard Worker static void
xmlFreeElementTableEntry(void * elem,const xmlChar * name ATTRIBUTE_UNUSED)1333*6777b538SAndroid Build Coastguard Worker xmlFreeElementTableEntry(void *elem, const xmlChar *name ATTRIBUTE_UNUSED) {
1334*6777b538SAndroid Build Coastguard Worker xmlFreeElement((xmlElementPtr) elem);
1335*6777b538SAndroid Build Coastguard Worker }
1336*6777b538SAndroid Build Coastguard Worker
1337*6777b538SAndroid Build Coastguard Worker /**
1338*6777b538SAndroid Build Coastguard Worker * xmlFreeElementTable:
1339*6777b538SAndroid Build Coastguard Worker * @table: An element table
1340*6777b538SAndroid Build Coastguard Worker *
1341*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an element hash table.
1342*6777b538SAndroid Build Coastguard Worker */
1343*6777b538SAndroid Build Coastguard Worker void
xmlFreeElementTable(xmlElementTablePtr table)1344*6777b538SAndroid Build Coastguard Worker xmlFreeElementTable(xmlElementTablePtr table) {
1345*6777b538SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeElementTableEntry);
1346*6777b538SAndroid Build Coastguard Worker }
1347*6777b538SAndroid Build Coastguard Worker
1348*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_TREE_ENABLED
1349*6777b538SAndroid Build Coastguard Worker /**
1350*6777b538SAndroid Build Coastguard Worker * xmlCopyElement:
1351*6777b538SAndroid Build Coastguard Worker * @elem: An element
1352*6777b538SAndroid Build Coastguard Worker *
1353*6777b538SAndroid Build Coastguard Worker * Build a copy of an element.
1354*6777b538SAndroid Build Coastguard Worker *
1355*6777b538SAndroid Build Coastguard Worker * Returns the new xmlElementPtr or NULL in case of error.
1356*6777b538SAndroid Build Coastguard Worker */
1357*6777b538SAndroid Build Coastguard Worker static void *
xmlCopyElement(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)1358*6777b538SAndroid Build Coastguard Worker xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
1359*6777b538SAndroid Build Coastguard Worker xmlElementPtr elem = (xmlElementPtr) payload;
1360*6777b538SAndroid Build Coastguard Worker xmlElementPtr cur;
1361*6777b538SAndroid Build Coastguard Worker
1362*6777b538SAndroid Build Coastguard Worker cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
1363*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
1364*6777b538SAndroid Build Coastguard Worker return(NULL);
1365*6777b538SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlElement));
1366*6777b538SAndroid Build Coastguard Worker cur->type = XML_ELEMENT_DECL;
1367*6777b538SAndroid Build Coastguard Worker cur->etype = elem->etype;
1368*6777b538SAndroid Build Coastguard Worker if (elem->name != NULL) {
1369*6777b538SAndroid Build Coastguard Worker cur->name = xmlStrdup(elem->name);
1370*6777b538SAndroid Build Coastguard Worker if (cur->name == NULL)
1371*6777b538SAndroid Build Coastguard Worker goto error;
1372*6777b538SAndroid Build Coastguard Worker }
1373*6777b538SAndroid Build Coastguard Worker if (elem->prefix != NULL) {
1374*6777b538SAndroid Build Coastguard Worker cur->prefix = xmlStrdup(elem->prefix);
1375*6777b538SAndroid Build Coastguard Worker if (cur->prefix == NULL)
1376*6777b538SAndroid Build Coastguard Worker goto error;
1377*6777b538SAndroid Build Coastguard Worker }
1378*6777b538SAndroid Build Coastguard Worker if (elem->content != NULL) {
1379*6777b538SAndroid Build Coastguard Worker cur->content = xmlCopyElementContent(elem->content);
1380*6777b538SAndroid Build Coastguard Worker if (cur->content == NULL)
1381*6777b538SAndroid Build Coastguard Worker goto error;
1382*6777b538SAndroid Build Coastguard Worker }
1383*6777b538SAndroid Build Coastguard Worker /* TODO : rebuild the attribute list on the copy */
1384*6777b538SAndroid Build Coastguard Worker cur->attributes = NULL;
1385*6777b538SAndroid Build Coastguard Worker return(cur);
1386*6777b538SAndroid Build Coastguard Worker
1387*6777b538SAndroid Build Coastguard Worker error:
1388*6777b538SAndroid Build Coastguard Worker xmlFreeElement(cur);
1389*6777b538SAndroid Build Coastguard Worker return(NULL);
1390*6777b538SAndroid Build Coastguard Worker }
1391*6777b538SAndroid Build Coastguard Worker
1392*6777b538SAndroid Build Coastguard Worker /**
1393*6777b538SAndroid Build Coastguard Worker * xmlCopyElementTable:
1394*6777b538SAndroid Build Coastguard Worker * @table: An element table
1395*6777b538SAndroid Build Coastguard Worker *
1396*6777b538SAndroid Build Coastguard Worker * Build a copy of an element table.
1397*6777b538SAndroid Build Coastguard Worker *
1398*6777b538SAndroid Build Coastguard Worker * Returns the new xmlElementTablePtr or NULL in case of error.
1399*6777b538SAndroid Build Coastguard Worker */
1400*6777b538SAndroid Build Coastguard Worker xmlElementTablePtr
xmlCopyElementTable(xmlElementTablePtr table)1401*6777b538SAndroid Build Coastguard Worker xmlCopyElementTable(xmlElementTablePtr table) {
1402*6777b538SAndroid Build Coastguard Worker return(xmlHashCopySafe(table, xmlCopyElement, xmlFreeElementTableEntry));
1403*6777b538SAndroid Build Coastguard Worker }
1404*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_TREE_ENABLED */
1405*6777b538SAndroid Build Coastguard Worker
1406*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
1407*6777b538SAndroid Build Coastguard Worker /**
1408*6777b538SAndroid Build Coastguard Worker * xmlDumpElementDecl:
1409*6777b538SAndroid Build Coastguard Worker * @buf: the XML buffer output
1410*6777b538SAndroid Build Coastguard Worker * @elem: An element table
1411*6777b538SAndroid Build Coastguard Worker *
1412*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Use xmlSaveTree.
1413*6777b538SAndroid Build Coastguard Worker *
1414*6777b538SAndroid Build Coastguard Worker * This will dump the content of the element declaration as an XML
1415*6777b538SAndroid Build Coastguard Worker * DTD definition
1416*6777b538SAndroid Build Coastguard Worker */
1417*6777b538SAndroid Build Coastguard Worker void
xmlDumpElementDecl(xmlBufferPtr buf,xmlElementPtr elem)1418*6777b538SAndroid Build Coastguard Worker xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
1419*6777b538SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
1420*6777b538SAndroid Build Coastguard Worker
1421*6777b538SAndroid Build Coastguard Worker if ((buf == NULL) || (elem == NULL))
1422*6777b538SAndroid Build Coastguard Worker return;
1423*6777b538SAndroid Build Coastguard Worker
1424*6777b538SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
1425*6777b538SAndroid Build Coastguard Worker xmlSaveTree(save, (xmlNodePtr) elem);
1426*6777b538SAndroid Build Coastguard Worker xmlSaveClose(save);
1427*6777b538SAndroid Build Coastguard Worker }
1428*6777b538SAndroid Build Coastguard Worker
1429*6777b538SAndroid Build Coastguard Worker /**
1430*6777b538SAndroid Build Coastguard Worker * xmlDumpElementDeclScan:
1431*6777b538SAndroid Build Coastguard Worker * @elem: An element table
1432*6777b538SAndroid Build Coastguard Worker * @buf: the XML buffer output
1433*6777b538SAndroid Build Coastguard Worker *
1434*6777b538SAndroid Build Coastguard Worker * This routine is used by the hash scan function. It just reverses
1435*6777b538SAndroid Build Coastguard Worker * the arguments.
1436*6777b538SAndroid Build Coastguard Worker */
1437*6777b538SAndroid Build Coastguard Worker static void
xmlDumpElementDeclScan(void * elem,void * buf,const xmlChar * name ATTRIBUTE_UNUSED)1438*6777b538SAndroid Build Coastguard Worker xmlDumpElementDeclScan(void *elem, void *buf,
1439*6777b538SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
1440*6777b538SAndroid Build Coastguard Worker xmlDumpElementDecl((xmlBufferPtr) buf, (xmlElementPtr) elem);
1441*6777b538SAndroid Build Coastguard Worker }
1442*6777b538SAndroid Build Coastguard Worker
1443*6777b538SAndroid Build Coastguard Worker /**
1444*6777b538SAndroid Build Coastguard Worker * xmlDumpElementTable:
1445*6777b538SAndroid Build Coastguard Worker * @buf: the XML buffer output
1446*6777b538SAndroid Build Coastguard Worker * @table: An element table
1447*6777b538SAndroid Build Coastguard Worker *
1448*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Don't use.
1449*6777b538SAndroid Build Coastguard Worker *
1450*6777b538SAndroid Build Coastguard Worker * This will dump the content of the element table as an XML DTD definition
1451*6777b538SAndroid Build Coastguard Worker */
1452*6777b538SAndroid Build Coastguard Worker void
xmlDumpElementTable(xmlBufferPtr buf,xmlElementTablePtr table)1453*6777b538SAndroid Build Coastguard Worker xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
1454*6777b538SAndroid Build Coastguard Worker if ((buf == NULL) || (table == NULL))
1455*6777b538SAndroid Build Coastguard Worker return;
1456*6777b538SAndroid Build Coastguard Worker xmlHashScan(table, xmlDumpElementDeclScan, buf);
1457*6777b538SAndroid Build Coastguard Worker }
1458*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
1459*6777b538SAndroid Build Coastguard Worker
1460*6777b538SAndroid Build Coastguard Worker /**
1461*6777b538SAndroid Build Coastguard Worker * xmlCreateEnumeration:
1462*6777b538SAndroid Build Coastguard Worker * @name: the enumeration name or NULL
1463*6777b538SAndroid Build Coastguard Worker *
1464*6777b538SAndroid Build Coastguard Worker * create and initialize an enumeration attribute node.
1465*6777b538SAndroid Build Coastguard Worker *
1466*6777b538SAndroid Build Coastguard Worker * Returns the xmlEnumerationPtr just created or NULL in case
1467*6777b538SAndroid Build Coastguard Worker * of error.
1468*6777b538SAndroid Build Coastguard Worker */
1469*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr
xmlCreateEnumeration(const xmlChar * name)1470*6777b538SAndroid Build Coastguard Worker xmlCreateEnumeration(const xmlChar *name) {
1471*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr ret;
1472*6777b538SAndroid Build Coastguard Worker
1473*6777b538SAndroid Build Coastguard Worker ret = (xmlEnumerationPtr) xmlMalloc(sizeof(xmlEnumeration));
1474*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1475*6777b538SAndroid Build Coastguard Worker return(NULL);
1476*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlEnumeration));
1477*6777b538SAndroid Build Coastguard Worker
1478*6777b538SAndroid Build Coastguard Worker if (name != NULL) {
1479*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(name);
1480*6777b538SAndroid Build Coastguard Worker if (ret->name == NULL) {
1481*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
1482*6777b538SAndroid Build Coastguard Worker return(NULL);
1483*6777b538SAndroid Build Coastguard Worker }
1484*6777b538SAndroid Build Coastguard Worker }
1485*6777b538SAndroid Build Coastguard Worker
1486*6777b538SAndroid Build Coastguard Worker return(ret);
1487*6777b538SAndroid Build Coastguard Worker }
1488*6777b538SAndroid Build Coastguard Worker
1489*6777b538SAndroid Build Coastguard Worker /**
1490*6777b538SAndroid Build Coastguard Worker * xmlFreeEnumeration:
1491*6777b538SAndroid Build Coastguard Worker * @cur: the tree to free.
1492*6777b538SAndroid Build Coastguard Worker *
1493*6777b538SAndroid Build Coastguard Worker * free an enumeration attribute node (recursive).
1494*6777b538SAndroid Build Coastguard Worker */
1495*6777b538SAndroid Build Coastguard Worker void
xmlFreeEnumeration(xmlEnumerationPtr cur)1496*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(xmlEnumerationPtr cur) {
1497*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
1498*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr next = cur->next;
1499*6777b538SAndroid Build Coastguard Worker
1500*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) cur->name);
1501*6777b538SAndroid Build Coastguard Worker xmlFree(cur);
1502*6777b538SAndroid Build Coastguard Worker
1503*6777b538SAndroid Build Coastguard Worker cur = next;
1504*6777b538SAndroid Build Coastguard Worker }
1505*6777b538SAndroid Build Coastguard Worker }
1506*6777b538SAndroid Build Coastguard Worker
1507*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_TREE_ENABLED
1508*6777b538SAndroid Build Coastguard Worker /**
1509*6777b538SAndroid Build Coastguard Worker * xmlCopyEnumeration:
1510*6777b538SAndroid Build Coastguard Worker * @cur: the tree to copy.
1511*6777b538SAndroid Build Coastguard Worker *
1512*6777b538SAndroid Build Coastguard Worker * Copy an enumeration attribute node (recursive).
1513*6777b538SAndroid Build Coastguard Worker *
1514*6777b538SAndroid Build Coastguard Worker * Returns the xmlEnumerationPtr just created or NULL in case
1515*6777b538SAndroid Build Coastguard Worker * of error.
1516*6777b538SAndroid Build Coastguard Worker */
1517*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr
xmlCopyEnumeration(xmlEnumerationPtr cur)1518*6777b538SAndroid Build Coastguard Worker xmlCopyEnumeration(xmlEnumerationPtr cur) {
1519*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr ret = NULL;
1520*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr last = NULL;
1521*6777b538SAndroid Build Coastguard Worker
1522*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
1523*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr copy = xmlCreateEnumeration(cur->name);
1524*6777b538SAndroid Build Coastguard Worker
1525*6777b538SAndroid Build Coastguard Worker if (copy == NULL) {
1526*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(ret);
1527*6777b538SAndroid Build Coastguard Worker return(NULL);
1528*6777b538SAndroid Build Coastguard Worker }
1529*6777b538SAndroid Build Coastguard Worker
1530*6777b538SAndroid Build Coastguard Worker if (ret == NULL) {
1531*6777b538SAndroid Build Coastguard Worker ret = last = copy;
1532*6777b538SAndroid Build Coastguard Worker } else {
1533*6777b538SAndroid Build Coastguard Worker last->next = copy;
1534*6777b538SAndroid Build Coastguard Worker last = copy;
1535*6777b538SAndroid Build Coastguard Worker }
1536*6777b538SAndroid Build Coastguard Worker
1537*6777b538SAndroid Build Coastguard Worker cur = cur->next;
1538*6777b538SAndroid Build Coastguard Worker }
1539*6777b538SAndroid Build Coastguard Worker
1540*6777b538SAndroid Build Coastguard Worker return(ret);
1541*6777b538SAndroid Build Coastguard Worker }
1542*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_TREE_ENABLED */
1543*6777b538SAndroid Build Coastguard Worker
1544*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1545*6777b538SAndroid Build Coastguard Worker /**
1546*6777b538SAndroid Build Coastguard Worker * xmlScanIDAttributeDecl:
1547*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
1548*6777b538SAndroid Build Coastguard Worker * @elem: the element name
1549*6777b538SAndroid Build Coastguard Worker * @err: whether to raise errors here
1550*6777b538SAndroid Build Coastguard Worker *
1551*6777b538SAndroid Build Coastguard Worker * Verify that the element don't have too many ID attributes
1552*6777b538SAndroid Build Coastguard Worker * declared.
1553*6777b538SAndroid Build Coastguard Worker *
1554*6777b538SAndroid Build Coastguard Worker * Returns the number of ID attributes found.
1555*6777b538SAndroid Build Coastguard Worker */
1556*6777b538SAndroid Build Coastguard Worker static int
xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt,xmlElementPtr elem,int err)1557*6777b538SAndroid Build Coastguard Worker xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem, int err) {
1558*6777b538SAndroid Build Coastguard Worker xmlAttributePtr cur;
1559*6777b538SAndroid Build Coastguard Worker int ret = 0;
1560*6777b538SAndroid Build Coastguard Worker
1561*6777b538SAndroid Build Coastguard Worker if (elem == NULL) return(0);
1562*6777b538SAndroid Build Coastguard Worker cur = elem->attributes;
1563*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
1564*6777b538SAndroid Build Coastguard Worker if (cur->atype == XML_ATTRIBUTE_ID) {
1565*6777b538SAndroid Build Coastguard Worker ret ++;
1566*6777b538SAndroid Build Coastguard Worker if ((ret > 1) && (err))
1567*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_MULTIPLE_ID,
1568*6777b538SAndroid Build Coastguard Worker "Element %s has too many ID attributes defined : %s\n",
1569*6777b538SAndroid Build Coastguard Worker elem->name, cur->name, NULL);
1570*6777b538SAndroid Build Coastguard Worker }
1571*6777b538SAndroid Build Coastguard Worker cur = cur->nexth;
1572*6777b538SAndroid Build Coastguard Worker }
1573*6777b538SAndroid Build Coastguard Worker return(ret);
1574*6777b538SAndroid Build Coastguard Worker }
1575*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1576*6777b538SAndroid Build Coastguard Worker
1577*6777b538SAndroid Build Coastguard Worker /**
1578*6777b538SAndroid Build Coastguard Worker * xmlFreeAttribute:
1579*6777b538SAndroid Build Coastguard Worker * @elem: An attribute
1580*6777b538SAndroid Build Coastguard Worker *
1581*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an attribute definition
1582*6777b538SAndroid Build Coastguard Worker */
1583*6777b538SAndroid Build Coastguard Worker static void
xmlFreeAttribute(xmlAttributePtr attr)1584*6777b538SAndroid Build Coastguard Worker xmlFreeAttribute(xmlAttributePtr attr) {
1585*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict;
1586*6777b538SAndroid Build Coastguard Worker
1587*6777b538SAndroid Build Coastguard Worker if (attr == NULL) return;
1588*6777b538SAndroid Build Coastguard Worker if (attr->doc != NULL)
1589*6777b538SAndroid Build Coastguard Worker dict = attr->doc->dict;
1590*6777b538SAndroid Build Coastguard Worker else
1591*6777b538SAndroid Build Coastguard Worker dict = NULL;
1592*6777b538SAndroid Build Coastguard Worker xmlUnlinkNode((xmlNodePtr) attr);
1593*6777b538SAndroid Build Coastguard Worker if (attr->tree != NULL)
1594*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(attr->tree);
1595*6777b538SAndroid Build Coastguard Worker if (dict) {
1596*6777b538SAndroid Build Coastguard Worker if ((attr->elem != NULL) && (!xmlDictOwns(dict, attr->elem)))
1597*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->elem);
1598*6777b538SAndroid Build Coastguard Worker if ((attr->name != NULL) && (!xmlDictOwns(dict, attr->name)))
1599*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->name);
1600*6777b538SAndroid Build Coastguard Worker if ((attr->prefix != NULL) && (!xmlDictOwns(dict, attr->prefix)))
1601*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->prefix);
1602*6777b538SAndroid Build Coastguard Worker if ((attr->defaultValue != NULL) &&
1603*6777b538SAndroid Build Coastguard Worker (!xmlDictOwns(dict, attr->defaultValue)))
1604*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->defaultValue);
1605*6777b538SAndroid Build Coastguard Worker } else {
1606*6777b538SAndroid Build Coastguard Worker if (attr->elem != NULL)
1607*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->elem);
1608*6777b538SAndroid Build Coastguard Worker if (attr->name != NULL)
1609*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->name);
1610*6777b538SAndroid Build Coastguard Worker if (attr->defaultValue != NULL)
1611*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->defaultValue);
1612*6777b538SAndroid Build Coastguard Worker if (attr->prefix != NULL)
1613*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) attr->prefix);
1614*6777b538SAndroid Build Coastguard Worker }
1615*6777b538SAndroid Build Coastguard Worker xmlFree(attr);
1616*6777b538SAndroid Build Coastguard Worker }
1617*6777b538SAndroid Build Coastguard Worker
1618*6777b538SAndroid Build Coastguard Worker
1619*6777b538SAndroid Build Coastguard Worker /**
1620*6777b538SAndroid Build Coastguard Worker * xmlAddAttributeDecl:
1621*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
1622*6777b538SAndroid Build Coastguard Worker * @dtd: pointer to the DTD
1623*6777b538SAndroid Build Coastguard Worker * @elem: the element name
1624*6777b538SAndroid Build Coastguard Worker * @name: the attribute name
1625*6777b538SAndroid Build Coastguard Worker * @ns: the attribute namespace prefix
1626*6777b538SAndroid Build Coastguard Worker * @type: the attribute type
1627*6777b538SAndroid Build Coastguard Worker * @def: the attribute default type
1628*6777b538SAndroid Build Coastguard Worker * @defaultValue: the attribute default value
1629*6777b538SAndroid Build Coastguard Worker * @tree: if it's an enumeration, the associated list
1630*6777b538SAndroid Build Coastguard Worker *
1631*6777b538SAndroid Build Coastguard Worker * Register a new attribute declaration
1632*6777b538SAndroid Build Coastguard Worker * Note that @tree becomes the ownership of the DTD
1633*6777b538SAndroid Build Coastguard Worker *
1634*6777b538SAndroid Build Coastguard Worker * Returns NULL if not new, otherwise the attribute decl
1635*6777b538SAndroid Build Coastguard Worker */
1636*6777b538SAndroid Build Coastguard Worker xmlAttributePtr
xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * elem,const xmlChar * name,const xmlChar * ns,xmlAttributeType type,xmlAttributeDefault def,const xmlChar * defaultValue,xmlEnumerationPtr tree)1637*6777b538SAndroid Build Coastguard Worker xmlAddAttributeDecl(xmlValidCtxtPtr ctxt,
1638*6777b538SAndroid Build Coastguard Worker xmlDtdPtr dtd, const xmlChar *elem,
1639*6777b538SAndroid Build Coastguard Worker const xmlChar *name, const xmlChar *ns,
1640*6777b538SAndroid Build Coastguard Worker xmlAttributeType type, xmlAttributeDefault def,
1641*6777b538SAndroid Build Coastguard Worker const xmlChar *defaultValue, xmlEnumerationPtr tree) {
1642*6777b538SAndroid Build Coastguard Worker xmlAttributePtr ret = NULL;
1643*6777b538SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
1644*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDef;
1645*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
1646*6777b538SAndroid Build Coastguard Worker int res;
1647*6777b538SAndroid Build Coastguard Worker
1648*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) {
1649*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1650*6777b538SAndroid Build Coastguard Worker return(NULL);
1651*6777b538SAndroid Build Coastguard Worker }
1652*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
1653*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1654*6777b538SAndroid Build Coastguard Worker return(NULL);
1655*6777b538SAndroid Build Coastguard Worker }
1656*6777b538SAndroid Build Coastguard Worker if (elem == NULL) {
1657*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1658*6777b538SAndroid Build Coastguard Worker return(NULL);
1659*6777b538SAndroid Build Coastguard Worker }
1660*6777b538SAndroid Build Coastguard Worker if (dtd->doc != NULL)
1661*6777b538SAndroid Build Coastguard Worker dict = dtd->doc->dict;
1662*6777b538SAndroid Build Coastguard Worker
1663*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1664*6777b538SAndroid Build Coastguard Worker /*
1665*6777b538SAndroid Build Coastguard Worker * Check the type and possibly the default value.
1666*6777b538SAndroid Build Coastguard Worker */
1667*6777b538SAndroid Build Coastguard Worker switch (type) {
1668*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_CDATA:
1669*6777b538SAndroid Build Coastguard Worker break;
1670*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ID:
1671*6777b538SAndroid Build Coastguard Worker break;
1672*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREF:
1673*6777b538SAndroid Build Coastguard Worker break;
1674*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREFS:
1675*6777b538SAndroid Build Coastguard Worker break;
1676*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITY:
1677*6777b538SAndroid Build Coastguard Worker break;
1678*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITIES:
1679*6777b538SAndroid Build Coastguard Worker break;
1680*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKEN:
1681*6777b538SAndroid Build Coastguard Worker break;
1682*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKENS:
1683*6777b538SAndroid Build Coastguard Worker break;
1684*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENUMERATION:
1685*6777b538SAndroid Build Coastguard Worker break;
1686*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NOTATION:
1687*6777b538SAndroid Build Coastguard Worker break;
1688*6777b538SAndroid Build Coastguard Worker default:
1689*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
1690*6777b538SAndroid Build Coastguard Worker "Internal: ATTRIBUTE struct corrupted invalid type\n",
1691*6777b538SAndroid Build Coastguard Worker NULL);
1692*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1693*6777b538SAndroid Build Coastguard Worker return(NULL);
1694*6777b538SAndroid Build Coastguard Worker }
1695*6777b538SAndroid Build Coastguard Worker if ((defaultValue != NULL) &&
1696*6777b538SAndroid Build Coastguard Worker (!xmlValidateAttributeValueInternal(dtd->doc, type, defaultValue))) {
1697*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_DEFAULT,
1698*6777b538SAndroid Build Coastguard Worker "Attribute %s of %s: invalid default value\n",
1699*6777b538SAndroid Build Coastguard Worker elem, name, defaultValue);
1700*6777b538SAndroid Build Coastguard Worker defaultValue = NULL;
1701*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL)
1702*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
1703*6777b538SAndroid Build Coastguard Worker }
1704*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1705*6777b538SAndroid Build Coastguard Worker
1706*6777b538SAndroid Build Coastguard Worker /*
1707*6777b538SAndroid Build Coastguard Worker * Check first that an attribute defined in the external subset wasn't
1708*6777b538SAndroid Build Coastguard Worker * already defined in the internal subset
1709*6777b538SAndroid Build Coastguard Worker */
1710*6777b538SAndroid Build Coastguard Worker if ((dtd->doc != NULL) && (dtd->doc->extSubset == dtd) &&
1711*6777b538SAndroid Build Coastguard Worker (dtd->doc->intSubset != NULL) &&
1712*6777b538SAndroid Build Coastguard Worker (dtd->doc->intSubset->attributes != NULL)) {
1713*6777b538SAndroid Build Coastguard Worker ret = xmlHashLookup3(dtd->doc->intSubset->attributes, name, ns, elem);
1714*6777b538SAndroid Build Coastguard Worker if (ret != NULL) {
1715*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1716*6777b538SAndroid Build Coastguard Worker return(NULL);
1717*6777b538SAndroid Build Coastguard Worker }
1718*6777b538SAndroid Build Coastguard Worker }
1719*6777b538SAndroid Build Coastguard Worker
1720*6777b538SAndroid Build Coastguard Worker /*
1721*6777b538SAndroid Build Coastguard Worker * Create the Attribute table if needed.
1722*6777b538SAndroid Build Coastguard Worker */
1723*6777b538SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
1724*6777b538SAndroid Build Coastguard Worker if (table == NULL) {
1725*6777b538SAndroid Build Coastguard Worker table = xmlHashCreateDict(0, dict);
1726*6777b538SAndroid Build Coastguard Worker dtd->attributes = (void *) table;
1727*6777b538SAndroid Build Coastguard Worker }
1728*6777b538SAndroid Build Coastguard Worker if (table == NULL)
1729*6777b538SAndroid Build Coastguard Worker goto mem_error;
1730*6777b538SAndroid Build Coastguard Worker
1731*6777b538SAndroid Build Coastguard Worker ret = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
1732*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1733*6777b538SAndroid Build Coastguard Worker goto mem_error;
1734*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlAttribute));
1735*6777b538SAndroid Build Coastguard Worker ret->type = XML_ATTRIBUTE_DECL;
1736*6777b538SAndroid Build Coastguard Worker
1737*6777b538SAndroid Build Coastguard Worker /*
1738*6777b538SAndroid Build Coastguard Worker * fill the structure.
1739*6777b538SAndroid Build Coastguard Worker */
1740*6777b538SAndroid Build Coastguard Worker ret->atype = type;
1741*6777b538SAndroid Build Coastguard Worker /*
1742*6777b538SAndroid Build Coastguard Worker * doc must be set before possible error causes call
1743*6777b538SAndroid Build Coastguard Worker * to xmlFreeAttribute (because it's used to check on
1744*6777b538SAndroid Build Coastguard Worker * dict use)
1745*6777b538SAndroid Build Coastguard Worker */
1746*6777b538SAndroid Build Coastguard Worker ret->doc = dtd->doc;
1747*6777b538SAndroid Build Coastguard Worker if (dict) {
1748*6777b538SAndroid Build Coastguard Worker ret->name = xmlDictLookup(dict, name, -1);
1749*6777b538SAndroid Build Coastguard Worker ret->elem = xmlDictLookup(dict, elem, -1);
1750*6777b538SAndroid Build Coastguard Worker } else {
1751*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(name);
1752*6777b538SAndroid Build Coastguard Worker ret->elem = xmlStrdup(elem);
1753*6777b538SAndroid Build Coastguard Worker }
1754*6777b538SAndroid Build Coastguard Worker if ((ret->name == NULL) || (ret->elem == NULL))
1755*6777b538SAndroid Build Coastguard Worker goto mem_error;
1756*6777b538SAndroid Build Coastguard Worker if (ns != NULL) {
1757*6777b538SAndroid Build Coastguard Worker if (dict)
1758*6777b538SAndroid Build Coastguard Worker ret->prefix = xmlDictLookup(dict, ns, -1);
1759*6777b538SAndroid Build Coastguard Worker else
1760*6777b538SAndroid Build Coastguard Worker ret->prefix = xmlStrdup(ns);
1761*6777b538SAndroid Build Coastguard Worker if (ret->prefix == NULL)
1762*6777b538SAndroid Build Coastguard Worker goto mem_error;
1763*6777b538SAndroid Build Coastguard Worker }
1764*6777b538SAndroid Build Coastguard Worker ret->def = def;
1765*6777b538SAndroid Build Coastguard Worker ret->tree = tree;
1766*6777b538SAndroid Build Coastguard Worker tree = NULL;
1767*6777b538SAndroid Build Coastguard Worker if (defaultValue != NULL) {
1768*6777b538SAndroid Build Coastguard Worker if (dict)
1769*6777b538SAndroid Build Coastguard Worker ret->defaultValue = xmlDictLookup(dict, defaultValue, -1);
1770*6777b538SAndroid Build Coastguard Worker else
1771*6777b538SAndroid Build Coastguard Worker ret->defaultValue = xmlStrdup(defaultValue);
1772*6777b538SAndroid Build Coastguard Worker if (ret->defaultValue == NULL)
1773*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
1774*6777b538SAndroid Build Coastguard Worker }
1775*6777b538SAndroid Build Coastguard Worker
1776*6777b538SAndroid Build Coastguard Worker /*
1777*6777b538SAndroid Build Coastguard Worker * Validity Check:
1778*6777b538SAndroid Build Coastguard Worker * Search the DTD for previous declarations of the ATTLIST
1779*6777b538SAndroid Build Coastguard Worker */
1780*6777b538SAndroid Build Coastguard Worker res = xmlHashAdd3(table, ret->name, ret->prefix, ret->elem, ret);
1781*6777b538SAndroid Build Coastguard Worker if (res <= 0) {
1782*6777b538SAndroid Build Coastguard Worker if (res < 0)
1783*6777b538SAndroid Build Coastguard Worker goto mem_error;
1784*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1785*6777b538SAndroid Build Coastguard Worker /*
1786*6777b538SAndroid Build Coastguard Worker * The attribute is already defined in this DTD.
1787*6777b538SAndroid Build Coastguard Worker */
1788*6777b538SAndroid Build Coastguard Worker xmlErrValidWarning(ctxt, (xmlNodePtr) dtd,
1789*6777b538SAndroid Build Coastguard Worker XML_DTD_ATTRIBUTE_REDEFINED,
1790*6777b538SAndroid Build Coastguard Worker "Attribute %s of element %s: already defined\n",
1791*6777b538SAndroid Build Coastguard Worker name, elem, NULL);
1792*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1793*6777b538SAndroid Build Coastguard Worker xmlFreeAttribute(ret);
1794*6777b538SAndroid Build Coastguard Worker return(NULL);
1795*6777b538SAndroid Build Coastguard Worker }
1796*6777b538SAndroid Build Coastguard Worker
1797*6777b538SAndroid Build Coastguard Worker /*
1798*6777b538SAndroid Build Coastguard Worker * Validity Check:
1799*6777b538SAndroid Build Coastguard Worker * Multiple ID per element
1800*6777b538SAndroid Build Coastguard Worker */
1801*6777b538SAndroid Build Coastguard Worker elemDef = xmlGetDtdElementDesc2(ctxt, dtd, elem);
1802*6777b538SAndroid Build Coastguard Worker if (elemDef != NULL) {
1803*6777b538SAndroid Build Coastguard Worker
1804*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
1805*6777b538SAndroid Build Coastguard Worker if ((type == XML_ATTRIBUTE_ID) &&
1806*6777b538SAndroid Build Coastguard Worker (xmlScanIDAttributeDecl(ctxt, elemDef, 1) != 0)) {
1807*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID,
1808*6777b538SAndroid Build Coastguard Worker "Element %s has too may ID attributes defined : %s\n",
1809*6777b538SAndroid Build Coastguard Worker elem, name, NULL);
1810*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL)
1811*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
1812*6777b538SAndroid Build Coastguard Worker }
1813*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
1814*6777b538SAndroid Build Coastguard Worker
1815*6777b538SAndroid Build Coastguard Worker /*
1816*6777b538SAndroid Build Coastguard Worker * Insert namespace default def first they need to be
1817*6777b538SAndroid Build Coastguard Worker * processed first.
1818*6777b538SAndroid Build Coastguard Worker */
1819*6777b538SAndroid Build Coastguard Worker if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) ||
1820*6777b538SAndroid Build Coastguard Worker ((ret->prefix != NULL &&
1821*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) {
1822*6777b538SAndroid Build Coastguard Worker ret->nexth = elemDef->attributes;
1823*6777b538SAndroid Build Coastguard Worker elemDef->attributes = ret;
1824*6777b538SAndroid Build Coastguard Worker } else {
1825*6777b538SAndroid Build Coastguard Worker xmlAttributePtr tmp = elemDef->attributes;
1826*6777b538SAndroid Build Coastguard Worker
1827*6777b538SAndroid Build Coastguard Worker while ((tmp != NULL) &&
1828*6777b538SAndroid Build Coastguard Worker ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) ||
1829*6777b538SAndroid Build Coastguard Worker ((ret->prefix != NULL &&
1830*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) {
1831*6777b538SAndroid Build Coastguard Worker if (tmp->nexth == NULL)
1832*6777b538SAndroid Build Coastguard Worker break;
1833*6777b538SAndroid Build Coastguard Worker tmp = tmp->nexth;
1834*6777b538SAndroid Build Coastguard Worker }
1835*6777b538SAndroid Build Coastguard Worker if (tmp != NULL) {
1836*6777b538SAndroid Build Coastguard Worker ret->nexth = tmp->nexth;
1837*6777b538SAndroid Build Coastguard Worker tmp->nexth = ret;
1838*6777b538SAndroid Build Coastguard Worker } else {
1839*6777b538SAndroid Build Coastguard Worker ret->nexth = elemDef->attributes;
1840*6777b538SAndroid Build Coastguard Worker elemDef->attributes = ret;
1841*6777b538SAndroid Build Coastguard Worker }
1842*6777b538SAndroid Build Coastguard Worker }
1843*6777b538SAndroid Build Coastguard Worker }
1844*6777b538SAndroid Build Coastguard Worker
1845*6777b538SAndroid Build Coastguard Worker /*
1846*6777b538SAndroid Build Coastguard Worker * Link it to the DTD
1847*6777b538SAndroid Build Coastguard Worker */
1848*6777b538SAndroid Build Coastguard Worker ret->parent = dtd;
1849*6777b538SAndroid Build Coastguard Worker if (dtd->last == NULL) {
1850*6777b538SAndroid Build Coastguard Worker dtd->children = dtd->last = (xmlNodePtr) ret;
1851*6777b538SAndroid Build Coastguard Worker } else {
1852*6777b538SAndroid Build Coastguard Worker dtd->last->next = (xmlNodePtr) ret;
1853*6777b538SAndroid Build Coastguard Worker ret->prev = dtd->last;
1854*6777b538SAndroid Build Coastguard Worker dtd->last = (xmlNodePtr) ret;
1855*6777b538SAndroid Build Coastguard Worker }
1856*6777b538SAndroid Build Coastguard Worker return(ret);
1857*6777b538SAndroid Build Coastguard Worker
1858*6777b538SAndroid Build Coastguard Worker mem_error:
1859*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
1860*6777b538SAndroid Build Coastguard Worker xmlFreeEnumeration(tree);
1861*6777b538SAndroid Build Coastguard Worker xmlFreeAttribute(ret);
1862*6777b538SAndroid Build Coastguard Worker return(NULL);
1863*6777b538SAndroid Build Coastguard Worker }
1864*6777b538SAndroid Build Coastguard Worker
1865*6777b538SAndroid Build Coastguard Worker static void
xmlFreeAttributeTableEntry(void * attr,const xmlChar * name ATTRIBUTE_UNUSED)1866*6777b538SAndroid Build Coastguard Worker xmlFreeAttributeTableEntry(void *attr, const xmlChar *name ATTRIBUTE_UNUSED) {
1867*6777b538SAndroid Build Coastguard Worker xmlFreeAttribute((xmlAttributePtr) attr);
1868*6777b538SAndroid Build Coastguard Worker }
1869*6777b538SAndroid Build Coastguard Worker
1870*6777b538SAndroid Build Coastguard Worker /**
1871*6777b538SAndroid Build Coastguard Worker * xmlFreeAttributeTable:
1872*6777b538SAndroid Build Coastguard Worker * @table: An attribute table
1873*6777b538SAndroid Build Coastguard Worker *
1874*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an entities hash table.
1875*6777b538SAndroid Build Coastguard Worker */
1876*6777b538SAndroid Build Coastguard Worker void
xmlFreeAttributeTable(xmlAttributeTablePtr table)1877*6777b538SAndroid Build Coastguard Worker xmlFreeAttributeTable(xmlAttributeTablePtr table) {
1878*6777b538SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeAttributeTableEntry);
1879*6777b538SAndroid Build Coastguard Worker }
1880*6777b538SAndroid Build Coastguard Worker
1881*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_TREE_ENABLED
1882*6777b538SAndroid Build Coastguard Worker /**
1883*6777b538SAndroid Build Coastguard Worker * xmlCopyAttribute:
1884*6777b538SAndroid Build Coastguard Worker * @attr: An attribute
1885*6777b538SAndroid Build Coastguard Worker *
1886*6777b538SAndroid Build Coastguard Worker * Build a copy of an attribute.
1887*6777b538SAndroid Build Coastguard Worker *
1888*6777b538SAndroid Build Coastguard Worker * Returns the new xmlAttributePtr or NULL in case of error.
1889*6777b538SAndroid Build Coastguard Worker */
1890*6777b538SAndroid Build Coastguard Worker static void *
xmlCopyAttribute(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)1891*6777b538SAndroid Build Coastguard Worker xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
1892*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attr = (xmlAttributePtr) payload;
1893*6777b538SAndroid Build Coastguard Worker xmlAttributePtr cur;
1894*6777b538SAndroid Build Coastguard Worker
1895*6777b538SAndroid Build Coastguard Worker cur = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute));
1896*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
1897*6777b538SAndroid Build Coastguard Worker return(NULL);
1898*6777b538SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlAttribute));
1899*6777b538SAndroid Build Coastguard Worker cur->type = XML_ATTRIBUTE_DECL;
1900*6777b538SAndroid Build Coastguard Worker cur->atype = attr->atype;
1901*6777b538SAndroid Build Coastguard Worker cur->def = attr->def;
1902*6777b538SAndroid Build Coastguard Worker if (attr->tree != NULL) {
1903*6777b538SAndroid Build Coastguard Worker cur->tree = xmlCopyEnumeration(attr->tree);
1904*6777b538SAndroid Build Coastguard Worker if (cur->tree == NULL)
1905*6777b538SAndroid Build Coastguard Worker goto error;
1906*6777b538SAndroid Build Coastguard Worker }
1907*6777b538SAndroid Build Coastguard Worker if (attr->elem != NULL) {
1908*6777b538SAndroid Build Coastguard Worker cur->elem = xmlStrdup(attr->elem);
1909*6777b538SAndroid Build Coastguard Worker if (cur->elem == NULL)
1910*6777b538SAndroid Build Coastguard Worker goto error;
1911*6777b538SAndroid Build Coastguard Worker }
1912*6777b538SAndroid Build Coastguard Worker if (attr->name != NULL) {
1913*6777b538SAndroid Build Coastguard Worker cur->name = xmlStrdup(attr->name);
1914*6777b538SAndroid Build Coastguard Worker if (cur->name == NULL)
1915*6777b538SAndroid Build Coastguard Worker goto error;
1916*6777b538SAndroid Build Coastguard Worker }
1917*6777b538SAndroid Build Coastguard Worker if (attr->prefix != NULL) {
1918*6777b538SAndroid Build Coastguard Worker cur->prefix = xmlStrdup(attr->prefix);
1919*6777b538SAndroid Build Coastguard Worker if (cur->prefix == NULL)
1920*6777b538SAndroid Build Coastguard Worker goto error;
1921*6777b538SAndroid Build Coastguard Worker }
1922*6777b538SAndroid Build Coastguard Worker if (attr->defaultValue != NULL) {
1923*6777b538SAndroid Build Coastguard Worker cur->defaultValue = xmlStrdup(attr->defaultValue);
1924*6777b538SAndroid Build Coastguard Worker if (cur->defaultValue == NULL)
1925*6777b538SAndroid Build Coastguard Worker goto error;
1926*6777b538SAndroid Build Coastguard Worker }
1927*6777b538SAndroid Build Coastguard Worker return(cur);
1928*6777b538SAndroid Build Coastguard Worker
1929*6777b538SAndroid Build Coastguard Worker error:
1930*6777b538SAndroid Build Coastguard Worker xmlFreeAttribute(cur);
1931*6777b538SAndroid Build Coastguard Worker return(NULL);
1932*6777b538SAndroid Build Coastguard Worker }
1933*6777b538SAndroid Build Coastguard Worker
1934*6777b538SAndroid Build Coastguard Worker /**
1935*6777b538SAndroid Build Coastguard Worker * xmlCopyAttributeTable:
1936*6777b538SAndroid Build Coastguard Worker * @table: An attribute table
1937*6777b538SAndroid Build Coastguard Worker *
1938*6777b538SAndroid Build Coastguard Worker * Build a copy of an attribute table.
1939*6777b538SAndroid Build Coastguard Worker *
1940*6777b538SAndroid Build Coastguard Worker * Returns the new xmlAttributeTablePtr or NULL in case of error.
1941*6777b538SAndroid Build Coastguard Worker */
1942*6777b538SAndroid Build Coastguard Worker xmlAttributeTablePtr
xmlCopyAttributeTable(xmlAttributeTablePtr table)1943*6777b538SAndroid Build Coastguard Worker xmlCopyAttributeTable(xmlAttributeTablePtr table) {
1944*6777b538SAndroid Build Coastguard Worker return(xmlHashCopySafe(table, xmlCopyAttribute,
1945*6777b538SAndroid Build Coastguard Worker xmlFreeAttributeTableEntry));
1946*6777b538SAndroid Build Coastguard Worker }
1947*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_TREE_ENABLED */
1948*6777b538SAndroid Build Coastguard Worker
1949*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
1950*6777b538SAndroid Build Coastguard Worker /**
1951*6777b538SAndroid Build Coastguard Worker * xmlDumpAttributeDecl:
1952*6777b538SAndroid Build Coastguard Worker * @buf: the XML buffer output
1953*6777b538SAndroid Build Coastguard Worker * @attr: An attribute declaration
1954*6777b538SAndroid Build Coastguard Worker *
1955*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Use xmlSaveTree.
1956*6777b538SAndroid Build Coastguard Worker *
1957*6777b538SAndroid Build Coastguard Worker * This will dump the content of the attribute declaration as an XML
1958*6777b538SAndroid Build Coastguard Worker * DTD definition
1959*6777b538SAndroid Build Coastguard Worker */
1960*6777b538SAndroid Build Coastguard Worker void
xmlDumpAttributeDecl(xmlBufferPtr buf,xmlAttributePtr attr)1961*6777b538SAndroid Build Coastguard Worker xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
1962*6777b538SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
1963*6777b538SAndroid Build Coastguard Worker
1964*6777b538SAndroid Build Coastguard Worker if ((buf == NULL) || (attr == NULL))
1965*6777b538SAndroid Build Coastguard Worker return;
1966*6777b538SAndroid Build Coastguard Worker
1967*6777b538SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
1968*6777b538SAndroid Build Coastguard Worker xmlSaveTree(save, (xmlNodePtr) attr);
1969*6777b538SAndroid Build Coastguard Worker xmlSaveClose(save);
1970*6777b538SAndroid Build Coastguard Worker }
1971*6777b538SAndroid Build Coastguard Worker
1972*6777b538SAndroid Build Coastguard Worker /**
1973*6777b538SAndroid Build Coastguard Worker * xmlDumpAttributeDeclScan:
1974*6777b538SAndroid Build Coastguard Worker * @attr: An attribute declaration
1975*6777b538SAndroid Build Coastguard Worker * @buf: the XML buffer output
1976*6777b538SAndroid Build Coastguard Worker *
1977*6777b538SAndroid Build Coastguard Worker * This is used with the hash scan function - just reverses arguments
1978*6777b538SAndroid Build Coastguard Worker */
1979*6777b538SAndroid Build Coastguard Worker static void
xmlDumpAttributeDeclScan(void * attr,void * buf,const xmlChar * name ATTRIBUTE_UNUSED)1980*6777b538SAndroid Build Coastguard Worker xmlDumpAttributeDeclScan(void *attr, void *buf,
1981*6777b538SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
1982*6777b538SAndroid Build Coastguard Worker xmlDumpAttributeDecl((xmlBufferPtr) buf, (xmlAttributePtr) attr);
1983*6777b538SAndroid Build Coastguard Worker }
1984*6777b538SAndroid Build Coastguard Worker
1985*6777b538SAndroid Build Coastguard Worker /**
1986*6777b538SAndroid Build Coastguard Worker * xmlDumpAttributeTable:
1987*6777b538SAndroid Build Coastguard Worker * @buf: the XML buffer output
1988*6777b538SAndroid Build Coastguard Worker * @table: An attribute table
1989*6777b538SAndroid Build Coastguard Worker *
1990*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Don't use.
1991*6777b538SAndroid Build Coastguard Worker *
1992*6777b538SAndroid Build Coastguard Worker * This will dump the content of the attribute table as an XML DTD definition
1993*6777b538SAndroid Build Coastguard Worker */
1994*6777b538SAndroid Build Coastguard Worker void
xmlDumpAttributeTable(xmlBufferPtr buf,xmlAttributeTablePtr table)1995*6777b538SAndroid Build Coastguard Worker xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
1996*6777b538SAndroid Build Coastguard Worker if ((buf == NULL) || (table == NULL))
1997*6777b538SAndroid Build Coastguard Worker return;
1998*6777b538SAndroid Build Coastguard Worker xmlHashScan(table, xmlDumpAttributeDeclScan, buf);
1999*6777b538SAndroid Build Coastguard Worker }
2000*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
2001*6777b538SAndroid Build Coastguard Worker
2002*6777b538SAndroid Build Coastguard Worker /************************************************************************
2003*6777b538SAndroid Build Coastguard Worker * *
2004*6777b538SAndroid Build Coastguard Worker * NOTATIONs *
2005*6777b538SAndroid Build Coastguard Worker * *
2006*6777b538SAndroid Build Coastguard Worker ************************************************************************/
2007*6777b538SAndroid Build Coastguard Worker /**
2008*6777b538SAndroid Build Coastguard Worker * xmlFreeNotation:
2009*6777b538SAndroid Build Coastguard Worker * @not: A notation
2010*6777b538SAndroid Build Coastguard Worker *
2011*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an notation definition
2012*6777b538SAndroid Build Coastguard Worker */
2013*6777b538SAndroid Build Coastguard Worker static void
xmlFreeNotation(xmlNotationPtr nota)2014*6777b538SAndroid Build Coastguard Worker xmlFreeNotation(xmlNotationPtr nota) {
2015*6777b538SAndroid Build Coastguard Worker if (nota == NULL) return;
2016*6777b538SAndroid Build Coastguard Worker if (nota->name != NULL)
2017*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) nota->name);
2018*6777b538SAndroid Build Coastguard Worker if (nota->PublicID != NULL)
2019*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) nota->PublicID);
2020*6777b538SAndroid Build Coastguard Worker if (nota->SystemID != NULL)
2021*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) nota->SystemID);
2022*6777b538SAndroid Build Coastguard Worker xmlFree(nota);
2023*6777b538SAndroid Build Coastguard Worker }
2024*6777b538SAndroid Build Coastguard Worker
2025*6777b538SAndroid Build Coastguard Worker
2026*6777b538SAndroid Build Coastguard Worker /**
2027*6777b538SAndroid Build Coastguard Worker * xmlAddNotationDecl:
2028*6777b538SAndroid Build Coastguard Worker * @dtd: pointer to the DTD
2029*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
2030*6777b538SAndroid Build Coastguard Worker * @name: the entity name
2031*6777b538SAndroid Build Coastguard Worker * @PublicID: the public identifier or NULL
2032*6777b538SAndroid Build Coastguard Worker * @SystemID: the system identifier or NULL
2033*6777b538SAndroid Build Coastguard Worker *
2034*6777b538SAndroid Build Coastguard Worker * Register a new notation declaration
2035*6777b538SAndroid Build Coastguard Worker *
2036*6777b538SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the entity
2037*6777b538SAndroid Build Coastguard Worker */
2038*6777b538SAndroid Build Coastguard Worker xmlNotationPtr
xmlAddNotationDecl(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * name,const xmlChar * PublicID,const xmlChar * SystemID)2039*6777b538SAndroid Build Coastguard Worker xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd,
2040*6777b538SAndroid Build Coastguard Worker const xmlChar *name,
2041*6777b538SAndroid Build Coastguard Worker const xmlChar *PublicID, const xmlChar *SystemID) {
2042*6777b538SAndroid Build Coastguard Worker xmlNotationPtr ret = NULL;
2043*6777b538SAndroid Build Coastguard Worker xmlNotationTablePtr table;
2044*6777b538SAndroid Build Coastguard Worker int res;
2045*6777b538SAndroid Build Coastguard Worker
2046*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) {
2047*6777b538SAndroid Build Coastguard Worker return(NULL);
2048*6777b538SAndroid Build Coastguard Worker }
2049*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
2050*6777b538SAndroid Build Coastguard Worker return(NULL);
2051*6777b538SAndroid Build Coastguard Worker }
2052*6777b538SAndroid Build Coastguard Worker if ((PublicID == NULL) && (SystemID == NULL)) {
2053*6777b538SAndroid Build Coastguard Worker return(NULL);
2054*6777b538SAndroid Build Coastguard Worker }
2055*6777b538SAndroid Build Coastguard Worker
2056*6777b538SAndroid Build Coastguard Worker /*
2057*6777b538SAndroid Build Coastguard Worker * Create the Notation table if needed.
2058*6777b538SAndroid Build Coastguard Worker */
2059*6777b538SAndroid Build Coastguard Worker table = (xmlNotationTablePtr) dtd->notations;
2060*6777b538SAndroid Build Coastguard Worker if (table == NULL) {
2061*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
2062*6777b538SAndroid Build Coastguard Worker if (dtd->doc != NULL)
2063*6777b538SAndroid Build Coastguard Worker dict = dtd->doc->dict;
2064*6777b538SAndroid Build Coastguard Worker
2065*6777b538SAndroid Build Coastguard Worker dtd->notations = table = xmlHashCreateDict(0, dict);
2066*6777b538SAndroid Build Coastguard Worker if (table == NULL)
2067*6777b538SAndroid Build Coastguard Worker goto mem_error;
2068*6777b538SAndroid Build Coastguard Worker }
2069*6777b538SAndroid Build Coastguard Worker
2070*6777b538SAndroid Build Coastguard Worker ret = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
2071*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
2072*6777b538SAndroid Build Coastguard Worker goto mem_error;
2073*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlNotation));
2074*6777b538SAndroid Build Coastguard Worker
2075*6777b538SAndroid Build Coastguard Worker /*
2076*6777b538SAndroid Build Coastguard Worker * fill the structure.
2077*6777b538SAndroid Build Coastguard Worker */
2078*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(name);
2079*6777b538SAndroid Build Coastguard Worker if (ret->name == NULL)
2080*6777b538SAndroid Build Coastguard Worker goto mem_error;
2081*6777b538SAndroid Build Coastguard Worker if (SystemID != NULL) {
2082*6777b538SAndroid Build Coastguard Worker ret->SystemID = xmlStrdup(SystemID);
2083*6777b538SAndroid Build Coastguard Worker if (ret->SystemID == NULL)
2084*6777b538SAndroid Build Coastguard Worker goto mem_error;
2085*6777b538SAndroid Build Coastguard Worker }
2086*6777b538SAndroid Build Coastguard Worker if (PublicID != NULL) {
2087*6777b538SAndroid Build Coastguard Worker ret->PublicID = xmlStrdup(PublicID);
2088*6777b538SAndroid Build Coastguard Worker if (ret->PublicID == NULL)
2089*6777b538SAndroid Build Coastguard Worker goto mem_error;
2090*6777b538SAndroid Build Coastguard Worker }
2091*6777b538SAndroid Build Coastguard Worker
2092*6777b538SAndroid Build Coastguard Worker /*
2093*6777b538SAndroid Build Coastguard Worker * Validity Check:
2094*6777b538SAndroid Build Coastguard Worker * Check the DTD for previous declarations of the ATTLIST
2095*6777b538SAndroid Build Coastguard Worker */
2096*6777b538SAndroid Build Coastguard Worker res = xmlHashAdd(table, name, ret);
2097*6777b538SAndroid Build Coastguard Worker if (res <= 0) {
2098*6777b538SAndroid Build Coastguard Worker if (res < 0)
2099*6777b538SAndroid Build Coastguard Worker goto mem_error;
2100*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
2101*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_NOTATION_REDEFINED,
2102*6777b538SAndroid Build Coastguard Worker "xmlAddNotationDecl: %s already defined\n",
2103*6777b538SAndroid Build Coastguard Worker (const char *) name);
2104*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
2105*6777b538SAndroid Build Coastguard Worker xmlFreeNotation(ret);
2106*6777b538SAndroid Build Coastguard Worker return(NULL);
2107*6777b538SAndroid Build Coastguard Worker }
2108*6777b538SAndroid Build Coastguard Worker return(ret);
2109*6777b538SAndroid Build Coastguard Worker
2110*6777b538SAndroid Build Coastguard Worker mem_error:
2111*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
2112*6777b538SAndroid Build Coastguard Worker xmlFreeNotation(ret);
2113*6777b538SAndroid Build Coastguard Worker return(NULL);
2114*6777b538SAndroid Build Coastguard Worker }
2115*6777b538SAndroid Build Coastguard Worker
2116*6777b538SAndroid Build Coastguard Worker static void
xmlFreeNotationTableEntry(void * nota,const xmlChar * name ATTRIBUTE_UNUSED)2117*6777b538SAndroid Build Coastguard Worker xmlFreeNotationTableEntry(void *nota, const xmlChar *name ATTRIBUTE_UNUSED) {
2118*6777b538SAndroid Build Coastguard Worker xmlFreeNotation((xmlNotationPtr) nota);
2119*6777b538SAndroid Build Coastguard Worker }
2120*6777b538SAndroid Build Coastguard Worker
2121*6777b538SAndroid Build Coastguard Worker /**
2122*6777b538SAndroid Build Coastguard Worker * xmlFreeNotationTable:
2123*6777b538SAndroid Build Coastguard Worker * @table: An notation table
2124*6777b538SAndroid Build Coastguard Worker *
2125*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an entities hash table.
2126*6777b538SAndroid Build Coastguard Worker */
2127*6777b538SAndroid Build Coastguard Worker void
xmlFreeNotationTable(xmlNotationTablePtr table)2128*6777b538SAndroid Build Coastguard Worker xmlFreeNotationTable(xmlNotationTablePtr table) {
2129*6777b538SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeNotationTableEntry);
2130*6777b538SAndroid Build Coastguard Worker }
2131*6777b538SAndroid Build Coastguard Worker
2132*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_TREE_ENABLED
2133*6777b538SAndroid Build Coastguard Worker /**
2134*6777b538SAndroid Build Coastguard Worker * xmlCopyNotation:
2135*6777b538SAndroid Build Coastguard Worker * @nota: A notation
2136*6777b538SAndroid Build Coastguard Worker *
2137*6777b538SAndroid Build Coastguard Worker * Build a copy of a notation.
2138*6777b538SAndroid Build Coastguard Worker *
2139*6777b538SAndroid Build Coastguard Worker * Returns the new xmlNotationPtr or NULL in case of error.
2140*6777b538SAndroid Build Coastguard Worker */
2141*6777b538SAndroid Build Coastguard Worker static void *
xmlCopyNotation(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)2142*6777b538SAndroid Build Coastguard Worker xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
2143*6777b538SAndroid Build Coastguard Worker xmlNotationPtr nota = (xmlNotationPtr) payload;
2144*6777b538SAndroid Build Coastguard Worker xmlNotationPtr cur;
2145*6777b538SAndroid Build Coastguard Worker
2146*6777b538SAndroid Build Coastguard Worker cur = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation));
2147*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
2148*6777b538SAndroid Build Coastguard Worker return(NULL);
2149*6777b538SAndroid Build Coastguard Worker memset(cur, 0, sizeof(*cur));
2150*6777b538SAndroid Build Coastguard Worker if (nota->name != NULL) {
2151*6777b538SAndroid Build Coastguard Worker cur->name = xmlStrdup(nota->name);
2152*6777b538SAndroid Build Coastguard Worker if (cur->name == NULL)
2153*6777b538SAndroid Build Coastguard Worker goto error;
2154*6777b538SAndroid Build Coastguard Worker }
2155*6777b538SAndroid Build Coastguard Worker if (nota->PublicID != NULL) {
2156*6777b538SAndroid Build Coastguard Worker cur->PublicID = xmlStrdup(nota->PublicID);
2157*6777b538SAndroid Build Coastguard Worker if (cur->PublicID == NULL)
2158*6777b538SAndroid Build Coastguard Worker goto error;
2159*6777b538SAndroid Build Coastguard Worker }
2160*6777b538SAndroid Build Coastguard Worker if (nota->SystemID != NULL) {
2161*6777b538SAndroid Build Coastguard Worker cur->SystemID = xmlStrdup(nota->SystemID);
2162*6777b538SAndroid Build Coastguard Worker if (cur->SystemID == NULL)
2163*6777b538SAndroid Build Coastguard Worker goto error;
2164*6777b538SAndroid Build Coastguard Worker }
2165*6777b538SAndroid Build Coastguard Worker return(cur);
2166*6777b538SAndroid Build Coastguard Worker
2167*6777b538SAndroid Build Coastguard Worker error:
2168*6777b538SAndroid Build Coastguard Worker xmlFreeNotation(cur);
2169*6777b538SAndroid Build Coastguard Worker return(NULL);
2170*6777b538SAndroid Build Coastguard Worker }
2171*6777b538SAndroid Build Coastguard Worker
2172*6777b538SAndroid Build Coastguard Worker /**
2173*6777b538SAndroid Build Coastguard Worker * xmlCopyNotationTable:
2174*6777b538SAndroid Build Coastguard Worker * @table: A notation table
2175*6777b538SAndroid Build Coastguard Worker *
2176*6777b538SAndroid Build Coastguard Worker * Build a copy of a notation table.
2177*6777b538SAndroid Build Coastguard Worker *
2178*6777b538SAndroid Build Coastguard Worker * Returns the new xmlNotationTablePtr or NULL in case of error.
2179*6777b538SAndroid Build Coastguard Worker */
2180*6777b538SAndroid Build Coastguard Worker xmlNotationTablePtr
xmlCopyNotationTable(xmlNotationTablePtr table)2181*6777b538SAndroid Build Coastguard Worker xmlCopyNotationTable(xmlNotationTablePtr table) {
2182*6777b538SAndroid Build Coastguard Worker return(xmlHashCopySafe(table, xmlCopyNotation, xmlFreeNotationTableEntry));
2183*6777b538SAndroid Build Coastguard Worker }
2184*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_TREE_ENABLED */
2185*6777b538SAndroid Build Coastguard Worker
2186*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_OUTPUT_ENABLED
2187*6777b538SAndroid Build Coastguard Worker /**
2188*6777b538SAndroid Build Coastguard Worker * xmlDumpNotationDecl:
2189*6777b538SAndroid Build Coastguard Worker * @buf: the XML buffer output
2190*6777b538SAndroid Build Coastguard Worker * @nota: A notation declaration
2191*6777b538SAndroid Build Coastguard Worker *
2192*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Don't use.
2193*6777b538SAndroid Build Coastguard Worker *
2194*6777b538SAndroid Build Coastguard Worker * This will dump the content the notation declaration as an XML DTD definition
2195*6777b538SAndroid Build Coastguard Worker */
2196*6777b538SAndroid Build Coastguard Worker void
xmlDumpNotationDecl(xmlBufferPtr buf,xmlNotationPtr nota)2197*6777b538SAndroid Build Coastguard Worker xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) {
2198*6777b538SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
2199*6777b538SAndroid Build Coastguard Worker
2200*6777b538SAndroid Build Coastguard Worker if ((buf == NULL) || (nota == NULL))
2201*6777b538SAndroid Build Coastguard Worker return;
2202*6777b538SAndroid Build Coastguard Worker
2203*6777b538SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
2204*6777b538SAndroid Build Coastguard Worker xmlSaveNotationDecl(save, nota);
2205*6777b538SAndroid Build Coastguard Worker xmlSaveClose(save);
2206*6777b538SAndroid Build Coastguard Worker }
2207*6777b538SAndroid Build Coastguard Worker
2208*6777b538SAndroid Build Coastguard Worker /**
2209*6777b538SAndroid Build Coastguard Worker * xmlDumpNotationTable:
2210*6777b538SAndroid Build Coastguard Worker * @buf: the XML buffer output
2211*6777b538SAndroid Build Coastguard Worker * @table: A notation table
2212*6777b538SAndroid Build Coastguard Worker *
2213*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Don't use.
2214*6777b538SAndroid Build Coastguard Worker *
2215*6777b538SAndroid Build Coastguard Worker * This will dump the content of the notation table as an XML DTD definition
2216*6777b538SAndroid Build Coastguard Worker */
2217*6777b538SAndroid Build Coastguard Worker void
xmlDumpNotationTable(xmlBufferPtr buf,xmlNotationTablePtr table)2218*6777b538SAndroid Build Coastguard Worker xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
2219*6777b538SAndroid Build Coastguard Worker xmlSaveCtxtPtr save;
2220*6777b538SAndroid Build Coastguard Worker
2221*6777b538SAndroid Build Coastguard Worker if ((buf == NULL) || (table == NULL))
2222*6777b538SAndroid Build Coastguard Worker return;
2223*6777b538SAndroid Build Coastguard Worker
2224*6777b538SAndroid Build Coastguard Worker save = xmlSaveToBuffer(buf, NULL, 0);
2225*6777b538SAndroid Build Coastguard Worker xmlSaveNotationTable(save, table);
2226*6777b538SAndroid Build Coastguard Worker xmlSaveClose(save);
2227*6777b538SAndroid Build Coastguard Worker }
2228*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_OUTPUT_ENABLED */
2229*6777b538SAndroid Build Coastguard Worker
2230*6777b538SAndroid Build Coastguard Worker /************************************************************************
2231*6777b538SAndroid Build Coastguard Worker * *
2232*6777b538SAndroid Build Coastguard Worker * IDs *
2233*6777b538SAndroid Build Coastguard Worker * *
2234*6777b538SAndroid Build Coastguard Worker ************************************************************************/
2235*6777b538SAndroid Build Coastguard Worker /**
2236*6777b538SAndroid Build Coastguard Worker * DICT_FREE:
2237*6777b538SAndroid Build Coastguard Worker * @str: a string
2238*6777b538SAndroid Build Coastguard Worker *
2239*6777b538SAndroid Build Coastguard Worker * Free a string if it is not owned by the "dict" dictionary in the
2240*6777b538SAndroid Build Coastguard Worker * current scope
2241*6777b538SAndroid Build Coastguard Worker */
2242*6777b538SAndroid Build Coastguard Worker #define DICT_FREE(str) \
2243*6777b538SAndroid Build Coastguard Worker if ((str) && ((!dict) || \
2244*6777b538SAndroid Build Coastguard Worker (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
2245*6777b538SAndroid Build Coastguard Worker xmlFree((char *)(str));
2246*6777b538SAndroid Build Coastguard Worker
2247*6777b538SAndroid Build Coastguard Worker static int
xmlIsStreaming(xmlValidCtxtPtr ctxt)2248*6777b538SAndroid Build Coastguard Worker xmlIsStreaming(xmlValidCtxtPtr ctxt) {
2249*6777b538SAndroid Build Coastguard Worker xmlParserCtxtPtr pctxt;
2250*6777b538SAndroid Build Coastguard Worker
2251*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
2252*6777b538SAndroid Build Coastguard Worker return(0);
2253*6777b538SAndroid Build Coastguard Worker if ((ctxt->flags & XML_VCTXT_USE_PCTXT) == 0)
2254*6777b538SAndroid Build Coastguard Worker return(0);
2255*6777b538SAndroid Build Coastguard Worker pctxt = ctxt->userData;
2256*6777b538SAndroid Build Coastguard Worker return(pctxt->parseMode == XML_PARSE_READER);
2257*6777b538SAndroid Build Coastguard Worker }
2258*6777b538SAndroid Build Coastguard Worker
2259*6777b538SAndroid Build Coastguard Worker /**
2260*6777b538SAndroid Build Coastguard Worker * xmlFreeID:
2261*6777b538SAndroid Build Coastguard Worker * @not: A id
2262*6777b538SAndroid Build Coastguard Worker *
2263*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an id definition
2264*6777b538SAndroid Build Coastguard Worker */
2265*6777b538SAndroid Build Coastguard Worker static void
xmlFreeID(xmlIDPtr id)2266*6777b538SAndroid Build Coastguard Worker xmlFreeID(xmlIDPtr id) {
2267*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
2268*6777b538SAndroid Build Coastguard Worker
2269*6777b538SAndroid Build Coastguard Worker if (id == NULL) return;
2270*6777b538SAndroid Build Coastguard Worker
2271*6777b538SAndroid Build Coastguard Worker if (id->doc != NULL)
2272*6777b538SAndroid Build Coastguard Worker dict = id->doc->dict;
2273*6777b538SAndroid Build Coastguard Worker
2274*6777b538SAndroid Build Coastguard Worker if (id->value != NULL)
2275*6777b538SAndroid Build Coastguard Worker DICT_FREE(id->value)
2276*6777b538SAndroid Build Coastguard Worker if (id->name != NULL)
2277*6777b538SAndroid Build Coastguard Worker DICT_FREE(id->name)
2278*6777b538SAndroid Build Coastguard Worker xmlFree(id);
2279*6777b538SAndroid Build Coastguard Worker }
2280*6777b538SAndroid Build Coastguard Worker
2281*6777b538SAndroid Build Coastguard Worker
2282*6777b538SAndroid Build Coastguard Worker /**
2283*6777b538SAndroid Build Coastguard Worker * xmlAddIDSafe:
2284*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document
2285*6777b538SAndroid Build Coastguard Worker * @value: the value name
2286*6777b538SAndroid Build Coastguard Worker * @attr: the attribute holding the ID
2287*6777b538SAndroid Build Coastguard Worker * @id: pointer to new xmlIdPtr (optional)
2288*6777b538SAndroid Build Coastguard Worker *
2289*6777b538SAndroid Build Coastguard Worker * Register a new id declaration
2290*6777b538SAndroid Build Coastguard Worker *
2291*6777b538SAndroid Build Coastguard Worker * Returns 1 on success, 0 if the ID already exists, -1 if a memory
2292*6777b538SAndroid Build Coastguard Worker * allocation fails.
2293*6777b538SAndroid Build Coastguard Worker */
2294*6777b538SAndroid Build Coastguard Worker int
xmlAddIDSafe(xmlDocPtr doc,const xmlChar * value,xmlAttrPtr attr,int streaming,xmlIDPtr * id)2295*6777b538SAndroid Build Coastguard Worker xmlAddIDSafe(xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr,
2296*6777b538SAndroid Build Coastguard Worker int streaming, xmlIDPtr *id) {
2297*6777b538SAndroid Build Coastguard Worker xmlIDPtr ret;
2298*6777b538SAndroid Build Coastguard Worker xmlIDTablePtr table;
2299*6777b538SAndroid Build Coastguard Worker
2300*6777b538SAndroid Build Coastguard Worker if (id != NULL)
2301*6777b538SAndroid Build Coastguard Worker *id = NULL;
2302*6777b538SAndroid Build Coastguard Worker
2303*6777b538SAndroid Build Coastguard Worker if (doc == NULL) {
2304*6777b538SAndroid Build Coastguard Worker return(-1);
2305*6777b538SAndroid Build Coastguard Worker }
2306*6777b538SAndroid Build Coastguard Worker if ((value == NULL) || (value[0] == 0)) {
2307*6777b538SAndroid Build Coastguard Worker return(0);
2308*6777b538SAndroid Build Coastguard Worker }
2309*6777b538SAndroid Build Coastguard Worker if (attr == NULL) {
2310*6777b538SAndroid Build Coastguard Worker return(-1);
2311*6777b538SAndroid Build Coastguard Worker }
2312*6777b538SAndroid Build Coastguard Worker
2313*6777b538SAndroid Build Coastguard Worker /*
2314*6777b538SAndroid Build Coastguard Worker * Create the ID table if needed.
2315*6777b538SAndroid Build Coastguard Worker */
2316*6777b538SAndroid Build Coastguard Worker table = (xmlIDTablePtr) doc->ids;
2317*6777b538SAndroid Build Coastguard Worker if (table == NULL) {
2318*6777b538SAndroid Build Coastguard Worker doc->ids = table = xmlHashCreateDict(0, doc->dict);
2319*6777b538SAndroid Build Coastguard Worker if (table == NULL)
2320*6777b538SAndroid Build Coastguard Worker return(-1);
2321*6777b538SAndroid Build Coastguard Worker } else {
2322*6777b538SAndroid Build Coastguard Worker ret = xmlHashLookup(table, value);
2323*6777b538SAndroid Build Coastguard Worker if (ret != NULL) {
2324*6777b538SAndroid Build Coastguard Worker /*
2325*6777b538SAndroid Build Coastguard Worker * Update the attribute unless we are parsing in streaming
2326*6777b538SAndroid Build Coastguard Worker * mode. If the attribute is copied from an entity we want
2327*6777b538SAndroid Build Coastguard Worker * the ID reference the copy.
2328*6777b538SAndroid Build Coastguard Worker */
2329*6777b538SAndroid Build Coastguard Worker if (ret->attr != NULL) {
2330*6777b538SAndroid Build Coastguard Worker ret->attr->id = NULL;
2331*6777b538SAndroid Build Coastguard Worker ret->attr = attr;
2332*6777b538SAndroid Build Coastguard Worker attr->id = ret;
2333*6777b538SAndroid Build Coastguard Worker }
2334*6777b538SAndroid Build Coastguard Worker ret->lineno = xmlGetLineNo(attr->parent);
2335*6777b538SAndroid Build Coastguard Worker attr->atype = XML_ATTRIBUTE_ID;
2336*6777b538SAndroid Build Coastguard Worker return(0);
2337*6777b538SAndroid Build Coastguard Worker }
2338*6777b538SAndroid Build Coastguard Worker }
2339*6777b538SAndroid Build Coastguard Worker
2340*6777b538SAndroid Build Coastguard Worker ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
2341*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
2342*6777b538SAndroid Build Coastguard Worker return(-1);
2343*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(*ret));
2344*6777b538SAndroid Build Coastguard Worker
2345*6777b538SAndroid Build Coastguard Worker /*
2346*6777b538SAndroid Build Coastguard Worker * fill the structure.
2347*6777b538SAndroid Build Coastguard Worker */
2348*6777b538SAndroid Build Coastguard Worker ret->doc = doc;
2349*6777b538SAndroid Build Coastguard Worker ret->value = xmlStrdup(value);
2350*6777b538SAndroid Build Coastguard Worker if (ret->value == NULL) {
2351*6777b538SAndroid Build Coastguard Worker xmlFreeID(ret);
2352*6777b538SAndroid Build Coastguard Worker return(-1);
2353*6777b538SAndroid Build Coastguard Worker }
2354*6777b538SAndroid Build Coastguard Worker if (streaming) {
2355*6777b538SAndroid Build Coastguard Worker /*
2356*6777b538SAndroid Build Coastguard Worker * Operating in streaming mode, attr is gonna disappear
2357*6777b538SAndroid Build Coastguard Worker */
2358*6777b538SAndroid Build Coastguard Worker if (doc->dict != NULL)
2359*6777b538SAndroid Build Coastguard Worker ret->name = xmlDictLookup(doc->dict, attr->name, -1);
2360*6777b538SAndroid Build Coastguard Worker else
2361*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(attr->name);
2362*6777b538SAndroid Build Coastguard Worker if (ret->name == NULL) {
2363*6777b538SAndroid Build Coastguard Worker xmlFreeID(ret);
2364*6777b538SAndroid Build Coastguard Worker return(-1);
2365*6777b538SAndroid Build Coastguard Worker }
2366*6777b538SAndroid Build Coastguard Worker ret->attr = NULL;
2367*6777b538SAndroid Build Coastguard Worker } else {
2368*6777b538SAndroid Build Coastguard Worker ret->attr = attr;
2369*6777b538SAndroid Build Coastguard Worker ret->name = NULL;
2370*6777b538SAndroid Build Coastguard Worker }
2371*6777b538SAndroid Build Coastguard Worker ret->lineno = xmlGetLineNo(attr->parent);
2372*6777b538SAndroid Build Coastguard Worker
2373*6777b538SAndroid Build Coastguard Worker if (xmlHashAddEntry(table, value, ret) < 0) {
2374*6777b538SAndroid Build Coastguard Worker xmlFreeID(ret);
2375*6777b538SAndroid Build Coastguard Worker return(-1);
2376*6777b538SAndroid Build Coastguard Worker }
2377*6777b538SAndroid Build Coastguard Worker
2378*6777b538SAndroid Build Coastguard Worker attr->atype = XML_ATTRIBUTE_ID;
2379*6777b538SAndroid Build Coastguard Worker if (!streaming)
2380*6777b538SAndroid Build Coastguard Worker attr->id = ret;
2381*6777b538SAndroid Build Coastguard Worker
2382*6777b538SAndroid Build Coastguard Worker if (id != NULL)
2383*6777b538SAndroid Build Coastguard Worker *id = ret;
2384*6777b538SAndroid Build Coastguard Worker return(1);
2385*6777b538SAndroid Build Coastguard Worker }
2386*6777b538SAndroid Build Coastguard Worker
2387*6777b538SAndroid Build Coastguard Worker /**
2388*6777b538SAndroid Build Coastguard Worker * xmlAddID:
2389*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
2390*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document
2391*6777b538SAndroid Build Coastguard Worker * @value: the value name
2392*6777b538SAndroid Build Coastguard Worker * @attr: the attribute holding the ID
2393*6777b538SAndroid Build Coastguard Worker *
2394*6777b538SAndroid Build Coastguard Worker * Register a new id declaration
2395*6777b538SAndroid Build Coastguard Worker *
2396*6777b538SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new xmlIDPtr
2397*6777b538SAndroid Build Coastguard Worker */
2398*6777b538SAndroid Build Coastguard Worker xmlIDPtr
xmlAddID(xmlValidCtxtPtr ctxt,xmlDocPtr doc,const xmlChar * value,xmlAttrPtr attr)2399*6777b538SAndroid Build Coastguard Worker xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
2400*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attr) {
2401*6777b538SAndroid Build Coastguard Worker xmlIDPtr id;
2402*6777b538SAndroid Build Coastguard Worker int res;
2403*6777b538SAndroid Build Coastguard Worker
2404*6777b538SAndroid Build Coastguard Worker res = xmlAddIDSafe(doc, value, attr, xmlIsStreaming(ctxt), &id);
2405*6777b538SAndroid Build Coastguard Worker if (res < 0) {
2406*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
2407*6777b538SAndroid Build Coastguard Worker }
2408*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
2409*6777b538SAndroid Build Coastguard Worker else if (res == 0) {
2410*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL) {
2411*6777b538SAndroid Build Coastguard Worker /*
2412*6777b538SAndroid Build Coastguard Worker * The id is already defined in this DTD.
2413*6777b538SAndroid Build Coastguard Worker */
2414*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
2415*6777b538SAndroid Build Coastguard Worker "ID %s already defined\n", value, NULL, NULL);
2416*6777b538SAndroid Build Coastguard Worker }
2417*6777b538SAndroid Build Coastguard Worker }
2418*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
2419*6777b538SAndroid Build Coastguard Worker
2420*6777b538SAndroid Build Coastguard Worker return(id);
2421*6777b538SAndroid Build Coastguard Worker }
2422*6777b538SAndroid Build Coastguard Worker
2423*6777b538SAndroid Build Coastguard Worker static void
xmlFreeIDTableEntry(void * id,const xmlChar * name ATTRIBUTE_UNUSED)2424*6777b538SAndroid Build Coastguard Worker xmlFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
2425*6777b538SAndroid Build Coastguard Worker xmlFreeID((xmlIDPtr) id);
2426*6777b538SAndroid Build Coastguard Worker }
2427*6777b538SAndroid Build Coastguard Worker
2428*6777b538SAndroid Build Coastguard Worker /**
2429*6777b538SAndroid Build Coastguard Worker * xmlFreeIDTable:
2430*6777b538SAndroid Build Coastguard Worker * @table: An id table
2431*6777b538SAndroid Build Coastguard Worker *
2432*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an ID hash table.
2433*6777b538SAndroid Build Coastguard Worker */
2434*6777b538SAndroid Build Coastguard Worker void
xmlFreeIDTable(xmlIDTablePtr table)2435*6777b538SAndroid Build Coastguard Worker xmlFreeIDTable(xmlIDTablePtr table) {
2436*6777b538SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeIDTableEntry);
2437*6777b538SAndroid Build Coastguard Worker }
2438*6777b538SAndroid Build Coastguard Worker
2439*6777b538SAndroid Build Coastguard Worker /**
2440*6777b538SAndroid Build Coastguard Worker * xmlIsID:
2441*6777b538SAndroid Build Coastguard Worker * @doc: the document
2442*6777b538SAndroid Build Coastguard Worker * @elem: the element carrying the attribute
2443*6777b538SAndroid Build Coastguard Worker * @attr: the attribute
2444*6777b538SAndroid Build Coastguard Worker *
2445*6777b538SAndroid Build Coastguard Worker * Determine whether an attribute is of type ID. In case we have DTD(s)
2446*6777b538SAndroid Build Coastguard Worker * then this is done if DTD loading has been requested. In the case
2447*6777b538SAndroid Build Coastguard Worker * of HTML documents parsed with the HTML parser, then ID detection is
2448*6777b538SAndroid Build Coastguard Worker * done systematically.
2449*6777b538SAndroid Build Coastguard Worker *
2450*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the lookup result or -1 if a memory allocation
2451*6777b538SAndroid Build Coastguard Worker * failed.
2452*6777b538SAndroid Build Coastguard Worker */
2453*6777b538SAndroid Build Coastguard Worker int
xmlIsID(xmlDocPtr doc,xmlNodePtr elem,xmlAttrPtr attr)2454*6777b538SAndroid Build Coastguard Worker xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
2455*6777b538SAndroid Build Coastguard Worker if ((attr == NULL) || (attr->name == NULL)) return(0);
2456*6777b538SAndroid Build Coastguard Worker if ((attr->ns != NULL) && (attr->ns->prefix != NULL) &&
2457*6777b538SAndroid Build Coastguard Worker (!strcmp((char *) attr->name, "id")) &&
2458*6777b538SAndroid Build Coastguard Worker (!strcmp((char *) attr->ns->prefix, "xml")))
2459*6777b538SAndroid Build Coastguard Worker return(1);
2460*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(0);
2461*6777b538SAndroid Build Coastguard Worker if ((doc->intSubset == NULL) && (doc->extSubset == NULL) &&
2462*6777b538SAndroid Build Coastguard Worker (doc->type != XML_HTML_DOCUMENT_NODE)) {
2463*6777b538SAndroid Build Coastguard Worker return(0);
2464*6777b538SAndroid Build Coastguard Worker } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2465*6777b538SAndroid Build Coastguard Worker if ((xmlStrEqual(BAD_CAST "id", attr->name)) ||
2466*6777b538SAndroid Build Coastguard Worker ((xmlStrEqual(BAD_CAST "name", attr->name)) &&
2467*6777b538SAndroid Build Coastguard Worker ((elem == NULL) || (xmlStrEqual(elem->name, BAD_CAST "a")))))
2468*6777b538SAndroid Build Coastguard Worker return(1);
2469*6777b538SAndroid Build Coastguard Worker return(0);
2470*6777b538SAndroid Build Coastguard Worker } else if (elem == NULL) {
2471*6777b538SAndroid Build Coastguard Worker return(0);
2472*6777b538SAndroid Build Coastguard Worker } else {
2473*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
2474*6777b538SAndroid Build Coastguard Worker
2475*6777b538SAndroid Build Coastguard Worker xmlChar felem[50];
2476*6777b538SAndroid Build Coastguard Worker xmlChar *fullelemname;
2477*6777b538SAndroid Build Coastguard Worker const xmlChar *aprefix;
2478*6777b538SAndroid Build Coastguard Worker
2479*6777b538SAndroid Build Coastguard Worker fullelemname = (elem->ns != NULL && elem->ns->prefix != NULL) ?
2480*6777b538SAndroid Build Coastguard Worker xmlBuildQName(elem->name, elem->ns->prefix, felem, 50) :
2481*6777b538SAndroid Build Coastguard Worker (xmlChar *)elem->name;
2482*6777b538SAndroid Build Coastguard Worker if (fullelemname == NULL)
2483*6777b538SAndroid Build Coastguard Worker return(-1);
2484*6777b538SAndroid Build Coastguard Worker
2485*6777b538SAndroid Build Coastguard Worker aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
2486*6777b538SAndroid Build Coastguard Worker
2487*6777b538SAndroid Build Coastguard Worker if (fullelemname != NULL) {
2488*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullelemname,
2489*6777b538SAndroid Build Coastguard Worker attr->name, aprefix);
2490*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
2491*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullelemname,
2492*6777b538SAndroid Build Coastguard Worker attr->name, aprefix);
2493*6777b538SAndroid Build Coastguard Worker }
2494*6777b538SAndroid Build Coastguard Worker
2495*6777b538SAndroid Build Coastguard Worker if ((fullelemname != felem) && (fullelemname != elem->name))
2496*6777b538SAndroid Build Coastguard Worker xmlFree(fullelemname);
2497*6777b538SAndroid Build Coastguard Worker
2498*6777b538SAndroid Build Coastguard Worker if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
2499*6777b538SAndroid Build Coastguard Worker return(1);
2500*6777b538SAndroid Build Coastguard Worker }
2501*6777b538SAndroid Build Coastguard Worker return(0);
2502*6777b538SAndroid Build Coastguard Worker }
2503*6777b538SAndroid Build Coastguard Worker
2504*6777b538SAndroid Build Coastguard Worker /**
2505*6777b538SAndroid Build Coastguard Worker * xmlRemoveID:
2506*6777b538SAndroid Build Coastguard Worker * @doc: the document
2507*6777b538SAndroid Build Coastguard Worker * @attr: the attribute
2508*6777b538SAndroid Build Coastguard Worker *
2509*6777b538SAndroid Build Coastguard Worker * Remove the given attribute from the ID table maintained internally.
2510*6777b538SAndroid Build Coastguard Worker *
2511*6777b538SAndroid Build Coastguard Worker * Returns -1 if the lookup failed and 0 otherwise
2512*6777b538SAndroid Build Coastguard Worker */
2513*6777b538SAndroid Build Coastguard Worker int
xmlRemoveID(xmlDocPtr doc,xmlAttrPtr attr)2514*6777b538SAndroid Build Coastguard Worker xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
2515*6777b538SAndroid Build Coastguard Worker xmlIDTablePtr table;
2516*6777b538SAndroid Build Coastguard Worker
2517*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(-1);
2518*6777b538SAndroid Build Coastguard Worker if ((attr == NULL) || (attr->id == NULL)) return(-1);
2519*6777b538SAndroid Build Coastguard Worker
2520*6777b538SAndroid Build Coastguard Worker table = (xmlIDTablePtr) doc->ids;
2521*6777b538SAndroid Build Coastguard Worker if (table == NULL)
2522*6777b538SAndroid Build Coastguard Worker return(-1);
2523*6777b538SAndroid Build Coastguard Worker
2524*6777b538SAndroid Build Coastguard Worker if (xmlHashRemoveEntry(table, attr->id->value, xmlFreeIDTableEntry) < 0)
2525*6777b538SAndroid Build Coastguard Worker return(-1);
2526*6777b538SAndroid Build Coastguard Worker
2527*6777b538SAndroid Build Coastguard Worker attr->atype = 0;
2528*6777b538SAndroid Build Coastguard Worker attr->id = NULL;
2529*6777b538SAndroid Build Coastguard Worker
2530*6777b538SAndroid Build Coastguard Worker return(0);
2531*6777b538SAndroid Build Coastguard Worker }
2532*6777b538SAndroid Build Coastguard Worker
2533*6777b538SAndroid Build Coastguard Worker /**
2534*6777b538SAndroid Build Coastguard Worker * xmlGetID:
2535*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document
2536*6777b538SAndroid Build Coastguard Worker * @ID: the ID value
2537*6777b538SAndroid Build Coastguard Worker *
2538*6777b538SAndroid Build Coastguard Worker * Search the attribute declaring the given ID
2539*6777b538SAndroid Build Coastguard Worker *
2540*6777b538SAndroid Build Coastguard Worker * Returns NULL if not found, otherwise the xmlAttrPtr defining the ID
2541*6777b538SAndroid Build Coastguard Worker */
2542*6777b538SAndroid Build Coastguard Worker xmlAttrPtr
xmlGetID(xmlDocPtr doc,const xmlChar * ID)2543*6777b538SAndroid Build Coastguard Worker xmlGetID(xmlDocPtr doc, const xmlChar *ID) {
2544*6777b538SAndroid Build Coastguard Worker xmlIDTablePtr table;
2545*6777b538SAndroid Build Coastguard Worker xmlIDPtr id;
2546*6777b538SAndroid Build Coastguard Worker
2547*6777b538SAndroid Build Coastguard Worker if (doc == NULL) {
2548*6777b538SAndroid Build Coastguard Worker return(NULL);
2549*6777b538SAndroid Build Coastguard Worker }
2550*6777b538SAndroid Build Coastguard Worker
2551*6777b538SAndroid Build Coastguard Worker if (ID == NULL) {
2552*6777b538SAndroid Build Coastguard Worker return(NULL);
2553*6777b538SAndroid Build Coastguard Worker }
2554*6777b538SAndroid Build Coastguard Worker
2555*6777b538SAndroid Build Coastguard Worker table = (xmlIDTablePtr) doc->ids;
2556*6777b538SAndroid Build Coastguard Worker if (table == NULL)
2557*6777b538SAndroid Build Coastguard Worker return(NULL);
2558*6777b538SAndroid Build Coastguard Worker
2559*6777b538SAndroid Build Coastguard Worker id = xmlHashLookup(table, ID);
2560*6777b538SAndroid Build Coastguard Worker if (id == NULL)
2561*6777b538SAndroid Build Coastguard Worker return(NULL);
2562*6777b538SAndroid Build Coastguard Worker if (id->attr == NULL) {
2563*6777b538SAndroid Build Coastguard Worker /*
2564*6777b538SAndroid Build Coastguard Worker * We are operating on a stream, return a well known reference
2565*6777b538SAndroid Build Coastguard Worker * since the attribute node doesn't exist anymore
2566*6777b538SAndroid Build Coastguard Worker */
2567*6777b538SAndroid Build Coastguard Worker return((xmlAttrPtr) doc);
2568*6777b538SAndroid Build Coastguard Worker }
2569*6777b538SAndroid Build Coastguard Worker return(id->attr);
2570*6777b538SAndroid Build Coastguard Worker }
2571*6777b538SAndroid Build Coastguard Worker
2572*6777b538SAndroid Build Coastguard Worker /************************************************************************
2573*6777b538SAndroid Build Coastguard Worker * *
2574*6777b538SAndroid Build Coastguard Worker * Refs *
2575*6777b538SAndroid Build Coastguard Worker * *
2576*6777b538SAndroid Build Coastguard Worker ************************************************************************/
2577*6777b538SAndroid Build Coastguard Worker typedef struct xmlRemoveMemo_t
2578*6777b538SAndroid Build Coastguard Worker {
2579*6777b538SAndroid Build Coastguard Worker xmlListPtr l;
2580*6777b538SAndroid Build Coastguard Worker xmlAttrPtr ap;
2581*6777b538SAndroid Build Coastguard Worker } xmlRemoveMemo;
2582*6777b538SAndroid Build Coastguard Worker
2583*6777b538SAndroid Build Coastguard Worker typedef xmlRemoveMemo *xmlRemoveMemoPtr;
2584*6777b538SAndroid Build Coastguard Worker
2585*6777b538SAndroid Build Coastguard Worker typedef struct xmlValidateMemo_t
2586*6777b538SAndroid Build Coastguard Worker {
2587*6777b538SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt;
2588*6777b538SAndroid Build Coastguard Worker const xmlChar *name;
2589*6777b538SAndroid Build Coastguard Worker } xmlValidateMemo;
2590*6777b538SAndroid Build Coastguard Worker
2591*6777b538SAndroid Build Coastguard Worker typedef xmlValidateMemo *xmlValidateMemoPtr;
2592*6777b538SAndroid Build Coastguard Worker
2593*6777b538SAndroid Build Coastguard Worker /**
2594*6777b538SAndroid Build Coastguard Worker * xmlFreeRef:
2595*6777b538SAndroid Build Coastguard Worker * @lk: A list link
2596*6777b538SAndroid Build Coastguard Worker *
2597*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by a ref definition
2598*6777b538SAndroid Build Coastguard Worker */
2599*6777b538SAndroid Build Coastguard Worker static void
xmlFreeRef(xmlLinkPtr lk)2600*6777b538SAndroid Build Coastguard Worker xmlFreeRef(xmlLinkPtr lk) {
2601*6777b538SAndroid Build Coastguard Worker xmlRefPtr ref = (xmlRefPtr)xmlLinkGetData(lk);
2602*6777b538SAndroid Build Coastguard Worker if (ref == NULL) return;
2603*6777b538SAndroid Build Coastguard Worker if (ref->value != NULL)
2604*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *)ref->value);
2605*6777b538SAndroid Build Coastguard Worker if (ref->name != NULL)
2606*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *)ref->name);
2607*6777b538SAndroid Build Coastguard Worker xmlFree(ref);
2608*6777b538SAndroid Build Coastguard Worker }
2609*6777b538SAndroid Build Coastguard Worker
2610*6777b538SAndroid Build Coastguard Worker /**
2611*6777b538SAndroid Build Coastguard Worker * xmlFreeRefTableEntry:
2612*6777b538SAndroid Build Coastguard Worker * @list_ref: A list of references.
2613*6777b538SAndroid Build Coastguard Worker *
2614*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by a list of references
2615*6777b538SAndroid Build Coastguard Worker */
2616*6777b538SAndroid Build Coastguard Worker static void
xmlFreeRefTableEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)2617*6777b538SAndroid Build Coastguard Worker xmlFreeRefTableEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
2618*6777b538SAndroid Build Coastguard Worker xmlListPtr list_ref = (xmlListPtr) payload;
2619*6777b538SAndroid Build Coastguard Worker if (list_ref == NULL) return;
2620*6777b538SAndroid Build Coastguard Worker xmlListDelete(list_ref);
2621*6777b538SAndroid Build Coastguard Worker }
2622*6777b538SAndroid Build Coastguard Worker
2623*6777b538SAndroid Build Coastguard Worker /**
2624*6777b538SAndroid Build Coastguard Worker * xmlWalkRemoveRef:
2625*6777b538SAndroid Build Coastguard Worker * @data: Contents of current link
2626*6777b538SAndroid Build Coastguard Worker * @user: Value supplied by the user
2627*6777b538SAndroid Build Coastguard Worker *
2628*6777b538SAndroid Build Coastguard Worker * Returns 0 to abort the walk or 1 to continue
2629*6777b538SAndroid Build Coastguard Worker */
2630*6777b538SAndroid Build Coastguard Worker static int
xmlWalkRemoveRef(const void * data,void * user)2631*6777b538SAndroid Build Coastguard Worker xmlWalkRemoveRef(const void *data, void *user)
2632*6777b538SAndroid Build Coastguard Worker {
2633*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attr0 = ((xmlRefPtr)data)->attr;
2634*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attr1 = ((xmlRemoveMemoPtr)user)->ap;
2635*6777b538SAndroid Build Coastguard Worker xmlListPtr ref_list = ((xmlRemoveMemoPtr)user)->l;
2636*6777b538SAndroid Build Coastguard Worker
2637*6777b538SAndroid Build Coastguard Worker if (attr0 == attr1) { /* Matched: remove and terminate walk */
2638*6777b538SAndroid Build Coastguard Worker xmlListRemoveFirst(ref_list, (void *)data);
2639*6777b538SAndroid Build Coastguard Worker return 0;
2640*6777b538SAndroid Build Coastguard Worker }
2641*6777b538SAndroid Build Coastguard Worker return 1;
2642*6777b538SAndroid Build Coastguard Worker }
2643*6777b538SAndroid Build Coastguard Worker
2644*6777b538SAndroid Build Coastguard Worker /**
2645*6777b538SAndroid Build Coastguard Worker * xmlDummyCompare
2646*6777b538SAndroid Build Coastguard Worker * @data0: Value supplied by the user
2647*6777b538SAndroid Build Coastguard Worker * @data1: Value supplied by the user
2648*6777b538SAndroid Build Coastguard Worker *
2649*6777b538SAndroid Build Coastguard Worker * Do nothing, return 0. Used to create unordered lists.
2650*6777b538SAndroid Build Coastguard Worker */
2651*6777b538SAndroid Build Coastguard Worker static int
xmlDummyCompare(const void * data0 ATTRIBUTE_UNUSED,const void * data1 ATTRIBUTE_UNUSED)2652*6777b538SAndroid Build Coastguard Worker xmlDummyCompare(const void *data0 ATTRIBUTE_UNUSED,
2653*6777b538SAndroid Build Coastguard Worker const void *data1 ATTRIBUTE_UNUSED)
2654*6777b538SAndroid Build Coastguard Worker {
2655*6777b538SAndroid Build Coastguard Worker return (0);
2656*6777b538SAndroid Build Coastguard Worker }
2657*6777b538SAndroid Build Coastguard Worker
2658*6777b538SAndroid Build Coastguard Worker /**
2659*6777b538SAndroid Build Coastguard Worker * xmlAddRef:
2660*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
2661*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document
2662*6777b538SAndroid Build Coastguard Worker * @value: the value name
2663*6777b538SAndroid Build Coastguard Worker * @attr: the attribute holding the Ref
2664*6777b538SAndroid Build Coastguard Worker *
2665*6777b538SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2666*6777b538SAndroid Build Coastguard Worker *
2667*6777b538SAndroid Build Coastguard Worker * Register a new ref declaration
2668*6777b538SAndroid Build Coastguard Worker *
2669*6777b538SAndroid Build Coastguard Worker * Returns NULL if not, otherwise the new xmlRefPtr
2670*6777b538SAndroid Build Coastguard Worker */
2671*6777b538SAndroid Build Coastguard Worker xmlRefPtr
xmlAddRef(xmlValidCtxtPtr ctxt,xmlDocPtr doc,const xmlChar * value,xmlAttrPtr attr)2672*6777b538SAndroid Build Coastguard Worker xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
2673*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attr) {
2674*6777b538SAndroid Build Coastguard Worker xmlRefPtr ret = NULL;
2675*6777b538SAndroid Build Coastguard Worker xmlRefTablePtr table;
2676*6777b538SAndroid Build Coastguard Worker xmlListPtr ref_list;
2677*6777b538SAndroid Build Coastguard Worker
2678*6777b538SAndroid Build Coastguard Worker if (doc == NULL) {
2679*6777b538SAndroid Build Coastguard Worker return(NULL);
2680*6777b538SAndroid Build Coastguard Worker }
2681*6777b538SAndroid Build Coastguard Worker if (value == NULL) {
2682*6777b538SAndroid Build Coastguard Worker return(NULL);
2683*6777b538SAndroid Build Coastguard Worker }
2684*6777b538SAndroid Build Coastguard Worker if (attr == NULL) {
2685*6777b538SAndroid Build Coastguard Worker return(NULL);
2686*6777b538SAndroid Build Coastguard Worker }
2687*6777b538SAndroid Build Coastguard Worker
2688*6777b538SAndroid Build Coastguard Worker /*
2689*6777b538SAndroid Build Coastguard Worker * Create the Ref table if needed.
2690*6777b538SAndroid Build Coastguard Worker */
2691*6777b538SAndroid Build Coastguard Worker table = (xmlRefTablePtr) doc->refs;
2692*6777b538SAndroid Build Coastguard Worker if (table == NULL) {
2693*6777b538SAndroid Build Coastguard Worker doc->refs = table = xmlHashCreateDict(0, doc->dict);
2694*6777b538SAndroid Build Coastguard Worker if (table == NULL)
2695*6777b538SAndroid Build Coastguard Worker goto failed;
2696*6777b538SAndroid Build Coastguard Worker }
2697*6777b538SAndroid Build Coastguard Worker
2698*6777b538SAndroid Build Coastguard Worker ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef));
2699*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
2700*6777b538SAndroid Build Coastguard Worker goto failed;
2701*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(*ret));
2702*6777b538SAndroid Build Coastguard Worker
2703*6777b538SAndroid Build Coastguard Worker /*
2704*6777b538SAndroid Build Coastguard Worker * fill the structure.
2705*6777b538SAndroid Build Coastguard Worker */
2706*6777b538SAndroid Build Coastguard Worker ret->value = xmlStrdup(value);
2707*6777b538SAndroid Build Coastguard Worker if (ret->value == NULL)
2708*6777b538SAndroid Build Coastguard Worker goto failed;
2709*6777b538SAndroid Build Coastguard Worker if (xmlIsStreaming(ctxt)) {
2710*6777b538SAndroid Build Coastguard Worker /*
2711*6777b538SAndroid Build Coastguard Worker * Operating in streaming mode, attr is gonna disappear
2712*6777b538SAndroid Build Coastguard Worker */
2713*6777b538SAndroid Build Coastguard Worker ret->name = xmlStrdup(attr->name);
2714*6777b538SAndroid Build Coastguard Worker if (ret->name == NULL)
2715*6777b538SAndroid Build Coastguard Worker goto failed;
2716*6777b538SAndroid Build Coastguard Worker ret->attr = NULL;
2717*6777b538SAndroid Build Coastguard Worker } else {
2718*6777b538SAndroid Build Coastguard Worker ret->name = NULL;
2719*6777b538SAndroid Build Coastguard Worker ret->attr = attr;
2720*6777b538SAndroid Build Coastguard Worker }
2721*6777b538SAndroid Build Coastguard Worker ret->lineno = xmlGetLineNo(attr->parent);
2722*6777b538SAndroid Build Coastguard Worker
2723*6777b538SAndroid Build Coastguard Worker /* To add a reference :-
2724*6777b538SAndroid Build Coastguard Worker * References are maintained as a list of references,
2725*6777b538SAndroid Build Coastguard Worker * Lookup the entry, if no entry create new nodelist
2726*6777b538SAndroid Build Coastguard Worker * Add the owning node to the NodeList
2727*6777b538SAndroid Build Coastguard Worker * Return the ref
2728*6777b538SAndroid Build Coastguard Worker */
2729*6777b538SAndroid Build Coastguard Worker
2730*6777b538SAndroid Build Coastguard Worker if (NULL == (ref_list = xmlHashLookup(table, value))) {
2731*6777b538SAndroid Build Coastguard Worker int res;
2732*6777b538SAndroid Build Coastguard Worker
2733*6777b538SAndroid Build Coastguard Worker if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare)))
2734*6777b538SAndroid Build Coastguard Worker goto failed;
2735*6777b538SAndroid Build Coastguard Worker res = xmlHashAdd(table, value, ref_list);
2736*6777b538SAndroid Build Coastguard Worker if (res <= 0) {
2737*6777b538SAndroid Build Coastguard Worker xmlListDelete(ref_list);
2738*6777b538SAndroid Build Coastguard Worker goto failed;
2739*6777b538SAndroid Build Coastguard Worker }
2740*6777b538SAndroid Build Coastguard Worker }
2741*6777b538SAndroid Build Coastguard Worker if (xmlListAppend(ref_list, ret) != 0)
2742*6777b538SAndroid Build Coastguard Worker goto failed;
2743*6777b538SAndroid Build Coastguard Worker return(ret);
2744*6777b538SAndroid Build Coastguard Worker
2745*6777b538SAndroid Build Coastguard Worker failed:
2746*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
2747*6777b538SAndroid Build Coastguard Worker if (ret != NULL) {
2748*6777b538SAndroid Build Coastguard Worker if (ret->value != NULL)
2749*6777b538SAndroid Build Coastguard Worker xmlFree((char *)ret->value);
2750*6777b538SAndroid Build Coastguard Worker if (ret->name != NULL)
2751*6777b538SAndroid Build Coastguard Worker xmlFree((char *)ret->name);
2752*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
2753*6777b538SAndroid Build Coastguard Worker }
2754*6777b538SAndroid Build Coastguard Worker return(NULL);
2755*6777b538SAndroid Build Coastguard Worker }
2756*6777b538SAndroid Build Coastguard Worker
2757*6777b538SAndroid Build Coastguard Worker /**
2758*6777b538SAndroid Build Coastguard Worker * xmlFreeRefTable:
2759*6777b538SAndroid Build Coastguard Worker * @table: An ref table
2760*6777b538SAndroid Build Coastguard Worker *
2761*6777b538SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2762*6777b538SAndroid Build Coastguard Worker *
2763*6777b538SAndroid Build Coastguard Worker * Deallocate the memory used by an Ref hash table.
2764*6777b538SAndroid Build Coastguard Worker */
2765*6777b538SAndroid Build Coastguard Worker void
xmlFreeRefTable(xmlRefTablePtr table)2766*6777b538SAndroid Build Coastguard Worker xmlFreeRefTable(xmlRefTablePtr table) {
2767*6777b538SAndroid Build Coastguard Worker xmlHashFree(table, xmlFreeRefTableEntry);
2768*6777b538SAndroid Build Coastguard Worker }
2769*6777b538SAndroid Build Coastguard Worker
2770*6777b538SAndroid Build Coastguard Worker /**
2771*6777b538SAndroid Build Coastguard Worker * xmlIsRef:
2772*6777b538SAndroid Build Coastguard Worker * @doc: the document
2773*6777b538SAndroid Build Coastguard Worker * @elem: the element carrying the attribute
2774*6777b538SAndroid Build Coastguard Worker * @attr: the attribute
2775*6777b538SAndroid Build Coastguard Worker *
2776*6777b538SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2777*6777b538SAndroid Build Coastguard Worker *
2778*6777b538SAndroid Build Coastguard Worker * Determine whether an attribute is of type Ref. In case we have DTD(s)
2779*6777b538SAndroid Build Coastguard Worker * then this is simple, otherwise we use an heuristic: name Ref (upper
2780*6777b538SAndroid Build Coastguard Worker * or lowercase).
2781*6777b538SAndroid Build Coastguard Worker *
2782*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the lookup result
2783*6777b538SAndroid Build Coastguard Worker */
2784*6777b538SAndroid Build Coastguard Worker int
xmlIsRef(xmlDocPtr doc,xmlNodePtr elem,xmlAttrPtr attr)2785*6777b538SAndroid Build Coastguard Worker xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
2786*6777b538SAndroid Build Coastguard Worker if (attr == NULL)
2787*6777b538SAndroid Build Coastguard Worker return(0);
2788*6777b538SAndroid Build Coastguard Worker if (doc == NULL) {
2789*6777b538SAndroid Build Coastguard Worker doc = attr->doc;
2790*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(0);
2791*6777b538SAndroid Build Coastguard Worker }
2792*6777b538SAndroid Build Coastguard Worker
2793*6777b538SAndroid Build Coastguard Worker if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
2794*6777b538SAndroid Build Coastguard Worker return(0);
2795*6777b538SAndroid Build Coastguard Worker } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2796*6777b538SAndroid Build Coastguard Worker /* TODO @@@ */
2797*6777b538SAndroid Build Coastguard Worker return(0);
2798*6777b538SAndroid Build Coastguard Worker } else {
2799*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attrDecl;
2800*6777b538SAndroid Build Coastguard Worker const xmlChar *aprefix;
2801*6777b538SAndroid Build Coastguard Worker
2802*6777b538SAndroid Build Coastguard Worker if (elem == NULL) return(0);
2803*6777b538SAndroid Build Coastguard Worker aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
2804*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, attr->name,
2805*6777b538SAndroid Build Coastguard Worker aprefix);
2806*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
2807*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, attr->name,
2808*6777b538SAndroid Build Coastguard Worker aprefix);
2809*6777b538SAndroid Build Coastguard Worker
2810*6777b538SAndroid Build Coastguard Worker if ((attrDecl != NULL) &&
2811*6777b538SAndroid Build Coastguard Worker (attrDecl->atype == XML_ATTRIBUTE_IDREF ||
2812*6777b538SAndroid Build Coastguard Worker attrDecl->atype == XML_ATTRIBUTE_IDREFS))
2813*6777b538SAndroid Build Coastguard Worker return(1);
2814*6777b538SAndroid Build Coastguard Worker }
2815*6777b538SAndroid Build Coastguard Worker return(0);
2816*6777b538SAndroid Build Coastguard Worker }
2817*6777b538SAndroid Build Coastguard Worker
2818*6777b538SAndroid Build Coastguard Worker /**
2819*6777b538SAndroid Build Coastguard Worker * xmlRemoveRef:
2820*6777b538SAndroid Build Coastguard Worker * @doc: the document
2821*6777b538SAndroid Build Coastguard Worker * @attr: the attribute
2822*6777b538SAndroid Build Coastguard Worker *
2823*6777b538SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2824*6777b538SAndroid Build Coastguard Worker *
2825*6777b538SAndroid Build Coastguard Worker * Remove the given attribute from the Ref table maintained internally.
2826*6777b538SAndroid Build Coastguard Worker *
2827*6777b538SAndroid Build Coastguard Worker * Returns -1 if the lookup failed and 0 otherwise
2828*6777b538SAndroid Build Coastguard Worker */
2829*6777b538SAndroid Build Coastguard Worker int
xmlRemoveRef(xmlDocPtr doc,xmlAttrPtr attr)2830*6777b538SAndroid Build Coastguard Worker xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
2831*6777b538SAndroid Build Coastguard Worker xmlListPtr ref_list;
2832*6777b538SAndroid Build Coastguard Worker xmlRefTablePtr table;
2833*6777b538SAndroid Build Coastguard Worker xmlChar *ID;
2834*6777b538SAndroid Build Coastguard Worker xmlRemoveMemo target;
2835*6777b538SAndroid Build Coastguard Worker
2836*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(-1);
2837*6777b538SAndroid Build Coastguard Worker if (attr == NULL) return(-1);
2838*6777b538SAndroid Build Coastguard Worker
2839*6777b538SAndroid Build Coastguard Worker table = (xmlRefTablePtr) doc->refs;
2840*6777b538SAndroid Build Coastguard Worker if (table == NULL)
2841*6777b538SAndroid Build Coastguard Worker return(-1);
2842*6777b538SAndroid Build Coastguard Worker
2843*6777b538SAndroid Build Coastguard Worker ID = xmlNodeListGetString(doc, attr->children, 1);
2844*6777b538SAndroid Build Coastguard Worker if (ID == NULL)
2845*6777b538SAndroid Build Coastguard Worker return(-1);
2846*6777b538SAndroid Build Coastguard Worker
2847*6777b538SAndroid Build Coastguard Worker ref_list = xmlHashLookup(table, ID);
2848*6777b538SAndroid Build Coastguard Worker if(ref_list == NULL) {
2849*6777b538SAndroid Build Coastguard Worker xmlFree(ID);
2850*6777b538SAndroid Build Coastguard Worker return (-1);
2851*6777b538SAndroid Build Coastguard Worker }
2852*6777b538SAndroid Build Coastguard Worker
2853*6777b538SAndroid Build Coastguard Worker /* At this point, ref_list refers to a list of references which
2854*6777b538SAndroid Build Coastguard Worker * have the same key as the supplied attr. Our list of references
2855*6777b538SAndroid Build Coastguard Worker * is ordered by reference address and we don't have that information
2856*6777b538SAndroid Build Coastguard Worker * here to use when removing. We'll have to walk the list and
2857*6777b538SAndroid Build Coastguard Worker * check for a matching attribute, when we find one stop the walk
2858*6777b538SAndroid Build Coastguard Worker * and remove the entry.
2859*6777b538SAndroid Build Coastguard Worker * The list is ordered by reference, so that means we don't have the
2860*6777b538SAndroid Build Coastguard Worker * key. Passing the list and the reference to the walker means we
2861*6777b538SAndroid Build Coastguard Worker * will have enough data to be able to remove the entry.
2862*6777b538SAndroid Build Coastguard Worker */
2863*6777b538SAndroid Build Coastguard Worker target.l = ref_list;
2864*6777b538SAndroid Build Coastguard Worker target.ap = attr;
2865*6777b538SAndroid Build Coastguard Worker
2866*6777b538SAndroid Build Coastguard Worker /* Remove the supplied attr from our list */
2867*6777b538SAndroid Build Coastguard Worker xmlListWalk(ref_list, xmlWalkRemoveRef, &target);
2868*6777b538SAndroid Build Coastguard Worker
2869*6777b538SAndroid Build Coastguard Worker /*If the list is empty then remove the list entry in the hash */
2870*6777b538SAndroid Build Coastguard Worker if (xmlListEmpty(ref_list))
2871*6777b538SAndroid Build Coastguard Worker xmlHashUpdateEntry(table, ID, NULL, xmlFreeRefTableEntry);
2872*6777b538SAndroid Build Coastguard Worker xmlFree(ID);
2873*6777b538SAndroid Build Coastguard Worker return(0);
2874*6777b538SAndroid Build Coastguard Worker }
2875*6777b538SAndroid Build Coastguard Worker
2876*6777b538SAndroid Build Coastguard Worker /**
2877*6777b538SAndroid Build Coastguard Worker * xmlGetRefs:
2878*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document
2879*6777b538SAndroid Build Coastguard Worker * @ID: the ID value
2880*6777b538SAndroid Build Coastguard Worker *
2881*6777b538SAndroid Build Coastguard Worker * DEPRECATED, do not use. This function will be removed from the public API.
2882*6777b538SAndroid Build Coastguard Worker *
2883*6777b538SAndroid Build Coastguard Worker * Find the set of references for the supplied ID.
2884*6777b538SAndroid Build Coastguard Worker *
2885*6777b538SAndroid Build Coastguard Worker * Returns NULL if not found, otherwise node set for the ID.
2886*6777b538SAndroid Build Coastguard Worker */
2887*6777b538SAndroid Build Coastguard Worker xmlListPtr
xmlGetRefs(xmlDocPtr doc,const xmlChar * ID)2888*6777b538SAndroid Build Coastguard Worker xmlGetRefs(xmlDocPtr doc, const xmlChar *ID) {
2889*6777b538SAndroid Build Coastguard Worker xmlRefTablePtr table;
2890*6777b538SAndroid Build Coastguard Worker
2891*6777b538SAndroid Build Coastguard Worker if (doc == NULL) {
2892*6777b538SAndroid Build Coastguard Worker return(NULL);
2893*6777b538SAndroid Build Coastguard Worker }
2894*6777b538SAndroid Build Coastguard Worker
2895*6777b538SAndroid Build Coastguard Worker if (ID == NULL) {
2896*6777b538SAndroid Build Coastguard Worker return(NULL);
2897*6777b538SAndroid Build Coastguard Worker }
2898*6777b538SAndroid Build Coastguard Worker
2899*6777b538SAndroid Build Coastguard Worker table = (xmlRefTablePtr) doc->refs;
2900*6777b538SAndroid Build Coastguard Worker if (table == NULL)
2901*6777b538SAndroid Build Coastguard Worker return(NULL);
2902*6777b538SAndroid Build Coastguard Worker
2903*6777b538SAndroid Build Coastguard Worker return (xmlHashLookup(table, ID));
2904*6777b538SAndroid Build Coastguard Worker }
2905*6777b538SAndroid Build Coastguard Worker
2906*6777b538SAndroid Build Coastguard Worker /************************************************************************
2907*6777b538SAndroid Build Coastguard Worker * *
2908*6777b538SAndroid Build Coastguard Worker * Routines for validity checking *
2909*6777b538SAndroid Build Coastguard Worker * *
2910*6777b538SAndroid Build Coastguard Worker ************************************************************************/
2911*6777b538SAndroid Build Coastguard Worker
2912*6777b538SAndroid Build Coastguard Worker /**
2913*6777b538SAndroid Build Coastguard Worker * xmlGetDtdElementDesc:
2914*6777b538SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
2915*6777b538SAndroid Build Coastguard Worker * @name: the element name
2916*6777b538SAndroid Build Coastguard Worker *
2917*6777b538SAndroid Build Coastguard Worker * Search the DTD for the description of this element
2918*6777b538SAndroid Build Coastguard Worker *
2919*6777b538SAndroid Build Coastguard Worker * NOTE: A NULL return value can also mean that a memory allocation failed.
2920*6777b538SAndroid Build Coastguard Worker *
2921*6777b538SAndroid Build Coastguard Worker * returns the xmlElementPtr if found or NULL
2922*6777b538SAndroid Build Coastguard Worker */
2923*6777b538SAndroid Build Coastguard Worker
2924*6777b538SAndroid Build Coastguard Worker xmlElementPtr
xmlGetDtdElementDesc(xmlDtdPtr dtd,const xmlChar * name)2925*6777b538SAndroid Build Coastguard Worker xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
2926*6777b538SAndroid Build Coastguard Worker xmlElementTablePtr table;
2927*6777b538SAndroid Build Coastguard Worker xmlElementPtr cur;
2928*6777b538SAndroid Build Coastguard Worker xmlChar *uqname = NULL, *prefix = NULL;
2929*6777b538SAndroid Build Coastguard Worker
2930*6777b538SAndroid Build Coastguard Worker if ((dtd == NULL) || (name == NULL)) return(NULL);
2931*6777b538SAndroid Build Coastguard Worker if (dtd->elements == NULL)
2932*6777b538SAndroid Build Coastguard Worker return(NULL);
2933*6777b538SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
2934*6777b538SAndroid Build Coastguard Worker
2935*6777b538SAndroid Build Coastguard Worker uqname = xmlSplitQName2(name, &prefix);
2936*6777b538SAndroid Build Coastguard Worker if (uqname != NULL)
2937*6777b538SAndroid Build Coastguard Worker name = uqname;
2938*6777b538SAndroid Build Coastguard Worker cur = xmlHashLookup2(table, name, prefix);
2939*6777b538SAndroid Build Coastguard Worker if (prefix != NULL) xmlFree(prefix);
2940*6777b538SAndroid Build Coastguard Worker if (uqname != NULL) xmlFree(uqname);
2941*6777b538SAndroid Build Coastguard Worker return(cur);
2942*6777b538SAndroid Build Coastguard Worker }
2943*6777b538SAndroid Build Coastguard Worker
2944*6777b538SAndroid Build Coastguard Worker /**
2945*6777b538SAndroid Build Coastguard Worker * xmlGetDtdElementDesc2:
2946*6777b538SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
2947*6777b538SAndroid Build Coastguard Worker * @name: the element name
2948*6777b538SAndroid Build Coastguard Worker * @create: create an empty description if not found
2949*6777b538SAndroid Build Coastguard Worker *
2950*6777b538SAndroid Build Coastguard Worker * Search the DTD for the description of this element
2951*6777b538SAndroid Build Coastguard Worker *
2952*6777b538SAndroid Build Coastguard Worker * returns the xmlElementPtr if found or NULL
2953*6777b538SAndroid Build Coastguard Worker */
2954*6777b538SAndroid Build Coastguard Worker
2955*6777b538SAndroid Build Coastguard Worker static xmlElementPtr
xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * name)2956*6777b538SAndroid Build Coastguard Worker xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name) {
2957*6777b538SAndroid Build Coastguard Worker xmlElementTablePtr table;
2958*6777b538SAndroid Build Coastguard Worker xmlElementPtr cur = NULL;
2959*6777b538SAndroid Build Coastguard Worker const xmlChar *localName;
2960*6777b538SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
2961*6777b538SAndroid Build Coastguard Worker
2962*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
2963*6777b538SAndroid Build Coastguard Worker
2964*6777b538SAndroid Build Coastguard Worker /*
2965*6777b538SAndroid Build Coastguard Worker * Create the Element table if needed.
2966*6777b538SAndroid Build Coastguard Worker */
2967*6777b538SAndroid Build Coastguard Worker if (dtd->elements == NULL) {
2968*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
2969*6777b538SAndroid Build Coastguard Worker
2970*6777b538SAndroid Build Coastguard Worker if (dtd->doc != NULL)
2971*6777b538SAndroid Build Coastguard Worker dict = dtd->doc->dict;
2972*6777b538SAndroid Build Coastguard Worker
2973*6777b538SAndroid Build Coastguard Worker dtd->elements = xmlHashCreateDict(0, dict);
2974*6777b538SAndroid Build Coastguard Worker if (dtd->elements == NULL)
2975*6777b538SAndroid Build Coastguard Worker goto mem_error;
2976*6777b538SAndroid Build Coastguard Worker }
2977*6777b538SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
2978*6777b538SAndroid Build Coastguard Worker
2979*6777b538SAndroid Build Coastguard Worker localName = xmlSplitQName4(name, &prefix);
2980*6777b538SAndroid Build Coastguard Worker if (localName == NULL)
2981*6777b538SAndroid Build Coastguard Worker goto mem_error;
2982*6777b538SAndroid Build Coastguard Worker cur = xmlHashLookup2(table, localName, prefix);
2983*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
2984*6777b538SAndroid Build Coastguard Worker cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
2985*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
2986*6777b538SAndroid Build Coastguard Worker goto mem_error;
2987*6777b538SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlElement));
2988*6777b538SAndroid Build Coastguard Worker cur->type = XML_ELEMENT_DECL;
2989*6777b538SAndroid Build Coastguard Worker
2990*6777b538SAndroid Build Coastguard Worker /*
2991*6777b538SAndroid Build Coastguard Worker * fill the structure.
2992*6777b538SAndroid Build Coastguard Worker */
2993*6777b538SAndroid Build Coastguard Worker cur->name = xmlStrdup(localName);
2994*6777b538SAndroid Build Coastguard Worker if (cur->name == NULL)
2995*6777b538SAndroid Build Coastguard Worker goto mem_error;
2996*6777b538SAndroid Build Coastguard Worker cur->prefix = prefix;
2997*6777b538SAndroid Build Coastguard Worker prefix = NULL;
2998*6777b538SAndroid Build Coastguard Worker cur->etype = XML_ELEMENT_TYPE_UNDEFINED;
2999*6777b538SAndroid Build Coastguard Worker
3000*6777b538SAndroid Build Coastguard Worker if (xmlHashAdd2(table, localName, cur->prefix, cur) <= 0)
3001*6777b538SAndroid Build Coastguard Worker goto mem_error;
3002*6777b538SAndroid Build Coastguard Worker }
3003*6777b538SAndroid Build Coastguard Worker
3004*6777b538SAndroid Build Coastguard Worker if (prefix != NULL)
3005*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
3006*6777b538SAndroid Build Coastguard Worker return(cur);
3007*6777b538SAndroid Build Coastguard Worker
3008*6777b538SAndroid Build Coastguard Worker mem_error:
3009*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
3010*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
3011*6777b538SAndroid Build Coastguard Worker xmlFreeElement(cur);
3012*6777b538SAndroid Build Coastguard Worker return(NULL);
3013*6777b538SAndroid Build Coastguard Worker }
3014*6777b538SAndroid Build Coastguard Worker
3015*6777b538SAndroid Build Coastguard Worker /**
3016*6777b538SAndroid Build Coastguard Worker * xmlGetDtdQElementDesc:
3017*6777b538SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3018*6777b538SAndroid Build Coastguard Worker * @name: the element name
3019*6777b538SAndroid Build Coastguard Worker * @prefix: the element namespace prefix
3020*6777b538SAndroid Build Coastguard Worker *
3021*6777b538SAndroid Build Coastguard Worker * Search the DTD for the description of this element
3022*6777b538SAndroid Build Coastguard Worker *
3023*6777b538SAndroid Build Coastguard Worker * returns the xmlElementPtr if found or NULL
3024*6777b538SAndroid Build Coastguard Worker */
3025*6777b538SAndroid Build Coastguard Worker
3026*6777b538SAndroid Build Coastguard Worker xmlElementPtr
xmlGetDtdQElementDesc(xmlDtdPtr dtd,const xmlChar * name,const xmlChar * prefix)3027*6777b538SAndroid Build Coastguard Worker xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name,
3028*6777b538SAndroid Build Coastguard Worker const xmlChar *prefix) {
3029*6777b538SAndroid Build Coastguard Worker xmlElementTablePtr table;
3030*6777b538SAndroid Build Coastguard Worker
3031*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
3032*6777b538SAndroid Build Coastguard Worker if (dtd->elements == NULL) return(NULL);
3033*6777b538SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
3034*6777b538SAndroid Build Coastguard Worker
3035*6777b538SAndroid Build Coastguard Worker return(xmlHashLookup2(table, name, prefix));
3036*6777b538SAndroid Build Coastguard Worker }
3037*6777b538SAndroid Build Coastguard Worker
3038*6777b538SAndroid Build Coastguard Worker /**
3039*6777b538SAndroid Build Coastguard Worker * xmlGetDtdAttrDesc:
3040*6777b538SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3041*6777b538SAndroid Build Coastguard Worker * @elem: the element name
3042*6777b538SAndroid Build Coastguard Worker * @name: the attribute name
3043*6777b538SAndroid Build Coastguard Worker *
3044*6777b538SAndroid Build Coastguard Worker * Search the DTD for the description of this attribute on
3045*6777b538SAndroid Build Coastguard Worker * this element.
3046*6777b538SAndroid Build Coastguard Worker *
3047*6777b538SAndroid Build Coastguard Worker * returns the xmlAttributePtr if found or NULL
3048*6777b538SAndroid Build Coastguard Worker */
3049*6777b538SAndroid Build Coastguard Worker
3050*6777b538SAndroid Build Coastguard Worker xmlAttributePtr
xmlGetDtdAttrDesc(xmlDtdPtr dtd,const xmlChar * elem,const xmlChar * name)3051*6777b538SAndroid Build Coastguard Worker xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) {
3052*6777b538SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
3053*6777b538SAndroid Build Coastguard Worker xmlAttributePtr cur;
3054*6777b538SAndroid Build Coastguard Worker xmlChar *uqname = NULL, *prefix = NULL;
3055*6777b538SAndroid Build Coastguard Worker
3056*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
3057*6777b538SAndroid Build Coastguard Worker if (dtd->attributes == NULL) return(NULL);
3058*6777b538SAndroid Build Coastguard Worker
3059*6777b538SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
3060*6777b538SAndroid Build Coastguard Worker if (table == NULL)
3061*6777b538SAndroid Build Coastguard Worker return(NULL);
3062*6777b538SAndroid Build Coastguard Worker
3063*6777b538SAndroid Build Coastguard Worker uqname = xmlSplitQName2(name, &prefix);
3064*6777b538SAndroid Build Coastguard Worker
3065*6777b538SAndroid Build Coastguard Worker if (uqname != NULL) {
3066*6777b538SAndroid Build Coastguard Worker cur = xmlHashLookup3(table, uqname, prefix, elem);
3067*6777b538SAndroid Build Coastguard Worker if (prefix != NULL) xmlFree(prefix);
3068*6777b538SAndroid Build Coastguard Worker if (uqname != NULL) xmlFree(uqname);
3069*6777b538SAndroid Build Coastguard Worker } else
3070*6777b538SAndroid Build Coastguard Worker cur = xmlHashLookup3(table, name, NULL, elem);
3071*6777b538SAndroid Build Coastguard Worker return(cur);
3072*6777b538SAndroid Build Coastguard Worker }
3073*6777b538SAndroid Build Coastguard Worker
3074*6777b538SAndroid Build Coastguard Worker /**
3075*6777b538SAndroid Build Coastguard Worker * xmlGetDtdQAttrDesc:
3076*6777b538SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3077*6777b538SAndroid Build Coastguard Worker * @elem: the element name
3078*6777b538SAndroid Build Coastguard Worker * @name: the attribute name
3079*6777b538SAndroid Build Coastguard Worker * @prefix: the attribute namespace prefix
3080*6777b538SAndroid Build Coastguard Worker *
3081*6777b538SAndroid Build Coastguard Worker * Search the DTD for the description of this qualified attribute on
3082*6777b538SAndroid Build Coastguard Worker * this element.
3083*6777b538SAndroid Build Coastguard Worker *
3084*6777b538SAndroid Build Coastguard Worker * returns the xmlAttributePtr if found or NULL
3085*6777b538SAndroid Build Coastguard Worker */
3086*6777b538SAndroid Build Coastguard Worker
3087*6777b538SAndroid Build Coastguard Worker xmlAttributePtr
xmlGetDtdQAttrDesc(xmlDtdPtr dtd,const xmlChar * elem,const xmlChar * name,const xmlChar * prefix)3088*6777b538SAndroid Build Coastguard Worker xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name,
3089*6777b538SAndroid Build Coastguard Worker const xmlChar *prefix) {
3090*6777b538SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
3091*6777b538SAndroid Build Coastguard Worker
3092*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
3093*6777b538SAndroid Build Coastguard Worker if (dtd->attributes == NULL) return(NULL);
3094*6777b538SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
3095*6777b538SAndroid Build Coastguard Worker
3096*6777b538SAndroid Build Coastguard Worker return(xmlHashLookup3(table, name, prefix, elem));
3097*6777b538SAndroid Build Coastguard Worker }
3098*6777b538SAndroid Build Coastguard Worker
3099*6777b538SAndroid Build Coastguard Worker /**
3100*6777b538SAndroid Build Coastguard Worker * xmlGetDtdNotationDesc:
3101*6777b538SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3102*6777b538SAndroid Build Coastguard Worker * @name: the notation name
3103*6777b538SAndroid Build Coastguard Worker *
3104*6777b538SAndroid Build Coastguard Worker * Search the DTD for the description of this notation
3105*6777b538SAndroid Build Coastguard Worker *
3106*6777b538SAndroid Build Coastguard Worker * returns the xmlNotationPtr if found or NULL
3107*6777b538SAndroid Build Coastguard Worker */
3108*6777b538SAndroid Build Coastguard Worker
3109*6777b538SAndroid Build Coastguard Worker xmlNotationPtr
xmlGetDtdNotationDesc(xmlDtdPtr dtd,const xmlChar * name)3110*6777b538SAndroid Build Coastguard Worker xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name) {
3111*6777b538SAndroid Build Coastguard Worker xmlNotationTablePtr table;
3112*6777b538SAndroid Build Coastguard Worker
3113*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) return(NULL);
3114*6777b538SAndroid Build Coastguard Worker if (dtd->notations == NULL) return(NULL);
3115*6777b538SAndroid Build Coastguard Worker table = (xmlNotationTablePtr) dtd->notations;
3116*6777b538SAndroid Build Coastguard Worker
3117*6777b538SAndroid Build Coastguard Worker return(xmlHashLookup(table, name));
3118*6777b538SAndroid Build Coastguard Worker }
3119*6777b538SAndroid Build Coastguard Worker
3120*6777b538SAndroid Build Coastguard Worker #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
3121*6777b538SAndroid Build Coastguard Worker /**
3122*6777b538SAndroid Build Coastguard Worker * xmlValidateNotationUse:
3123*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
3124*6777b538SAndroid Build Coastguard Worker * @doc: the document
3125*6777b538SAndroid Build Coastguard Worker * @notationName: the notation name to check
3126*6777b538SAndroid Build Coastguard Worker *
3127*6777b538SAndroid Build Coastguard Worker * Validate that the given name match a notation declaration.
3128*6777b538SAndroid Build Coastguard Worker * - [ VC: Notation Declared ]
3129*6777b538SAndroid Build Coastguard Worker *
3130*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3131*6777b538SAndroid Build Coastguard Worker */
3132*6777b538SAndroid Build Coastguard Worker
3133*6777b538SAndroid Build Coastguard Worker int
xmlValidateNotationUse(xmlValidCtxtPtr ctxt,xmlDocPtr doc,const xmlChar * notationName)3134*6777b538SAndroid Build Coastguard Worker xmlValidateNotationUse(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3135*6777b538SAndroid Build Coastguard Worker const xmlChar *notationName) {
3136*6777b538SAndroid Build Coastguard Worker xmlNotationPtr notaDecl;
3137*6777b538SAndroid Build Coastguard Worker if ((doc == NULL) || (doc->intSubset == NULL) ||
3138*6777b538SAndroid Build Coastguard Worker (notationName == NULL)) return(-1);
3139*6777b538SAndroid Build Coastguard Worker
3140*6777b538SAndroid Build Coastguard Worker notaDecl = xmlGetDtdNotationDesc(doc->intSubset, notationName);
3141*6777b538SAndroid Build Coastguard Worker if ((notaDecl == NULL) && (doc->extSubset != NULL))
3142*6777b538SAndroid Build Coastguard Worker notaDecl = xmlGetDtdNotationDesc(doc->extSubset, notationName);
3143*6777b538SAndroid Build Coastguard Worker
3144*6777b538SAndroid Build Coastguard Worker if ((notaDecl == NULL) && (ctxt != NULL)) {
3145*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc, XML_DTD_UNKNOWN_NOTATION,
3146*6777b538SAndroid Build Coastguard Worker "NOTATION %s is not declared\n",
3147*6777b538SAndroid Build Coastguard Worker notationName, NULL, NULL);
3148*6777b538SAndroid Build Coastguard Worker return(0);
3149*6777b538SAndroid Build Coastguard Worker }
3150*6777b538SAndroid Build Coastguard Worker return(1);
3151*6777b538SAndroid Build Coastguard Worker }
3152*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
3153*6777b538SAndroid Build Coastguard Worker
3154*6777b538SAndroid Build Coastguard Worker /**
3155*6777b538SAndroid Build Coastguard Worker * xmlIsMixedElement:
3156*6777b538SAndroid Build Coastguard Worker * @doc: the document
3157*6777b538SAndroid Build Coastguard Worker * @name: the element name
3158*6777b538SAndroid Build Coastguard Worker *
3159*6777b538SAndroid Build Coastguard Worker * Search in the DtDs whether an element accept Mixed content (or ANY)
3160*6777b538SAndroid Build Coastguard Worker * basically if it is supposed to accept text childs
3161*6777b538SAndroid Build Coastguard Worker *
3162*6777b538SAndroid Build Coastguard Worker * returns 0 if no, 1 if yes, and -1 if no element description is available
3163*6777b538SAndroid Build Coastguard Worker */
3164*6777b538SAndroid Build Coastguard Worker
3165*6777b538SAndroid Build Coastguard Worker int
xmlIsMixedElement(xmlDocPtr doc,const xmlChar * name)3166*6777b538SAndroid Build Coastguard Worker xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) {
3167*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
3168*6777b538SAndroid Build Coastguard Worker
3169*6777b538SAndroid Build Coastguard Worker if ((doc == NULL) || (doc->intSubset == NULL)) return(-1);
3170*6777b538SAndroid Build Coastguard Worker
3171*6777b538SAndroid Build Coastguard Worker elemDecl = xmlGetDtdElementDesc(doc->intSubset, name);
3172*6777b538SAndroid Build Coastguard Worker if ((elemDecl == NULL) && (doc->extSubset != NULL))
3173*6777b538SAndroid Build Coastguard Worker elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
3174*6777b538SAndroid Build Coastguard Worker if (elemDecl == NULL) return(-1);
3175*6777b538SAndroid Build Coastguard Worker switch (elemDecl->etype) {
3176*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_UNDEFINED:
3177*6777b538SAndroid Build Coastguard Worker return(-1);
3178*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT:
3179*6777b538SAndroid Build Coastguard Worker return(0);
3180*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
3181*6777b538SAndroid Build Coastguard Worker /*
3182*6777b538SAndroid Build Coastguard Worker * return 1 for EMPTY since we want VC error to pop up
3183*6777b538SAndroid Build Coastguard Worker * on <empty> </empty> for example
3184*6777b538SAndroid Build Coastguard Worker */
3185*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
3186*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
3187*6777b538SAndroid Build Coastguard Worker return(1);
3188*6777b538SAndroid Build Coastguard Worker }
3189*6777b538SAndroid Build Coastguard Worker return(1);
3190*6777b538SAndroid Build Coastguard Worker }
3191*6777b538SAndroid Build Coastguard Worker
3192*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_VALID_ENABLED
3193*6777b538SAndroid Build Coastguard Worker
3194*6777b538SAndroid Build Coastguard Worker /**
3195*6777b538SAndroid Build Coastguard Worker * xmlValidNormalizeString:
3196*6777b538SAndroid Build Coastguard Worker * @str: a string
3197*6777b538SAndroid Build Coastguard Worker *
3198*6777b538SAndroid Build Coastguard Worker * Normalize a string in-place.
3199*6777b538SAndroid Build Coastguard Worker */
3200*6777b538SAndroid Build Coastguard Worker static void
xmlValidNormalizeString(xmlChar * str)3201*6777b538SAndroid Build Coastguard Worker xmlValidNormalizeString(xmlChar *str) {
3202*6777b538SAndroid Build Coastguard Worker xmlChar *dst;
3203*6777b538SAndroid Build Coastguard Worker const xmlChar *src;
3204*6777b538SAndroid Build Coastguard Worker
3205*6777b538SAndroid Build Coastguard Worker if (str == NULL)
3206*6777b538SAndroid Build Coastguard Worker return;
3207*6777b538SAndroid Build Coastguard Worker src = str;
3208*6777b538SAndroid Build Coastguard Worker dst = str;
3209*6777b538SAndroid Build Coastguard Worker
3210*6777b538SAndroid Build Coastguard Worker while (*src == 0x20) src++;
3211*6777b538SAndroid Build Coastguard Worker while (*src != 0) {
3212*6777b538SAndroid Build Coastguard Worker if (*src == 0x20) {
3213*6777b538SAndroid Build Coastguard Worker while (*src == 0x20) src++;
3214*6777b538SAndroid Build Coastguard Worker if (*src != 0)
3215*6777b538SAndroid Build Coastguard Worker *dst++ = 0x20;
3216*6777b538SAndroid Build Coastguard Worker } else {
3217*6777b538SAndroid Build Coastguard Worker *dst++ = *src++;
3218*6777b538SAndroid Build Coastguard Worker }
3219*6777b538SAndroid Build Coastguard Worker }
3220*6777b538SAndroid Build Coastguard Worker *dst = 0;
3221*6777b538SAndroid Build Coastguard Worker }
3222*6777b538SAndroid Build Coastguard Worker
3223*6777b538SAndroid Build Coastguard Worker /**
3224*6777b538SAndroid Build Coastguard Worker * xmlCtxtGetDtdElementDesc:
3225*6777b538SAndroid Build Coastguard Worker * @ctxt: validation context
3226*6777b538SAndroid Build Coastguard Worker * @dtd: a pointer to the DtD to search
3227*6777b538SAndroid Build Coastguard Worker * @name: the element name
3228*6777b538SAndroid Build Coastguard Worker *
3229*6777b538SAndroid Build Coastguard Worker * Search the DTD for the description of this element
3230*6777b538SAndroid Build Coastguard Worker *
3231*6777b538SAndroid Build Coastguard Worker * returns the xmlElementPtr if found or NULL
3232*6777b538SAndroid Build Coastguard Worker */
3233*6777b538SAndroid Build Coastguard Worker
3234*6777b538SAndroid Build Coastguard Worker static xmlElementPtr
xmlCtxtGetDtdElementDesc(xmlValidCtxtPtr ctxt,xmlDtdPtr dtd,const xmlChar * name)3235*6777b538SAndroid Build Coastguard Worker xmlCtxtGetDtdElementDesc(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd,
3236*6777b538SAndroid Build Coastguard Worker const xmlChar *name) {
3237*6777b538SAndroid Build Coastguard Worker xmlElementTablePtr table;
3238*6777b538SAndroid Build Coastguard Worker xmlElementPtr cur;
3239*6777b538SAndroid Build Coastguard Worker const xmlChar *localName;
3240*6777b538SAndroid Build Coastguard Worker xmlChar *prefix;
3241*6777b538SAndroid Build Coastguard Worker
3242*6777b538SAndroid Build Coastguard Worker if ((dtd == NULL) || (name == NULL)) return(NULL);
3243*6777b538SAndroid Build Coastguard Worker if (dtd->elements == NULL)
3244*6777b538SAndroid Build Coastguard Worker return(NULL);
3245*6777b538SAndroid Build Coastguard Worker table = (xmlElementTablePtr) dtd->elements;
3246*6777b538SAndroid Build Coastguard Worker
3247*6777b538SAndroid Build Coastguard Worker localName = xmlSplitQName4(name, &prefix);
3248*6777b538SAndroid Build Coastguard Worker if (localName == NULL) {
3249*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
3250*6777b538SAndroid Build Coastguard Worker return(NULL);
3251*6777b538SAndroid Build Coastguard Worker }
3252*6777b538SAndroid Build Coastguard Worker cur = xmlHashLookup2(table, localName, prefix);
3253*6777b538SAndroid Build Coastguard Worker if (prefix != NULL)
3254*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
3255*6777b538SAndroid Build Coastguard Worker return(cur);
3256*6777b538SAndroid Build Coastguard Worker }
3257*6777b538SAndroid Build Coastguard Worker
3258*6777b538SAndroid Build Coastguard Worker static int
xmlIsDocNameStartChar(xmlDocPtr doc,int c)3259*6777b538SAndroid Build Coastguard Worker xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
3260*6777b538SAndroid Build Coastguard Worker if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
3261*6777b538SAndroid Build Coastguard Worker /*
3262*6777b538SAndroid Build Coastguard Worker * Use the new checks of production [4] [4a] amd [5] of the
3263*6777b538SAndroid Build Coastguard Worker * Update 5 of XML-1.0
3264*6777b538SAndroid Build Coastguard Worker */
3265*6777b538SAndroid Build Coastguard Worker if (((c >= 'a') && (c <= 'z')) ||
3266*6777b538SAndroid Build Coastguard Worker ((c >= 'A') && (c <= 'Z')) ||
3267*6777b538SAndroid Build Coastguard Worker (c == '_') || (c == ':') ||
3268*6777b538SAndroid Build Coastguard Worker ((c >= 0xC0) && (c <= 0xD6)) ||
3269*6777b538SAndroid Build Coastguard Worker ((c >= 0xD8) && (c <= 0xF6)) ||
3270*6777b538SAndroid Build Coastguard Worker ((c >= 0xF8) && (c <= 0x2FF)) ||
3271*6777b538SAndroid Build Coastguard Worker ((c >= 0x370) && (c <= 0x37D)) ||
3272*6777b538SAndroid Build Coastguard Worker ((c >= 0x37F) && (c <= 0x1FFF)) ||
3273*6777b538SAndroid Build Coastguard Worker ((c >= 0x200C) && (c <= 0x200D)) ||
3274*6777b538SAndroid Build Coastguard Worker ((c >= 0x2070) && (c <= 0x218F)) ||
3275*6777b538SAndroid Build Coastguard Worker ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3276*6777b538SAndroid Build Coastguard Worker ((c >= 0x3001) && (c <= 0xD7FF)) ||
3277*6777b538SAndroid Build Coastguard Worker ((c >= 0xF900) && (c <= 0xFDCF)) ||
3278*6777b538SAndroid Build Coastguard Worker ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3279*6777b538SAndroid Build Coastguard Worker ((c >= 0x10000) && (c <= 0xEFFFF)))
3280*6777b538SAndroid Build Coastguard Worker return(1);
3281*6777b538SAndroid Build Coastguard Worker } else {
3282*6777b538SAndroid Build Coastguard Worker if (IS_LETTER(c) || (c == '_') || (c == ':'))
3283*6777b538SAndroid Build Coastguard Worker return(1);
3284*6777b538SAndroid Build Coastguard Worker }
3285*6777b538SAndroid Build Coastguard Worker return(0);
3286*6777b538SAndroid Build Coastguard Worker }
3287*6777b538SAndroid Build Coastguard Worker
3288*6777b538SAndroid Build Coastguard Worker static int
xmlIsDocNameChar(xmlDocPtr doc,int c)3289*6777b538SAndroid Build Coastguard Worker xmlIsDocNameChar(xmlDocPtr doc, int c) {
3290*6777b538SAndroid Build Coastguard Worker if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
3291*6777b538SAndroid Build Coastguard Worker /*
3292*6777b538SAndroid Build Coastguard Worker * Use the new checks of production [4] [4a] amd [5] of the
3293*6777b538SAndroid Build Coastguard Worker * Update 5 of XML-1.0
3294*6777b538SAndroid Build Coastguard Worker */
3295*6777b538SAndroid Build Coastguard Worker if (((c >= 'a') && (c <= 'z')) ||
3296*6777b538SAndroid Build Coastguard Worker ((c >= 'A') && (c <= 'Z')) ||
3297*6777b538SAndroid Build Coastguard Worker ((c >= '0') && (c <= '9')) || /* !start */
3298*6777b538SAndroid Build Coastguard Worker (c == '_') || (c == ':') ||
3299*6777b538SAndroid Build Coastguard Worker (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3300*6777b538SAndroid Build Coastguard Worker ((c >= 0xC0) && (c <= 0xD6)) ||
3301*6777b538SAndroid Build Coastguard Worker ((c >= 0xD8) && (c <= 0xF6)) ||
3302*6777b538SAndroid Build Coastguard Worker ((c >= 0xF8) && (c <= 0x2FF)) ||
3303*6777b538SAndroid Build Coastguard Worker ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3304*6777b538SAndroid Build Coastguard Worker ((c >= 0x370) && (c <= 0x37D)) ||
3305*6777b538SAndroid Build Coastguard Worker ((c >= 0x37F) && (c <= 0x1FFF)) ||
3306*6777b538SAndroid Build Coastguard Worker ((c >= 0x200C) && (c <= 0x200D)) ||
3307*6777b538SAndroid Build Coastguard Worker ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3308*6777b538SAndroid Build Coastguard Worker ((c >= 0x2070) && (c <= 0x218F)) ||
3309*6777b538SAndroid Build Coastguard Worker ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3310*6777b538SAndroid Build Coastguard Worker ((c >= 0x3001) && (c <= 0xD7FF)) ||
3311*6777b538SAndroid Build Coastguard Worker ((c >= 0xF900) && (c <= 0xFDCF)) ||
3312*6777b538SAndroid Build Coastguard Worker ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3313*6777b538SAndroid Build Coastguard Worker ((c >= 0x10000) && (c <= 0xEFFFF)))
3314*6777b538SAndroid Build Coastguard Worker return(1);
3315*6777b538SAndroid Build Coastguard Worker } else {
3316*6777b538SAndroid Build Coastguard Worker if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3317*6777b538SAndroid Build Coastguard Worker (c == '.') || (c == '-') ||
3318*6777b538SAndroid Build Coastguard Worker (c == '_') || (c == ':') ||
3319*6777b538SAndroid Build Coastguard Worker (IS_COMBINING(c)) ||
3320*6777b538SAndroid Build Coastguard Worker (IS_EXTENDER(c)))
3321*6777b538SAndroid Build Coastguard Worker return(1);
3322*6777b538SAndroid Build Coastguard Worker }
3323*6777b538SAndroid Build Coastguard Worker return(0);
3324*6777b538SAndroid Build Coastguard Worker }
3325*6777b538SAndroid Build Coastguard Worker
3326*6777b538SAndroid Build Coastguard Worker /**
3327*6777b538SAndroid Build Coastguard Worker * xmlValidateNameValue:
3328*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document or NULL
3329*6777b538SAndroid Build Coastguard Worker * @value: an Name value
3330*6777b538SAndroid Build Coastguard Worker *
3331*6777b538SAndroid Build Coastguard Worker * Validate that the given value match Name production
3332*6777b538SAndroid Build Coastguard Worker *
3333*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3334*6777b538SAndroid Build Coastguard Worker */
3335*6777b538SAndroid Build Coastguard Worker
3336*6777b538SAndroid Build Coastguard Worker static int
xmlValidateNameValueInternal(xmlDocPtr doc,const xmlChar * value)3337*6777b538SAndroid Build Coastguard Worker xmlValidateNameValueInternal(xmlDocPtr doc, const xmlChar *value) {
3338*6777b538SAndroid Build Coastguard Worker const xmlChar *cur;
3339*6777b538SAndroid Build Coastguard Worker int val, len;
3340*6777b538SAndroid Build Coastguard Worker
3341*6777b538SAndroid Build Coastguard Worker if (value == NULL) return(0);
3342*6777b538SAndroid Build Coastguard Worker cur = value;
3343*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3344*6777b538SAndroid Build Coastguard Worker cur += len;
3345*6777b538SAndroid Build Coastguard Worker if (!xmlIsDocNameStartChar(doc, val))
3346*6777b538SAndroid Build Coastguard Worker return(0);
3347*6777b538SAndroid Build Coastguard Worker
3348*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3349*6777b538SAndroid Build Coastguard Worker cur += len;
3350*6777b538SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3351*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3352*6777b538SAndroid Build Coastguard Worker cur += len;
3353*6777b538SAndroid Build Coastguard Worker }
3354*6777b538SAndroid Build Coastguard Worker
3355*6777b538SAndroid Build Coastguard Worker if (val != 0) return(0);
3356*6777b538SAndroid Build Coastguard Worker
3357*6777b538SAndroid Build Coastguard Worker return(1);
3358*6777b538SAndroid Build Coastguard Worker }
3359*6777b538SAndroid Build Coastguard Worker
3360*6777b538SAndroid Build Coastguard Worker /**
3361*6777b538SAndroid Build Coastguard Worker * xmlValidateNameValue:
3362*6777b538SAndroid Build Coastguard Worker * @value: an Name value
3363*6777b538SAndroid Build Coastguard Worker *
3364*6777b538SAndroid Build Coastguard Worker * Validate that the given value match Name production
3365*6777b538SAndroid Build Coastguard Worker *
3366*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3367*6777b538SAndroid Build Coastguard Worker */
3368*6777b538SAndroid Build Coastguard Worker
3369*6777b538SAndroid Build Coastguard Worker int
xmlValidateNameValue(const xmlChar * value)3370*6777b538SAndroid Build Coastguard Worker xmlValidateNameValue(const xmlChar *value) {
3371*6777b538SAndroid Build Coastguard Worker return(xmlValidateNameValueInternal(NULL, value));
3372*6777b538SAndroid Build Coastguard Worker }
3373*6777b538SAndroid Build Coastguard Worker
3374*6777b538SAndroid Build Coastguard Worker /**
3375*6777b538SAndroid Build Coastguard Worker * xmlValidateNamesValueInternal:
3376*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document or NULL
3377*6777b538SAndroid Build Coastguard Worker * @value: an Names value
3378*6777b538SAndroid Build Coastguard Worker *
3379*6777b538SAndroid Build Coastguard Worker * Validate that the given value match Names production
3380*6777b538SAndroid Build Coastguard Worker *
3381*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3382*6777b538SAndroid Build Coastguard Worker */
3383*6777b538SAndroid Build Coastguard Worker
3384*6777b538SAndroid Build Coastguard Worker static int
xmlValidateNamesValueInternal(xmlDocPtr doc,const xmlChar * value)3385*6777b538SAndroid Build Coastguard Worker xmlValidateNamesValueInternal(xmlDocPtr doc, const xmlChar *value) {
3386*6777b538SAndroid Build Coastguard Worker const xmlChar *cur;
3387*6777b538SAndroid Build Coastguard Worker int val, len;
3388*6777b538SAndroid Build Coastguard Worker
3389*6777b538SAndroid Build Coastguard Worker if (value == NULL) return(0);
3390*6777b538SAndroid Build Coastguard Worker cur = value;
3391*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3392*6777b538SAndroid Build Coastguard Worker cur += len;
3393*6777b538SAndroid Build Coastguard Worker
3394*6777b538SAndroid Build Coastguard Worker if (!xmlIsDocNameStartChar(doc, val))
3395*6777b538SAndroid Build Coastguard Worker return(0);
3396*6777b538SAndroid Build Coastguard Worker
3397*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3398*6777b538SAndroid Build Coastguard Worker cur += len;
3399*6777b538SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3400*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3401*6777b538SAndroid Build Coastguard Worker cur += len;
3402*6777b538SAndroid Build Coastguard Worker }
3403*6777b538SAndroid Build Coastguard Worker
3404*6777b538SAndroid Build Coastguard Worker /* Should not test IS_BLANK(val) here -- see erratum E20*/
3405*6777b538SAndroid Build Coastguard Worker while (val == 0x20) {
3406*6777b538SAndroid Build Coastguard Worker while (val == 0x20) {
3407*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3408*6777b538SAndroid Build Coastguard Worker cur += len;
3409*6777b538SAndroid Build Coastguard Worker }
3410*6777b538SAndroid Build Coastguard Worker
3411*6777b538SAndroid Build Coastguard Worker if (!xmlIsDocNameStartChar(doc, val))
3412*6777b538SAndroid Build Coastguard Worker return(0);
3413*6777b538SAndroid Build Coastguard Worker
3414*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3415*6777b538SAndroid Build Coastguard Worker cur += len;
3416*6777b538SAndroid Build Coastguard Worker
3417*6777b538SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3418*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3419*6777b538SAndroid Build Coastguard Worker cur += len;
3420*6777b538SAndroid Build Coastguard Worker }
3421*6777b538SAndroid Build Coastguard Worker }
3422*6777b538SAndroid Build Coastguard Worker
3423*6777b538SAndroid Build Coastguard Worker if (val != 0) return(0);
3424*6777b538SAndroid Build Coastguard Worker
3425*6777b538SAndroid Build Coastguard Worker return(1);
3426*6777b538SAndroid Build Coastguard Worker }
3427*6777b538SAndroid Build Coastguard Worker
3428*6777b538SAndroid Build Coastguard Worker /**
3429*6777b538SAndroid Build Coastguard Worker * xmlValidateNamesValue:
3430*6777b538SAndroid Build Coastguard Worker * @value: an Names value
3431*6777b538SAndroid Build Coastguard Worker *
3432*6777b538SAndroid Build Coastguard Worker * Validate that the given value match Names production
3433*6777b538SAndroid Build Coastguard Worker *
3434*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3435*6777b538SAndroid Build Coastguard Worker */
3436*6777b538SAndroid Build Coastguard Worker
3437*6777b538SAndroid Build Coastguard Worker int
xmlValidateNamesValue(const xmlChar * value)3438*6777b538SAndroid Build Coastguard Worker xmlValidateNamesValue(const xmlChar *value) {
3439*6777b538SAndroid Build Coastguard Worker return(xmlValidateNamesValueInternal(NULL, value));
3440*6777b538SAndroid Build Coastguard Worker }
3441*6777b538SAndroid Build Coastguard Worker
3442*6777b538SAndroid Build Coastguard Worker /**
3443*6777b538SAndroid Build Coastguard Worker * xmlValidateNmtokenValueInternal:
3444*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document or NULL
3445*6777b538SAndroid Build Coastguard Worker * @value: an Nmtoken value
3446*6777b538SAndroid Build Coastguard Worker *
3447*6777b538SAndroid Build Coastguard Worker * Validate that the given value match Nmtoken production
3448*6777b538SAndroid Build Coastguard Worker *
3449*6777b538SAndroid Build Coastguard Worker * [ VC: Name Token ]
3450*6777b538SAndroid Build Coastguard Worker *
3451*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3452*6777b538SAndroid Build Coastguard Worker */
3453*6777b538SAndroid Build Coastguard Worker
3454*6777b538SAndroid Build Coastguard Worker static int
xmlValidateNmtokenValueInternal(xmlDocPtr doc,const xmlChar * value)3455*6777b538SAndroid Build Coastguard Worker xmlValidateNmtokenValueInternal(xmlDocPtr doc, const xmlChar *value) {
3456*6777b538SAndroid Build Coastguard Worker const xmlChar *cur;
3457*6777b538SAndroid Build Coastguard Worker int val, len;
3458*6777b538SAndroid Build Coastguard Worker
3459*6777b538SAndroid Build Coastguard Worker if (value == NULL) return(0);
3460*6777b538SAndroid Build Coastguard Worker cur = value;
3461*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3462*6777b538SAndroid Build Coastguard Worker cur += len;
3463*6777b538SAndroid Build Coastguard Worker
3464*6777b538SAndroid Build Coastguard Worker if (!xmlIsDocNameChar(doc, val))
3465*6777b538SAndroid Build Coastguard Worker return(0);
3466*6777b538SAndroid Build Coastguard Worker
3467*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3468*6777b538SAndroid Build Coastguard Worker cur += len;
3469*6777b538SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3470*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3471*6777b538SAndroid Build Coastguard Worker cur += len;
3472*6777b538SAndroid Build Coastguard Worker }
3473*6777b538SAndroid Build Coastguard Worker
3474*6777b538SAndroid Build Coastguard Worker if (val != 0) return(0);
3475*6777b538SAndroid Build Coastguard Worker
3476*6777b538SAndroid Build Coastguard Worker return(1);
3477*6777b538SAndroid Build Coastguard Worker }
3478*6777b538SAndroid Build Coastguard Worker
3479*6777b538SAndroid Build Coastguard Worker /**
3480*6777b538SAndroid Build Coastguard Worker * xmlValidateNmtokenValue:
3481*6777b538SAndroid Build Coastguard Worker * @value: an Nmtoken value
3482*6777b538SAndroid Build Coastguard Worker *
3483*6777b538SAndroid Build Coastguard Worker * Validate that the given value match Nmtoken production
3484*6777b538SAndroid Build Coastguard Worker *
3485*6777b538SAndroid Build Coastguard Worker * [ VC: Name Token ]
3486*6777b538SAndroid Build Coastguard Worker *
3487*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3488*6777b538SAndroid Build Coastguard Worker */
3489*6777b538SAndroid Build Coastguard Worker
3490*6777b538SAndroid Build Coastguard Worker int
xmlValidateNmtokenValue(const xmlChar * value)3491*6777b538SAndroid Build Coastguard Worker xmlValidateNmtokenValue(const xmlChar *value) {
3492*6777b538SAndroid Build Coastguard Worker return(xmlValidateNmtokenValueInternal(NULL, value));
3493*6777b538SAndroid Build Coastguard Worker }
3494*6777b538SAndroid Build Coastguard Worker
3495*6777b538SAndroid Build Coastguard Worker /**
3496*6777b538SAndroid Build Coastguard Worker * xmlValidateNmtokensValueInternal:
3497*6777b538SAndroid Build Coastguard Worker * @doc: pointer to the document or NULL
3498*6777b538SAndroid Build Coastguard Worker * @value: an Nmtokens value
3499*6777b538SAndroid Build Coastguard Worker *
3500*6777b538SAndroid Build Coastguard Worker * Validate that the given value match Nmtokens production
3501*6777b538SAndroid Build Coastguard Worker *
3502*6777b538SAndroid Build Coastguard Worker * [ VC: Name Token ]
3503*6777b538SAndroid Build Coastguard Worker *
3504*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3505*6777b538SAndroid Build Coastguard Worker */
3506*6777b538SAndroid Build Coastguard Worker
3507*6777b538SAndroid Build Coastguard Worker static int
xmlValidateNmtokensValueInternal(xmlDocPtr doc,const xmlChar * value)3508*6777b538SAndroid Build Coastguard Worker xmlValidateNmtokensValueInternal(xmlDocPtr doc, const xmlChar *value) {
3509*6777b538SAndroid Build Coastguard Worker const xmlChar *cur;
3510*6777b538SAndroid Build Coastguard Worker int val, len;
3511*6777b538SAndroid Build Coastguard Worker
3512*6777b538SAndroid Build Coastguard Worker if (value == NULL) return(0);
3513*6777b538SAndroid Build Coastguard Worker cur = value;
3514*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3515*6777b538SAndroid Build Coastguard Worker cur += len;
3516*6777b538SAndroid Build Coastguard Worker
3517*6777b538SAndroid Build Coastguard Worker while (IS_BLANK(val)) {
3518*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3519*6777b538SAndroid Build Coastguard Worker cur += len;
3520*6777b538SAndroid Build Coastguard Worker }
3521*6777b538SAndroid Build Coastguard Worker
3522*6777b538SAndroid Build Coastguard Worker if (!xmlIsDocNameChar(doc, val))
3523*6777b538SAndroid Build Coastguard Worker return(0);
3524*6777b538SAndroid Build Coastguard Worker
3525*6777b538SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3526*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3527*6777b538SAndroid Build Coastguard Worker cur += len;
3528*6777b538SAndroid Build Coastguard Worker }
3529*6777b538SAndroid Build Coastguard Worker
3530*6777b538SAndroid Build Coastguard Worker /* Should not test IS_BLANK(val) here -- see erratum E20*/
3531*6777b538SAndroid Build Coastguard Worker while (val == 0x20) {
3532*6777b538SAndroid Build Coastguard Worker while (val == 0x20) {
3533*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3534*6777b538SAndroid Build Coastguard Worker cur += len;
3535*6777b538SAndroid Build Coastguard Worker }
3536*6777b538SAndroid Build Coastguard Worker if (val == 0) return(1);
3537*6777b538SAndroid Build Coastguard Worker
3538*6777b538SAndroid Build Coastguard Worker if (!xmlIsDocNameChar(doc, val))
3539*6777b538SAndroid Build Coastguard Worker return(0);
3540*6777b538SAndroid Build Coastguard Worker
3541*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3542*6777b538SAndroid Build Coastguard Worker cur += len;
3543*6777b538SAndroid Build Coastguard Worker
3544*6777b538SAndroid Build Coastguard Worker while (xmlIsDocNameChar(doc, val)) {
3545*6777b538SAndroid Build Coastguard Worker val = xmlStringCurrentChar(NULL, cur, &len);
3546*6777b538SAndroid Build Coastguard Worker cur += len;
3547*6777b538SAndroid Build Coastguard Worker }
3548*6777b538SAndroid Build Coastguard Worker }
3549*6777b538SAndroid Build Coastguard Worker
3550*6777b538SAndroid Build Coastguard Worker if (val != 0) return(0);
3551*6777b538SAndroid Build Coastguard Worker
3552*6777b538SAndroid Build Coastguard Worker return(1);
3553*6777b538SAndroid Build Coastguard Worker }
3554*6777b538SAndroid Build Coastguard Worker
3555*6777b538SAndroid Build Coastguard Worker /**
3556*6777b538SAndroid Build Coastguard Worker * xmlValidateNmtokensValue:
3557*6777b538SAndroid Build Coastguard Worker * @value: an Nmtokens value
3558*6777b538SAndroid Build Coastguard Worker *
3559*6777b538SAndroid Build Coastguard Worker * Validate that the given value match Nmtokens production
3560*6777b538SAndroid Build Coastguard Worker *
3561*6777b538SAndroid Build Coastguard Worker * [ VC: Name Token ]
3562*6777b538SAndroid Build Coastguard Worker *
3563*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3564*6777b538SAndroid Build Coastguard Worker */
3565*6777b538SAndroid Build Coastguard Worker
3566*6777b538SAndroid Build Coastguard Worker int
xmlValidateNmtokensValue(const xmlChar * value)3567*6777b538SAndroid Build Coastguard Worker xmlValidateNmtokensValue(const xmlChar *value) {
3568*6777b538SAndroid Build Coastguard Worker return(xmlValidateNmtokensValueInternal(NULL, value));
3569*6777b538SAndroid Build Coastguard Worker }
3570*6777b538SAndroid Build Coastguard Worker
3571*6777b538SAndroid Build Coastguard Worker /**
3572*6777b538SAndroid Build Coastguard Worker * xmlValidateNotationDecl:
3573*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
3574*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
3575*6777b538SAndroid Build Coastguard Worker * @nota: a notation definition
3576*6777b538SAndroid Build Coastguard Worker *
3577*6777b538SAndroid Build Coastguard Worker * Try to validate a single notation definition
3578*6777b538SAndroid Build Coastguard Worker * basically it does the following checks as described by the
3579*6777b538SAndroid Build Coastguard Worker * XML-1.0 recommendation:
3580*6777b538SAndroid Build Coastguard Worker * - it seems that no validity constraint exists on notation declarations
3581*6777b538SAndroid Build Coastguard Worker * But this function get called anyway ...
3582*6777b538SAndroid Build Coastguard Worker *
3583*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3584*6777b538SAndroid Build Coastguard Worker */
3585*6777b538SAndroid Build Coastguard Worker
3586*6777b538SAndroid Build Coastguard Worker int
xmlValidateNotationDecl(xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlDocPtr doc ATTRIBUTE_UNUSED,xmlNotationPtr nota ATTRIBUTE_UNUSED)3587*6777b538SAndroid Build Coastguard Worker xmlValidateNotationDecl(xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED, xmlDocPtr doc ATTRIBUTE_UNUSED,
3588*6777b538SAndroid Build Coastguard Worker xmlNotationPtr nota ATTRIBUTE_UNUSED) {
3589*6777b538SAndroid Build Coastguard Worker int ret = 1;
3590*6777b538SAndroid Build Coastguard Worker
3591*6777b538SAndroid Build Coastguard Worker return(ret);
3592*6777b538SAndroid Build Coastguard Worker }
3593*6777b538SAndroid Build Coastguard Worker
3594*6777b538SAndroid Build Coastguard Worker /**
3595*6777b538SAndroid Build Coastguard Worker * xmlValidateAttributeValueInternal:
3596*6777b538SAndroid Build Coastguard Worker * @doc: the document
3597*6777b538SAndroid Build Coastguard Worker * @type: an attribute type
3598*6777b538SAndroid Build Coastguard Worker * @value: an attribute value
3599*6777b538SAndroid Build Coastguard Worker *
3600*6777b538SAndroid Build Coastguard Worker * Validate that the given attribute value match the proper production
3601*6777b538SAndroid Build Coastguard Worker *
3602*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3603*6777b538SAndroid Build Coastguard Worker */
3604*6777b538SAndroid Build Coastguard Worker
3605*6777b538SAndroid Build Coastguard Worker static int
xmlValidateAttributeValueInternal(xmlDocPtr doc,xmlAttributeType type,const xmlChar * value)3606*6777b538SAndroid Build Coastguard Worker xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
3607*6777b538SAndroid Build Coastguard Worker const xmlChar *value) {
3608*6777b538SAndroid Build Coastguard Worker switch (type) {
3609*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITIES:
3610*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREFS:
3611*6777b538SAndroid Build Coastguard Worker return(xmlValidateNamesValueInternal(doc, value));
3612*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITY:
3613*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREF:
3614*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ID:
3615*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NOTATION:
3616*6777b538SAndroid Build Coastguard Worker return(xmlValidateNameValueInternal(doc, value));
3617*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKENS:
3618*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENUMERATION:
3619*6777b538SAndroid Build Coastguard Worker return(xmlValidateNmtokensValueInternal(doc, value));
3620*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKEN:
3621*6777b538SAndroid Build Coastguard Worker return(xmlValidateNmtokenValueInternal(doc, value));
3622*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_CDATA:
3623*6777b538SAndroid Build Coastguard Worker break;
3624*6777b538SAndroid Build Coastguard Worker }
3625*6777b538SAndroid Build Coastguard Worker return(1);
3626*6777b538SAndroid Build Coastguard Worker }
3627*6777b538SAndroid Build Coastguard Worker
3628*6777b538SAndroid Build Coastguard Worker /**
3629*6777b538SAndroid Build Coastguard Worker * xmlValidateAttributeValue:
3630*6777b538SAndroid Build Coastguard Worker * @type: an attribute type
3631*6777b538SAndroid Build Coastguard Worker * @value: an attribute value
3632*6777b538SAndroid Build Coastguard Worker *
3633*6777b538SAndroid Build Coastguard Worker * Validate that the given attribute value match the proper production
3634*6777b538SAndroid Build Coastguard Worker *
3635*6777b538SAndroid Build Coastguard Worker * [ VC: ID ]
3636*6777b538SAndroid Build Coastguard Worker * Values of type ID must match the Name production....
3637*6777b538SAndroid Build Coastguard Worker *
3638*6777b538SAndroid Build Coastguard Worker * [ VC: IDREF ]
3639*6777b538SAndroid Build Coastguard Worker * Values of type IDREF must match the Name production, and values
3640*6777b538SAndroid Build Coastguard Worker * of type IDREFS must match Names ...
3641*6777b538SAndroid Build Coastguard Worker *
3642*6777b538SAndroid Build Coastguard Worker * [ VC: Entity Name ]
3643*6777b538SAndroid Build Coastguard Worker * Values of type ENTITY must match the Name production, values
3644*6777b538SAndroid Build Coastguard Worker * of type ENTITIES must match Names ...
3645*6777b538SAndroid Build Coastguard Worker *
3646*6777b538SAndroid Build Coastguard Worker * [ VC: Name Token ]
3647*6777b538SAndroid Build Coastguard Worker * Values of type NMTOKEN must match the Nmtoken production; values
3648*6777b538SAndroid Build Coastguard Worker * of type NMTOKENS must match Nmtokens.
3649*6777b538SAndroid Build Coastguard Worker *
3650*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3651*6777b538SAndroid Build Coastguard Worker */
3652*6777b538SAndroid Build Coastguard Worker int
xmlValidateAttributeValue(xmlAttributeType type,const xmlChar * value)3653*6777b538SAndroid Build Coastguard Worker xmlValidateAttributeValue(xmlAttributeType type, const xmlChar *value) {
3654*6777b538SAndroid Build Coastguard Worker return(xmlValidateAttributeValueInternal(NULL, type, value));
3655*6777b538SAndroid Build Coastguard Worker }
3656*6777b538SAndroid Build Coastguard Worker
3657*6777b538SAndroid Build Coastguard Worker /**
3658*6777b538SAndroid Build Coastguard Worker * xmlValidateAttributeValue2:
3659*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
3660*6777b538SAndroid Build Coastguard Worker * @doc: the document
3661*6777b538SAndroid Build Coastguard Worker * @name: the attribute name (used for error reporting only)
3662*6777b538SAndroid Build Coastguard Worker * @type: the attribute type
3663*6777b538SAndroid Build Coastguard Worker * @value: the attribute value
3664*6777b538SAndroid Build Coastguard Worker *
3665*6777b538SAndroid Build Coastguard Worker * Validate that the given attribute value match a given type.
3666*6777b538SAndroid Build Coastguard Worker * This typically cannot be done before having finished parsing
3667*6777b538SAndroid Build Coastguard Worker * the subsets.
3668*6777b538SAndroid Build Coastguard Worker *
3669*6777b538SAndroid Build Coastguard Worker * [ VC: IDREF ]
3670*6777b538SAndroid Build Coastguard Worker * Values of type IDREF must match one of the declared IDs
3671*6777b538SAndroid Build Coastguard Worker * Values of type IDREFS must match a sequence of the declared IDs
3672*6777b538SAndroid Build Coastguard Worker * each Name must match the value of an ID attribute on some element
3673*6777b538SAndroid Build Coastguard Worker * in the XML document; i.e. IDREF values must match the value of
3674*6777b538SAndroid Build Coastguard Worker * some ID attribute
3675*6777b538SAndroid Build Coastguard Worker *
3676*6777b538SAndroid Build Coastguard Worker * [ VC: Entity Name ]
3677*6777b538SAndroid Build Coastguard Worker * Values of type ENTITY must match one declared entity
3678*6777b538SAndroid Build Coastguard Worker * Values of type ENTITIES must match a sequence of declared entities
3679*6777b538SAndroid Build Coastguard Worker *
3680*6777b538SAndroid Build Coastguard Worker * [ VC: Notation Attributes ]
3681*6777b538SAndroid Build Coastguard Worker * all notation names in the declaration must be declared.
3682*6777b538SAndroid Build Coastguard Worker *
3683*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3684*6777b538SAndroid Build Coastguard Worker */
3685*6777b538SAndroid Build Coastguard Worker
3686*6777b538SAndroid Build Coastguard Worker static int
xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt,xmlDocPtr doc,const xmlChar * name,xmlAttributeType type,const xmlChar * value)3687*6777b538SAndroid Build Coastguard Worker xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3688*6777b538SAndroid Build Coastguard Worker const xmlChar *name, xmlAttributeType type, const xmlChar *value) {
3689*6777b538SAndroid Build Coastguard Worker int ret = 1;
3690*6777b538SAndroid Build Coastguard Worker switch (type) {
3691*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREFS:
3692*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREF:
3693*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ID:
3694*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKENS:
3695*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENUMERATION:
3696*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKEN:
3697*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_CDATA:
3698*6777b538SAndroid Build Coastguard Worker break;
3699*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITY: {
3700*6777b538SAndroid Build Coastguard Worker xmlEntityPtr ent;
3701*6777b538SAndroid Build Coastguard Worker
3702*6777b538SAndroid Build Coastguard Worker ent = xmlGetDocEntity(doc, value);
3703*6777b538SAndroid Build Coastguard Worker /* yeah it's a bit messy... */
3704*6777b538SAndroid Build Coastguard Worker if ((ent == NULL) && (doc->standalone == 1)) {
3705*6777b538SAndroid Build Coastguard Worker doc->standalone = 0;
3706*6777b538SAndroid Build Coastguard Worker ent = xmlGetDocEntity(doc, value);
3707*6777b538SAndroid Build Coastguard Worker }
3708*6777b538SAndroid Build Coastguard Worker if (ent == NULL) {
3709*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3710*6777b538SAndroid Build Coastguard Worker XML_DTD_UNKNOWN_ENTITY,
3711*6777b538SAndroid Build Coastguard Worker "ENTITY attribute %s reference an unknown entity \"%s\"\n",
3712*6777b538SAndroid Build Coastguard Worker name, value, NULL);
3713*6777b538SAndroid Build Coastguard Worker ret = 0;
3714*6777b538SAndroid Build Coastguard Worker } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
3715*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3716*6777b538SAndroid Build Coastguard Worker XML_DTD_ENTITY_TYPE,
3717*6777b538SAndroid Build Coastguard Worker "ENTITY attribute %s reference an entity \"%s\" of wrong type\n",
3718*6777b538SAndroid Build Coastguard Worker name, value, NULL);
3719*6777b538SAndroid Build Coastguard Worker ret = 0;
3720*6777b538SAndroid Build Coastguard Worker }
3721*6777b538SAndroid Build Coastguard Worker break;
3722*6777b538SAndroid Build Coastguard Worker }
3723*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITIES: {
3724*6777b538SAndroid Build Coastguard Worker xmlChar *dup, *nam = NULL, *cur, save;
3725*6777b538SAndroid Build Coastguard Worker xmlEntityPtr ent;
3726*6777b538SAndroid Build Coastguard Worker
3727*6777b538SAndroid Build Coastguard Worker dup = xmlStrdup(value);
3728*6777b538SAndroid Build Coastguard Worker if (dup == NULL) {
3729*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
3730*6777b538SAndroid Build Coastguard Worker return(0);
3731*6777b538SAndroid Build Coastguard Worker }
3732*6777b538SAndroid Build Coastguard Worker cur = dup;
3733*6777b538SAndroid Build Coastguard Worker while (*cur != 0) {
3734*6777b538SAndroid Build Coastguard Worker nam = cur;
3735*6777b538SAndroid Build Coastguard Worker while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
3736*6777b538SAndroid Build Coastguard Worker save = *cur;
3737*6777b538SAndroid Build Coastguard Worker *cur = 0;
3738*6777b538SAndroid Build Coastguard Worker ent = xmlGetDocEntity(doc, nam);
3739*6777b538SAndroid Build Coastguard Worker if (ent == NULL) {
3740*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3741*6777b538SAndroid Build Coastguard Worker XML_DTD_UNKNOWN_ENTITY,
3742*6777b538SAndroid Build Coastguard Worker "ENTITIES attribute %s reference an unknown entity \"%s\"\n",
3743*6777b538SAndroid Build Coastguard Worker name, nam, NULL);
3744*6777b538SAndroid Build Coastguard Worker ret = 0;
3745*6777b538SAndroid Build Coastguard Worker } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
3746*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3747*6777b538SAndroid Build Coastguard Worker XML_DTD_ENTITY_TYPE,
3748*6777b538SAndroid Build Coastguard Worker "ENTITIES attribute %s reference an entity \"%s\" of wrong type\n",
3749*6777b538SAndroid Build Coastguard Worker name, nam, NULL);
3750*6777b538SAndroid Build Coastguard Worker ret = 0;
3751*6777b538SAndroid Build Coastguard Worker }
3752*6777b538SAndroid Build Coastguard Worker if (save == 0)
3753*6777b538SAndroid Build Coastguard Worker break;
3754*6777b538SAndroid Build Coastguard Worker *cur = save;
3755*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
3756*6777b538SAndroid Build Coastguard Worker }
3757*6777b538SAndroid Build Coastguard Worker xmlFree(dup);
3758*6777b538SAndroid Build Coastguard Worker break;
3759*6777b538SAndroid Build Coastguard Worker }
3760*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NOTATION: {
3761*6777b538SAndroid Build Coastguard Worker xmlNotationPtr nota;
3762*6777b538SAndroid Build Coastguard Worker
3763*6777b538SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->intSubset, value);
3764*6777b538SAndroid Build Coastguard Worker if ((nota == NULL) && (doc->extSubset != NULL))
3765*6777b538SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->extSubset, value);
3766*6777b538SAndroid Build Coastguard Worker
3767*6777b538SAndroid Build Coastguard Worker if (nota == NULL) {
3768*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) doc,
3769*6777b538SAndroid Build Coastguard Worker XML_DTD_UNKNOWN_NOTATION,
3770*6777b538SAndroid Build Coastguard Worker "NOTATION attribute %s reference an unknown notation \"%s\"\n",
3771*6777b538SAndroid Build Coastguard Worker name, value, NULL);
3772*6777b538SAndroid Build Coastguard Worker ret = 0;
3773*6777b538SAndroid Build Coastguard Worker }
3774*6777b538SAndroid Build Coastguard Worker break;
3775*6777b538SAndroid Build Coastguard Worker }
3776*6777b538SAndroid Build Coastguard Worker }
3777*6777b538SAndroid Build Coastguard Worker return(ret);
3778*6777b538SAndroid Build Coastguard Worker }
3779*6777b538SAndroid Build Coastguard Worker
3780*6777b538SAndroid Build Coastguard Worker /**
3781*6777b538SAndroid Build Coastguard Worker * xmlValidCtxtNormalizeAttributeValue:
3782*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
3783*6777b538SAndroid Build Coastguard Worker * @doc: the document
3784*6777b538SAndroid Build Coastguard Worker * @elem: the parent
3785*6777b538SAndroid Build Coastguard Worker * @name: the attribute name
3786*6777b538SAndroid Build Coastguard Worker * @value: the attribute value
3787*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context or NULL
3788*6777b538SAndroid Build Coastguard Worker *
3789*6777b538SAndroid Build Coastguard Worker * Does the validation related extra step of the normalization of attribute
3790*6777b538SAndroid Build Coastguard Worker * values:
3791*6777b538SAndroid Build Coastguard Worker *
3792*6777b538SAndroid Build Coastguard Worker * If the declared value is not CDATA, then the XML processor must further
3793*6777b538SAndroid Build Coastguard Worker * process the normalized attribute value by discarding any leading and
3794*6777b538SAndroid Build Coastguard Worker * trailing space (#x20) characters, and by replacing sequences of space
3795*6777b538SAndroid Build Coastguard Worker * (#x20) characters by single space (#x20) character.
3796*6777b538SAndroid Build Coastguard Worker *
3797*6777b538SAndroid Build Coastguard Worker * Also check VC: Standalone Document Declaration in P32, and update
3798*6777b538SAndroid Build Coastguard Worker * ctxt->valid accordingly
3799*6777b538SAndroid Build Coastguard Worker *
3800*6777b538SAndroid Build Coastguard Worker * returns a new normalized string if normalization is needed, NULL otherwise
3801*6777b538SAndroid Build Coastguard Worker * the caller must free the returned value.
3802*6777b538SAndroid Build Coastguard Worker */
3803*6777b538SAndroid Build Coastguard Worker
3804*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,const xmlChar * name,const xmlChar * value)3805*6777b538SAndroid Build Coastguard Worker xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3806*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
3807*6777b538SAndroid Build Coastguard Worker xmlChar *ret;
3808*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
3809*6777b538SAndroid Build Coastguard Worker const xmlChar *localName;
3810*6777b538SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
3811*6777b538SAndroid Build Coastguard Worker int extsubset = 0;
3812*6777b538SAndroid Build Coastguard Worker
3813*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(NULL);
3814*6777b538SAndroid Build Coastguard Worker if (elem == NULL) return(NULL);
3815*6777b538SAndroid Build Coastguard Worker if (name == NULL) return(NULL);
3816*6777b538SAndroid Build Coastguard Worker if (value == NULL) return(NULL);
3817*6777b538SAndroid Build Coastguard Worker
3818*6777b538SAndroid Build Coastguard Worker localName = xmlSplitQName4(name, &prefix);
3819*6777b538SAndroid Build Coastguard Worker if (localName == NULL)
3820*6777b538SAndroid Build Coastguard Worker goto mem_error;
3821*6777b538SAndroid Build Coastguard Worker
3822*6777b538SAndroid Build Coastguard Worker if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
3823*6777b538SAndroid Build Coastguard Worker xmlChar buf[50];
3824*6777b538SAndroid Build Coastguard Worker xmlChar *elemname;
3825*6777b538SAndroid Build Coastguard Worker
3826*6777b538SAndroid Build Coastguard Worker elemname = xmlBuildQName(elem->name, elem->ns->prefix, buf, 50);
3827*6777b538SAndroid Build Coastguard Worker if (elemname == NULL)
3828*6777b538SAndroid Build Coastguard Worker goto mem_error;
3829*6777b538SAndroid Build Coastguard Worker if (doc->intSubset != NULL)
3830*6777b538SAndroid Build Coastguard Worker attrDecl = xmlHashLookup3(doc->intSubset->attributes, localName,
3831*6777b538SAndroid Build Coastguard Worker prefix, elemname);
3832*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
3833*6777b538SAndroid Build Coastguard Worker attrDecl = xmlHashLookup3(doc->extSubset->attributes, localName,
3834*6777b538SAndroid Build Coastguard Worker prefix, elemname);
3835*6777b538SAndroid Build Coastguard Worker if (attrDecl != NULL)
3836*6777b538SAndroid Build Coastguard Worker extsubset = 1;
3837*6777b538SAndroid Build Coastguard Worker }
3838*6777b538SAndroid Build Coastguard Worker if ((elemname != buf) && (elemname != elem->name))
3839*6777b538SAndroid Build Coastguard Worker xmlFree(elemname);
3840*6777b538SAndroid Build Coastguard Worker }
3841*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->intSubset != NULL))
3842*6777b538SAndroid Build Coastguard Worker attrDecl = xmlHashLookup3(doc->intSubset->attributes, localName,
3843*6777b538SAndroid Build Coastguard Worker prefix, elem->name);
3844*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
3845*6777b538SAndroid Build Coastguard Worker attrDecl = xmlHashLookup3(doc->extSubset->attributes, localName,
3846*6777b538SAndroid Build Coastguard Worker prefix, elem->name);
3847*6777b538SAndroid Build Coastguard Worker if (attrDecl != NULL)
3848*6777b538SAndroid Build Coastguard Worker extsubset = 1;
3849*6777b538SAndroid Build Coastguard Worker }
3850*6777b538SAndroid Build Coastguard Worker
3851*6777b538SAndroid Build Coastguard Worker if (attrDecl == NULL)
3852*6777b538SAndroid Build Coastguard Worker goto done;
3853*6777b538SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
3854*6777b538SAndroid Build Coastguard Worker goto done;
3855*6777b538SAndroid Build Coastguard Worker
3856*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup(value);
3857*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3858*6777b538SAndroid Build Coastguard Worker goto mem_error;
3859*6777b538SAndroid Build Coastguard Worker xmlValidNormalizeString(ret);
3860*6777b538SAndroid Build Coastguard Worker if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
3861*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
3862*6777b538SAndroid Build Coastguard Worker "standalone: %s on %s value had to be normalized based on external subset declaration\n",
3863*6777b538SAndroid Build Coastguard Worker name, elem->name, NULL);
3864*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
3865*6777b538SAndroid Build Coastguard Worker }
3866*6777b538SAndroid Build Coastguard Worker
3867*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
3868*6777b538SAndroid Build Coastguard Worker return(ret);
3869*6777b538SAndroid Build Coastguard Worker
3870*6777b538SAndroid Build Coastguard Worker mem_error:
3871*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
3872*6777b538SAndroid Build Coastguard Worker
3873*6777b538SAndroid Build Coastguard Worker done:
3874*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
3875*6777b538SAndroid Build Coastguard Worker return(NULL);
3876*6777b538SAndroid Build Coastguard Worker }
3877*6777b538SAndroid Build Coastguard Worker
3878*6777b538SAndroid Build Coastguard Worker /**
3879*6777b538SAndroid Build Coastguard Worker * xmlValidNormalizeAttributeValue:
3880*6777b538SAndroid Build Coastguard Worker * @doc: the document
3881*6777b538SAndroid Build Coastguard Worker * @elem: the parent
3882*6777b538SAndroid Build Coastguard Worker * @name: the attribute name
3883*6777b538SAndroid Build Coastguard Worker * @value: the attribute value
3884*6777b538SAndroid Build Coastguard Worker *
3885*6777b538SAndroid Build Coastguard Worker * Does the validation related extra step of the normalization of attribute
3886*6777b538SAndroid Build Coastguard Worker * values:
3887*6777b538SAndroid Build Coastguard Worker *
3888*6777b538SAndroid Build Coastguard Worker * If the declared value is not CDATA, then the XML processor must further
3889*6777b538SAndroid Build Coastguard Worker * process the normalized attribute value by discarding any leading and
3890*6777b538SAndroid Build Coastguard Worker * trailing space (#x20) characters, and by replacing sequences of space
3891*6777b538SAndroid Build Coastguard Worker * (#x20) characters by single space (#x20) character.
3892*6777b538SAndroid Build Coastguard Worker *
3893*6777b538SAndroid Build Coastguard Worker * Returns a new normalized string if normalization is needed, NULL otherwise
3894*6777b538SAndroid Build Coastguard Worker * the caller must free the returned value.
3895*6777b538SAndroid Build Coastguard Worker */
3896*6777b538SAndroid Build Coastguard Worker
3897*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlValidNormalizeAttributeValue(xmlDocPtr doc,xmlNodePtr elem,const xmlChar * name,const xmlChar * value)3898*6777b538SAndroid Build Coastguard Worker xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
3899*6777b538SAndroid Build Coastguard Worker const xmlChar *name, const xmlChar *value) {
3900*6777b538SAndroid Build Coastguard Worker xmlChar *ret;
3901*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
3902*6777b538SAndroid Build Coastguard Worker
3903*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(NULL);
3904*6777b538SAndroid Build Coastguard Worker if (elem == NULL) return(NULL);
3905*6777b538SAndroid Build Coastguard Worker if (name == NULL) return(NULL);
3906*6777b538SAndroid Build Coastguard Worker if (value == NULL) return(NULL);
3907*6777b538SAndroid Build Coastguard Worker
3908*6777b538SAndroid Build Coastguard Worker if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
3909*6777b538SAndroid Build Coastguard Worker xmlChar fn[50];
3910*6777b538SAndroid Build Coastguard Worker xmlChar *fullname;
3911*6777b538SAndroid Build Coastguard Worker
3912*6777b538SAndroid Build Coastguard Worker fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
3913*6777b538SAndroid Build Coastguard Worker if (fullname == NULL)
3914*6777b538SAndroid Build Coastguard Worker return(NULL);
3915*6777b538SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != elem->name))
3916*6777b538SAndroid Build Coastguard Worker xmlFree(fullname);
3917*6777b538SAndroid Build Coastguard Worker }
3918*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
3919*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
3920*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
3921*6777b538SAndroid Build Coastguard Worker
3922*6777b538SAndroid Build Coastguard Worker if (attrDecl == NULL)
3923*6777b538SAndroid Build Coastguard Worker return(NULL);
3924*6777b538SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
3925*6777b538SAndroid Build Coastguard Worker return(NULL);
3926*6777b538SAndroid Build Coastguard Worker
3927*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup(value);
3928*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3929*6777b538SAndroid Build Coastguard Worker return(NULL);
3930*6777b538SAndroid Build Coastguard Worker xmlValidNormalizeString(ret);
3931*6777b538SAndroid Build Coastguard Worker return(ret);
3932*6777b538SAndroid Build Coastguard Worker }
3933*6777b538SAndroid Build Coastguard Worker
3934*6777b538SAndroid Build Coastguard Worker static void
xmlValidateAttributeIdCallback(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)3935*6777b538SAndroid Build Coastguard Worker xmlValidateAttributeIdCallback(void *payload, void *data,
3936*6777b538SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
3937*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attr = (xmlAttributePtr) payload;
3938*6777b538SAndroid Build Coastguard Worker int *count = (int *) data;
3939*6777b538SAndroid Build Coastguard Worker if (attr->atype == XML_ATTRIBUTE_ID) (*count)++;
3940*6777b538SAndroid Build Coastguard Worker }
3941*6777b538SAndroid Build Coastguard Worker
3942*6777b538SAndroid Build Coastguard Worker /**
3943*6777b538SAndroid Build Coastguard Worker * xmlValidateAttributeDecl:
3944*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
3945*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
3946*6777b538SAndroid Build Coastguard Worker * @attr: an attribute definition
3947*6777b538SAndroid Build Coastguard Worker *
3948*6777b538SAndroid Build Coastguard Worker * Try to validate a single attribute definition
3949*6777b538SAndroid Build Coastguard Worker * basically it does the following checks as described by the
3950*6777b538SAndroid Build Coastguard Worker * XML-1.0 recommendation:
3951*6777b538SAndroid Build Coastguard Worker * - [ VC: Attribute Default Legal ]
3952*6777b538SAndroid Build Coastguard Worker * - [ VC: Enumeration ]
3953*6777b538SAndroid Build Coastguard Worker * - [ VC: ID Attribute Default ]
3954*6777b538SAndroid Build Coastguard Worker *
3955*6777b538SAndroid Build Coastguard Worker * The ID/IDREF uniqueness and matching are done separately
3956*6777b538SAndroid Build Coastguard Worker *
3957*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
3958*6777b538SAndroid Build Coastguard Worker */
3959*6777b538SAndroid Build Coastguard Worker
3960*6777b538SAndroid Build Coastguard Worker int
xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlAttributePtr attr)3961*6777b538SAndroid Build Coastguard Worker xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
3962*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attr) {
3963*6777b538SAndroid Build Coastguard Worker int ret = 1;
3964*6777b538SAndroid Build Coastguard Worker int val;
3965*6777b538SAndroid Build Coastguard Worker CHECK_DTD;
3966*6777b538SAndroid Build Coastguard Worker if(attr == NULL) return(1);
3967*6777b538SAndroid Build Coastguard Worker
3968*6777b538SAndroid Build Coastguard Worker /* Attribute Default Legal */
3969*6777b538SAndroid Build Coastguard Worker /* Enumeration */
3970*6777b538SAndroid Build Coastguard Worker if (attr->defaultValue != NULL) {
3971*6777b538SAndroid Build Coastguard Worker val = xmlValidateAttributeValueInternal(doc, attr->atype,
3972*6777b538SAndroid Build Coastguard Worker attr->defaultValue);
3973*6777b538SAndroid Build Coastguard Worker if (val == 0) {
3974*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_DEFAULT,
3975*6777b538SAndroid Build Coastguard Worker "Syntax of default value for attribute %s of %s is not valid\n",
3976*6777b538SAndroid Build Coastguard Worker attr->name, attr->elem, NULL);
3977*6777b538SAndroid Build Coastguard Worker }
3978*6777b538SAndroid Build Coastguard Worker ret &= val;
3979*6777b538SAndroid Build Coastguard Worker }
3980*6777b538SAndroid Build Coastguard Worker
3981*6777b538SAndroid Build Coastguard Worker /* ID Attribute Default */
3982*6777b538SAndroid Build Coastguard Worker if ((attr->atype == XML_ATTRIBUTE_ID)&&
3983*6777b538SAndroid Build Coastguard Worker (attr->def != XML_ATTRIBUTE_IMPLIED) &&
3984*6777b538SAndroid Build Coastguard Worker (attr->def != XML_ATTRIBUTE_REQUIRED)) {
3985*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_FIXED,
3986*6777b538SAndroid Build Coastguard Worker "ID attribute %s of %s is not valid must be #IMPLIED or #REQUIRED\n",
3987*6777b538SAndroid Build Coastguard Worker attr->name, attr->elem, NULL);
3988*6777b538SAndroid Build Coastguard Worker ret = 0;
3989*6777b538SAndroid Build Coastguard Worker }
3990*6777b538SAndroid Build Coastguard Worker
3991*6777b538SAndroid Build Coastguard Worker /* One ID per Element Type */
3992*6777b538SAndroid Build Coastguard Worker if (attr->atype == XML_ATTRIBUTE_ID) {
3993*6777b538SAndroid Build Coastguard Worker int nbId;
3994*6777b538SAndroid Build Coastguard Worker
3995*6777b538SAndroid Build Coastguard Worker /* the trick is that we parse DtD as their own internal subset */
3996*6777b538SAndroid Build Coastguard Worker xmlElementPtr elem = xmlCtxtGetDtdElementDesc(ctxt, doc->intSubset,
3997*6777b538SAndroid Build Coastguard Worker attr->elem);
3998*6777b538SAndroid Build Coastguard Worker if (elem != NULL) {
3999*6777b538SAndroid Build Coastguard Worker nbId = xmlScanIDAttributeDecl(ctxt, elem, 0);
4000*6777b538SAndroid Build Coastguard Worker } else {
4001*6777b538SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
4002*6777b538SAndroid Build Coastguard Worker
4003*6777b538SAndroid Build Coastguard Worker /*
4004*6777b538SAndroid Build Coastguard Worker * The attribute may be declared in the internal subset and the
4005*6777b538SAndroid Build Coastguard Worker * element in the external subset.
4006*6777b538SAndroid Build Coastguard Worker */
4007*6777b538SAndroid Build Coastguard Worker nbId = 0;
4008*6777b538SAndroid Build Coastguard Worker if (doc->intSubset != NULL) {
4009*6777b538SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) doc->intSubset->attributes;
4010*6777b538SAndroid Build Coastguard Worker xmlHashScan3(table, NULL, NULL, attr->elem,
4011*6777b538SAndroid Build Coastguard Worker xmlValidateAttributeIdCallback, &nbId);
4012*6777b538SAndroid Build Coastguard Worker }
4013*6777b538SAndroid Build Coastguard Worker }
4014*6777b538SAndroid Build Coastguard Worker if (nbId > 1) {
4015*6777b538SAndroid Build Coastguard Worker
4016*6777b538SAndroid Build Coastguard Worker xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4017*6777b538SAndroid Build Coastguard Worker "Element %s has %d ID attribute defined in the internal subset : %s\n",
4018*6777b538SAndroid Build Coastguard Worker attr->elem, nbId, attr->name);
4019*6777b538SAndroid Build Coastguard Worker } else if (doc->extSubset != NULL) {
4020*6777b538SAndroid Build Coastguard Worker int extId = 0;
4021*6777b538SAndroid Build Coastguard Worker elem = xmlCtxtGetDtdElementDesc(ctxt, doc->extSubset, attr->elem);
4022*6777b538SAndroid Build Coastguard Worker if (elem != NULL) {
4023*6777b538SAndroid Build Coastguard Worker extId = xmlScanIDAttributeDecl(ctxt, elem, 0);
4024*6777b538SAndroid Build Coastguard Worker }
4025*6777b538SAndroid Build Coastguard Worker if (extId > 1) {
4026*6777b538SAndroid Build Coastguard Worker xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4027*6777b538SAndroid Build Coastguard Worker "Element %s has %d ID attribute defined in the external subset : %s\n",
4028*6777b538SAndroid Build Coastguard Worker attr->elem, extId, attr->name);
4029*6777b538SAndroid Build Coastguard Worker } else if (extId + nbId > 1) {
4030*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET,
4031*6777b538SAndroid Build Coastguard Worker "Element %s has ID attributes defined in the internal and external subset : %s\n",
4032*6777b538SAndroid Build Coastguard Worker attr->elem, attr->name, NULL);
4033*6777b538SAndroid Build Coastguard Worker }
4034*6777b538SAndroid Build Coastguard Worker }
4035*6777b538SAndroid Build Coastguard Worker }
4036*6777b538SAndroid Build Coastguard Worker
4037*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: Enumeration */
4038*6777b538SAndroid Build Coastguard Worker if ((attr->defaultValue != NULL) && (attr->tree != NULL)) {
4039*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attr->tree;
4040*6777b538SAndroid Build Coastguard Worker while (tree != NULL) {
4041*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, attr->defaultValue)) break;
4042*6777b538SAndroid Build Coastguard Worker tree = tree->next;
4043*6777b538SAndroid Build Coastguard Worker }
4044*6777b538SAndroid Build Coastguard Worker if (tree == NULL) {
4045*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_VALUE,
4046*6777b538SAndroid Build Coastguard Worker "Default value \"%s\" for attribute %s of %s is not among the enumerated set\n",
4047*6777b538SAndroid Build Coastguard Worker attr->defaultValue, attr->name, attr->elem);
4048*6777b538SAndroid Build Coastguard Worker ret = 0;
4049*6777b538SAndroid Build Coastguard Worker }
4050*6777b538SAndroid Build Coastguard Worker }
4051*6777b538SAndroid Build Coastguard Worker
4052*6777b538SAndroid Build Coastguard Worker return(ret);
4053*6777b538SAndroid Build Coastguard Worker }
4054*6777b538SAndroid Build Coastguard Worker
4055*6777b538SAndroid Build Coastguard Worker /**
4056*6777b538SAndroid Build Coastguard Worker * xmlValidateElementDecl:
4057*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
4058*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
4059*6777b538SAndroid Build Coastguard Worker * @elem: an element definition
4060*6777b538SAndroid Build Coastguard Worker *
4061*6777b538SAndroid Build Coastguard Worker * Try to validate a single element definition
4062*6777b538SAndroid Build Coastguard Worker * basically it does the following checks as described by the
4063*6777b538SAndroid Build Coastguard Worker * XML-1.0 recommendation:
4064*6777b538SAndroid Build Coastguard Worker * - [ VC: One ID per Element Type ]
4065*6777b538SAndroid Build Coastguard Worker * - [ VC: No Duplicate Types ]
4066*6777b538SAndroid Build Coastguard Worker * - [ VC: Unique Element Type Declaration ]
4067*6777b538SAndroid Build Coastguard Worker *
4068*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
4069*6777b538SAndroid Build Coastguard Worker */
4070*6777b538SAndroid Build Coastguard Worker
4071*6777b538SAndroid Build Coastguard Worker int
xmlValidateElementDecl(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlElementPtr elem)4072*6777b538SAndroid Build Coastguard Worker xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4073*6777b538SAndroid Build Coastguard Worker xmlElementPtr elem) {
4074*6777b538SAndroid Build Coastguard Worker int ret = 1;
4075*6777b538SAndroid Build Coastguard Worker xmlElementPtr tst;
4076*6777b538SAndroid Build Coastguard Worker
4077*6777b538SAndroid Build Coastguard Worker CHECK_DTD;
4078*6777b538SAndroid Build Coastguard Worker
4079*6777b538SAndroid Build Coastguard Worker if (elem == NULL) return(1);
4080*6777b538SAndroid Build Coastguard Worker
4081*6777b538SAndroid Build Coastguard Worker #if 0
4082*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
4083*6777b538SAndroid Build Coastguard Worker /* Build the regexp associated to the content model */
4084*6777b538SAndroid Build Coastguard Worker ret = xmlValidBuildContentModel(ctxt, elem);
4085*6777b538SAndroid Build Coastguard Worker #endif
4086*6777b538SAndroid Build Coastguard Worker #endif
4087*6777b538SAndroid Build Coastguard Worker
4088*6777b538SAndroid Build Coastguard Worker /* No Duplicate Types */
4089*6777b538SAndroid Build Coastguard Worker if (elem->etype == XML_ELEMENT_TYPE_MIXED) {
4090*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr cur, next;
4091*6777b538SAndroid Build Coastguard Worker const xmlChar *name;
4092*6777b538SAndroid Build Coastguard Worker
4093*6777b538SAndroid Build Coastguard Worker cur = elem->content;
4094*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
4095*6777b538SAndroid Build Coastguard Worker if (cur->type != XML_ELEMENT_CONTENT_OR) break;
4096*6777b538SAndroid Build Coastguard Worker if (cur->c1 == NULL) break;
4097*6777b538SAndroid Build Coastguard Worker if (cur->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
4098*6777b538SAndroid Build Coastguard Worker name = cur->c1->name;
4099*6777b538SAndroid Build Coastguard Worker next = cur->c2;
4100*6777b538SAndroid Build Coastguard Worker while (next != NULL) {
4101*6777b538SAndroid Build Coastguard Worker if (next->type == XML_ELEMENT_CONTENT_ELEMENT) {
4102*6777b538SAndroid Build Coastguard Worker if ((xmlStrEqual(next->name, name)) &&
4103*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(next->prefix, cur->c1->prefix))) {
4104*6777b538SAndroid Build Coastguard Worker if (cur->c1->prefix == NULL) {
4105*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4106*6777b538SAndroid Build Coastguard Worker "Definition of %s has duplicate references of %s\n",
4107*6777b538SAndroid Build Coastguard Worker elem->name, name, NULL);
4108*6777b538SAndroid Build Coastguard Worker } else {
4109*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4110*6777b538SAndroid Build Coastguard Worker "Definition of %s has duplicate references of %s:%s\n",
4111*6777b538SAndroid Build Coastguard Worker elem->name, cur->c1->prefix, name);
4112*6777b538SAndroid Build Coastguard Worker }
4113*6777b538SAndroid Build Coastguard Worker ret = 0;
4114*6777b538SAndroid Build Coastguard Worker }
4115*6777b538SAndroid Build Coastguard Worker break;
4116*6777b538SAndroid Build Coastguard Worker }
4117*6777b538SAndroid Build Coastguard Worker if (next->c1 == NULL) break;
4118*6777b538SAndroid Build Coastguard Worker if (next->c1->type != XML_ELEMENT_CONTENT_ELEMENT) break;
4119*6777b538SAndroid Build Coastguard Worker if ((xmlStrEqual(next->c1->name, name)) &&
4120*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(next->c1->prefix, cur->c1->prefix))) {
4121*6777b538SAndroid Build Coastguard Worker if (cur->c1->prefix == NULL) {
4122*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4123*6777b538SAndroid Build Coastguard Worker "Definition of %s has duplicate references to %s\n",
4124*6777b538SAndroid Build Coastguard Worker elem->name, name, NULL);
4125*6777b538SAndroid Build Coastguard Worker } else {
4126*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR,
4127*6777b538SAndroid Build Coastguard Worker "Definition of %s has duplicate references to %s:%s\n",
4128*6777b538SAndroid Build Coastguard Worker elem->name, cur->c1->prefix, name);
4129*6777b538SAndroid Build Coastguard Worker }
4130*6777b538SAndroid Build Coastguard Worker ret = 0;
4131*6777b538SAndroid Build Coastguard Worker }
4132*6777b538SAndroid Build Coastguard Worker next = next->c2;
4133*6777b538SAndroid Build Coastguard Worker }
4134*6777b538SAndroid Build Coastguard Worker }
4135*6777b538SAndroid Build Coastguard Worker cur = cur->c2;
4136*6777b538SAndroid Build Coastguard Worker }
4137*6777b538SAndroid Build Coastguard Worker }
4138*6777b538SAndroid Build Coastguard Worker
4139*6777b538SAndroid Build Coastguard Worker /* VC: Unique Element Type Declaration */
4140*6777b538SAndroid Build Coastguard Worker tst = xmlCtxtGetDtdElementDesc(ctxt, doc->intSubset, elem->name);
4141*6777b538SAndroid Build Coastguard Worker if ((tst != NULL ) && (tst != elem) &&
4142*6777b538SAndroid Build Coastguard Worker ((tst->prefix == elem->prefix) ||
4143*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(tst->prefix, elem->prefix))) &&
4144*6777b538SAndroid Build Coastguard Worker (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
4145*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
4146*6777b538SAndroid Build Coastguard Worker "Redefinition of element %s\n",
4147*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
4148*6777b538SAndroid Build Coastguard Worker ret = 0;
4149*6777b538SAndroid Build Coastguard Worker }
4150*6777b538SAndroid Build Coastguard Worker tst = xmlCtxtGetDtdElementDesc(ctxt, doc->extSubset, elem->name);
4151*6777b538SAndroid Build Coastguard Worker if ((tst != NULL ) && (tst != elem) &&
4152*6777b538SAndroid Build Coastguard Worker ((tst->prefix == elem->prefix) ||
4153*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(tst->prefix, elem->prefix))) &&
4154*6777b538SAndroid Build Coastguard Worker (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
4155*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED,
4156*6777b538SAndroid Build Coastguard Worker "Redefinition of element %s\n",
4157*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
4158*6777b538SAndroid Build Coastguard Worker ret = 0;
4159*6777b538SAndroid Build Coastguard Worker }
4160*6777b538SAndroid Build Coastguard Worker /* One ID per Element Type
4161*6777b538SAndroid Build Coastguard Worker * already done when registering the attribute
4162*6777b538SAndroid Build Coastguard Worker if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
4163*6777b538SAndroid Build Coastguard Worker ret = 0;
4164*6777b538SAndroid Build Coastguard Worker } */
4165*6777b538SAndroid Build Coastguard Worker return(ret);
4166*6777b538SAndroid Build Coastguard Worker }
4167*6777b538SAndroid Build Coastguard Worker
4168*6777b538SAndroid Build Coastguard Worker /**
4169*6777b538SAndroid Build Coastguard Worker * xmlValidateOneAttribute:
4170*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
4171*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
4172*6777b538SAndroid Build Coastguard Worker * @elem: an element instance
4173*6777b538SAndroid Build Coastguard Worker * @attr: an attribute instance
4174*6777b538SAndroid Build Coastguard Worker * @value: the attribute value (without entities processing)
4175*6777b538SAndroid Build Coastguard Worker *
4176*6777b538SAndroid Build Coastguard Worker * Try to validate a single attribute for an element
4177*6777b538SAndroid Build Coastguard Worker * basically it does the following checks as described by the
4178*6777b538SAndroid Build Coastguard Worker * XML-1.0 recommendation:
4179*6777b538SAndroid Build Coastguard Worker * - [ VC: Attribute Value Type ]
4180*6777b538SAndroid Build Coastguard Worker * - [ VC: Fixed Attribute Default ]
4181*6777b538SAndroid Build Coastguard Worker * - [ VC: Entity Name ]
4182*6777b538SAndroid Build Coastguard Worker * - [ VC: Name Token ]
4183*6777b538SAndroid Build Coastguard Worker * - [ VC: ID ]
4184*6777b538SAndroid Build Coastguard Worker * - [ VC: IDREF ]
4185*6777b538SAndroid Build Coastguard Worker * - [ VC: Entity Name ]
4186*6777b538SAndroid Build Coastguard Worker * - [ VC: Notation Attributes ]
4187*6777b538SAndroid Build Coastguard Worker *
4188*6777b538SAndroid Build Coastguard Worker * The ID/IDREF uniqueness and matching are done separately
4189*6777b538SAndroid Build Coastguard Worker *
4190*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
4191*6777b538SAndroid Build Coastguard Worker */
4192*6777b538SAndroid Build Coastguard Worker
4193*6777b538SAndroid Build Coastguard Worker int
xmlValidateOneAttribute(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,xmlAttrPtr attr,const xmlChar * value)4194*6777b538SAndroid Build Coastguard Worker xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4195*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value)
4196*6777b538SAndroid Build Coastguard Worker {
4197*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
4198*6777b538SAndroid Build Coastguard Worker const xmlChar *aprefix;
4199*6777b538SAndroid Build Coastguard Worker int val;
4200*6777b538SAndroid Build Coastguard Worker int ret = 1;
4201*6777b538SAndroid Build Coastguard Worker
4202*6777b538SAndroid Build Coastguard Worker CHECK_DTD;
4203*6777b538SAndroid Build Coastguard Worker if ((elem == NULL) || (elem->name == NULL)) return(0);
4204*6777b538SAndroid Build Coastguard Worker if ((attr == NULL) || (attr->name == NULL)) return(0);
4205*6777b538SAndroid Build Coastguard Worker
4206*6777b538SAndroid Build Coastguard Worker aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL;
4207*6777b538SAndroid Build Coastguard Worker
4208*6777b538SAndroid Build Coastguard Worker if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
4209*6777b538SAndroid Build Coastguard Worker xmlChar fn[50];
4210*6777b538SAndroid Build Coastguard Worker xmlChar *fullname;
4211*6777b538SAndroid Build Coastguard Worker
4212*6777b538SAndroid Build Coastguard Worker fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
4213*6777b538SAndroid Build Coastguard Worker if (fullname == NULL) {
4214*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
4215*6777b538SAndroid Build Coastguard Worker return(0);
4216*6777b538SAndroid Build Coastguard Worker }
4217*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4218*6777b538SAndroid Build Coastguard Worker attr->name, aprefix);
4219*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4220*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4221*6777b538SAndroid Build Coastguard Worker attr->name, aprefix);
4222*6777b538SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != elem->name))
4223*6777b538SAndroid Build Coastguard Worker xmlFree(fullname);
4224*6777b538SAndroid Build Coastguard Worker }
4225*6777b538SAndroid Build Coastguard Worker if (attrDecl == NULL) {
4226*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4227*6777b538SAndroid Build Coastguard Worker attr->name, aprefix);
4228*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4229*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4230*6777b538SAndroid Build Coastguard Worker attr->name, aprefix);
4231*6777b538SAndroid Build Coastguard Worker }
4232*6777b538SAndroid Build Coastguard Worker
4233*6777b538SAndroid Build Coastguard Worker
4234*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: Attribute Value Type */
4235*6777b538SAndroid Build Coastguard Worker if (attrDecl == NULL) {
4236*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4237*6777b538SAndroid Build Coastguard Worker "No declaration for attribute %s of element %s\n",
4238*6777b538SAndroid Build Coastguard Worker attr->name, elem->name, NULL);
4239*6777b538SAndroid Build Coastguard Worker return(0);
4240*6777b538SAndroid Build Coastguard Worker }
4241*6777b538SAndroid Build Coastguard Worker attr->atype = attrDecl->atype;
4242*6777b538SAndroid Build Coastguard Worker
4243*6777b538SAndroid Build Coastguard Worker val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
4244*6777b538SAndroid Build Coastguard Worker if (val == 0) {
4245*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4246*6777b538SAndroid Build Coastguard Worker "Syntax of value for attribute %s of %s is not valid\n",
4247*6777b538SAndroid Build Coastguard Worker attr->name, elem->name, NULL);
4248*6777b538SAndroid Build Coastguard Worker ret = 0;
4249*6777b538SAndroid Build Coastguard Worker }
4250*6777b538SAndroid Build Coastguard Worker
4251*6777b538SAndroid Build Coastguard Worker /* Validity constraint: Fixed Attribute Default */
4252*6777b538SAndroid Build Coastguard Worker if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
4253*6777b538SAndroid Build Coastguard Worker if (!xmlStrEqual(value, attrDecl->defaultValue)) {
4254*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4255*6777b538SAndroid Build Coastguard Worker "Value for attribute %s of %s is different from default \"%s\"\n",
4256*6777b538SAndroid Build Coastguard Worker attr->name, elem->name, attrDecl->defaultValue);
4257*6777b538SAndroid Build Coastguard Worker ret = 0;
4258*6777b538SAndroid Build Coastguard Worker }
4259*6777b538SAndroid Build Coastguard Worker }
4260*6777b538SAndroid Build Coastguard Worker
4261*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: ID uniqueness */
4262*6777b538SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_ID) {
4263*6777b538SAndroid Build Coastguard Worker if (xmlAddID(ctxt, doc, value, attr) == NULL)
4264*6777b538SAndroid Build Coastguard Worker ret = 0;
4265*6777b538SAndroid Build Coastguard Worker }
4266*6777b538SAndroid Build Coastguard Worker
4267*6777b538SAndroid Build Coastguard Worker if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
4268*6777b538SAndroid Build Coastguard Worker (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
4269*6777b538SAndroid Build Coastguard Worker if (xmlAddRef(ctxt, doc, value, attr) == NULL)
4270*6777b538SAndroid Build Coastguard Worker ret = 0;
4271*6777b538SAndroid Build Coastguard Worker }
4272*6777b538SAndroid Build Coastguard Worker
4273*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: Notation Attributes */
4274*6777b538SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
4275*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attrDecl->tree;
4276*6777b538SAndroid Build Coastguard Worker xmlNotationPtr nota;
4277*6777b538SAndroid Build Coastguard Worker
4278*6777b538SAndroid Build Coastguard Worker /* First check that the given NOTATION was declared */
4279*6777b538SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->intSubset, value);
4280*6777b538SAndroid Build Coastguard Worker if (nota == NULL)
4281*6777b538SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->extSubset, value);
4282*6777b538SAndroid Build Coastguard Worker
4283*6777b538SAndroid Build Coastguard Worker if (nota == NULL) {
4284*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4285*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute %s of %s is not a declared Notation\n",
4286*6777b538SAndroid Build Coastguard Worker value, attr->name, elem->name);
4287*6777b538SAndroid Build Coastguard Worker ret = 0;
4288*6777b538SAndroid Build Coastguard Worker }
4289*6777b538SAndroid Build Coastguard Worker
4290*6777b538SAndroid Build Coastguard Worker /* Second, verify that it's among the list */
4291*6777b538SAndroid Build Coastguard Worker while (tree != NULL) {
4292*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, value)) break;
4293*6777b538SAndroid Build Coastguard Worker tree = tree->next;
4294*6777b538SAndroid Build Coastguard Worker }
4295*6777b538SAndroid Build Coastguard Worker if (tree == NULL) {
4296*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4297*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute %s of %s is not among the enumerated notations\n",
4298*6777b538SAndroid Build Coastguard Worker value, attr->name, elem->name);
4299*6777b538SAndroid Build Coastguard Worker ret = 0;
4300*6777b538SAndroid Build Coastguard Worker }
4301*6777b538SAndroid Build Coastguard Worker }
4302*6777b538SAndroid Build Coastguard Worker
4303*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: Enumeration */
4304*6777b538SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
4305*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attrDecl->tree;
4306*6777b538SAndroid Build Coastguard Worker while (tree != NULL) {
4307*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, value)) break;
4308*6777b538SAndroid Build Coastguard Worker tree = tree->next;
4309*6777b538SAndroid Build Coastguard Worker }
4310*6777b538SAndroid Build Coastguard Worker if (tree == NULL) {
4311*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4312*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute %s of %s is not among the enumerated set\n",
4313*6777b538SAndroid Build Coastguard Worker value, attr->name, elem->name);
4314*6777b538SAndroid Build Coastguard Worker ret = 0;
4315*6777b538SAndroid Build Coastguard Worker }
4316*6777b538SAndroid Build Coastguard Worker }
4317*6777b538SAndroid Build Coastguard Worker
4318*6777b538SAndroid Build Coastguard Worker /* Fixed Attribute Default */
4319*6777b538SAndroid Build Coastguard Worker if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
4320*6777b538SAndroid Build Coastguard Worker (!xmlStrEqual(attrDecl->defaultValue, value))) {
4321*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4322*6777b538SAndroid Build Coastguard Worker "Value for attribute %s of %s must be \"%s\"\n",
4323*6777b538SAndroid Build Coastguard Worker attr->name, elem->name, attrDecl->defaultValue);
4324*6777b538SAndroid Build Coastguard Worker ret = 0;
4325*6777b538SAndroid Build Coastguard Worker }
4326*6777b538SAndroid Build Coastguard Worker
4327*6777b538SAndroid Build Coastguard Worker /* Extra check for the attribute value */
4328*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name,
4329*6777b538SAndroid Build Coastguard Worker attrDecl->atype, value);
4330*6777b538SAndroid Build Coastguard Worker
4331*6777b538SAndroid Build Coastguard Worker return(ret);
4332*6777b538SAndroid Build Coastguard Worker }
4333*6777b538SAndroid Build Coastguard Worker
4334*6777b538SAndroid Build Coastguard Worker /**
4335*6777b538SAndroid Build Coastguard Worker * xmlValidateOneNamespace:
4336*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
4337*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
4338*6777b538SAndroid Build Coastguard Worker * @elem: an element instance
4339*6777b538SAndroid Build Coastguard Worker * @prefix: the namespace prefix
4340*6777b538SAndroid Build Coastguard Worker * @ns: an namespace declaration instance
4341*6777b538SAndroid Build Coastguard Worker * @value: the attribute value (without entities processing)
4342*6777b538SAndroid Build Coastguard Worker *
4343*6777b538SAndroid Build Coastguard Worker * Try to validate a single namespace declaration for an element
4344*6777b538SAndroid Build Coastguard Worker * basically it does the following checks as described by the
4345*6777b538SAndroid Build Coastguard Worker * XML-1.0 recommendation:
4346*6777b538SAndroid Build Coastguard Worker * - [ VC: Attribute Value Type ]
4347*6777b538SAndroid Build Coastguard Worker * - [ VC: Fixed Attribute Default ]
4348*6777b538SAndroid Build Coastguard Worker * - [ VC: Entity Name ]
4349*6777b538SAndroid Build Coastguard Worker * - [ VC: Name Token ]
4350*6777b538SAndroid Build Coastguard Worker * - [ VC: ID ]
4351*6777b538SAndroid Build Coastguard Worker * - [ VC: IDREF ]
4352*6777b538SAndroid Build Coastguard Worker * - [ VC: Entity Name ]
4353*6777b538SAndroid Build Coastguard Worker * - [ VC: Notation Attributes ]
4354*6777b538SAndroid Build Coastguard Worker *
4355*6777b538SAndroid Build Coastguard Worker * The ID/IDREF uniqueness and matching are done separately
4356*6777b538SAndroid Build Coastguard Worker *
4357*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
4358*6777b538SAndroid Build Coastguard Worker */
4359*6777b538SAndroid Build Coastguard Worker
4360*6777b538SAndroid Build Coastguard Worker int
xmlValidateOneNamespace(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,const xmlChar * prefix,xmlNsPtr ns,const xmlChar * value)4361*6777b538SAndroid Build Coastguard Worker xmlValidateOneNamespace(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
4362*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
4363*6777b538SAndroid Build Coastguard Worker /* xmlElementPtr elemDecl; */
4364*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attrDecl = NULL;
4365*6777b538SAndroid Build Coastguard Worker int val;
4366*6777b538SAndroid Build Coastguard Worker int ret = 1;
4367*6777b538SAndroid Build Coastguard Worker
4368*6777b538SAndroid Build Coastguard Worker CHECK_DTD;
4369*6777b538SAndroid Build Coastguard Worker if ((elem == NULL) || (elem->name == NULL)) return(0);
4370*6777b538SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->href == NULL)) return(0);
4371*6777b538SAndroid Build Coastguard Worker
4372*6777b538SAndroid Build Coastguard Worker if (prefix != NULL) {
4373*6777b538SAndroid Build Coastguard Worker xmlChar fn[50];
4374*6777b538SAndroid Build Coastguard Worker xmlChar *fullname;
4375*6777b538SAndroid Build Coastguard Worker
4376*6777b538SAndroid Build Coastguard Worker fullname = xmlBuildQName(elem->name, prefix, fn, 50);
4377*6777b538SAndroid Build Coastguard Worker if (fullname == NULL) {
4378*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
4379*6777b538SAndroid Build Coastguard Worker return(0);
4380*6777b538SAndroid Build Coastguard Worker }
4381*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4382*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4383*6777b538SAndroid Build Coastguard Worker ns->prefix, BAD_CAST "xmlns");
4384*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4385*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4386*6777b538SAndroid Build Coastguard Worker ns->prefix, BAD_CAST "xmlns");
4387*6777b538SAndroid Build Coastguard Worker } else {
4388*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
4389*6777b538SAndroid Build Coastguard Worker BAD_CAST "xmlns", NULL);
4390*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4391*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
4392*6777b538SAndroid Build Coastguard Worker BAD_CAST "xmlns", NULL);
4393*6777b538SAndroid Build Coastguard Worker }
4394*6777b538SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != elem->name))
4395*6777b538SAndroid Build Coastguard Worker xmlFree(fullname);
4396*6777b538SAndroid Build Coastguard Worker }
4397*6777b538SAndroid Build Coastguard Worker if (attrDecl == NULL) {
4398*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4399*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4400*6777b538SAndroid Build Coastguard Worker ns->prefix, BAD_CAST "xmlns");
4401*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4402*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4403*6777b538SAndroid Build Coastguard Worker ns->prefix, BAD_CAST "xmlns");
4404*6777b538SAndroid Build Coastguard Worker } else {
4405*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
4406*6777b538SAndroid Build Coastguard Worker BAD_CAST "xmlns", NULL);
4407*6777b538SAndroid Build Coastguard Worker if ((attrDecl == NULL) && (doc->extSubset != NULL))
4408*6777b538SAndroid Build Coastguard Worker attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
4409*6777b538SAndroid Build Coastguard Worker BAD_CAST "xmlns", NULL);
4410*6777b538SAndroid Build Coastguard Worker }
4411*6777b538SAndroid Build Coastguard Worker }
4412*6777b538SAndroid Build Coastguard Worker
4413*6777b538SAndroid Build Coastguard Worker
4414*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: Attribute Value Type */
4415*6777b538SAndroid Build Coastguard Worker if (attrDecl == NULL) {
4416*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4417*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4418*6777b538SAndroid Build Coastguard Worker "No declaration for attribute xmlns:%s of element %s\n",
4419*6777b538SAndroid Build Coastguard Worker ns->prefix, elem->name, NULL);
4420*6777b538SAndroid Build Coastguard Worker } else {
4421*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE,
4422*6777b538SAndroid Build Coastguard Worker "No declaration for attribute xmlns of element %s\n",
4423*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
4424*6777b538SAndroid Build Coastguard Worker }
4425*6777b538SAndroid Build Coastguard Worker return(0);
4426*6777b538SAndroid Build Coastguard Worker }
4427*6777b538SAndroid Build Coastguard Worker
4428*6777b538SAndroid Build Coastguard Worker val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
4429*6777b538SAndroid Build Coastguard Worker if (val == 0) {
4430*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4431*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
4432*6777b538SAndroid Build Coastguard Worker "Syntax of value for attribute xmlns:%s of %s is not valid\n",
4433*6777b538SAndroid Build Coastguard Worker ns->prefix, elem->name, NULL);
4434*6777b538SAndroid Build Coastguard Worker } else {
4435*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
4436*6777b538SAndroid Build Coastguard Worker "Syntax of value for attribute xmlns of %s is not valid\n",
4437*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
4438*6777b538SAndroid Build Coastguard Worker }
4439*6777b538SAndroid Build Coastguard Worker ret = 0;
4440*6777b538SAndroid Build Coastguard Worker }
4441*6777b538SAndroid Build Coastguard Worker
4442*6777b538SAndroid Build Coastguard Worker /* Validity constraint: Fixed Attribute Default */
4443*6777b538SAndroid Build Coastguard Worker if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
4444*6777b538SAndroid Build Coastguard Worker if (!xmlStrEqual(value, attrDecl->defaultValue)) {
4445*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4446*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4447*6777b538SAndroid Build Coastguard Worker "Value for attribute xmlns:%s of %s is different from default \"%s\"\n",
4448*6777b538SAndroid Build Coastguard Worker ns->prefix, elem->name, attrDecl->defaultValue);
4449*6777b538SAndroid Build Coastguard Worker } else {
4450*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT,
4451*6777b538SAndroid Build Coastguard Worker "Value for attribute xmlns of %s is different from default \"%s\"\n",
4452*6777b538SAndroid Build Coastguard Worker elem->name, attrDecl->defaultValue, NULL);
4453*6777b538SAndroid Build Coastguard Worker }
4454*6777b538SAndroid Build Coastguard Worker ret = 0;
4455*6777b538SAndroid Build Coastguard Worker }
4456*6777b538SAndroid Build Coastguard Worker }
4457*6777b538SAndroid Build Coastguard Worker
4458*6777b538SAndroid Build Coastguard Worker /*
4459*6777b538SAndroid Build Coastguard Worker * Casting ns to xmlAttrPtr is wrong. We'd need separate functions
4460*6777b538SAndroid Build Coastguard Worker * xmlAddID and xmlAddRef for namespace declarations, but it makes
4461*6777b538SAndroid Build Coastguard Worker * no practical sense to use ID types anyway.
4462*6777b538SAndroid Build Coastguard Worker */
4463*6777b538SAndroid Build Coastguard Worker #if 0
4464*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: ID uniqueness */
4465*6777b538SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_ID) {
4466*6777b538SAndroid Build Coastguard Worker if (xmlAddID(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
4467*6777b538SAndroid Build Coastguard Worker ret = 0;
4468*6777b538SAndroid Build Coastguard Worker }
4469*6777b538SAndroid Build Coastguard Worker
4470*6777b538SAndroid Build Coastguard Worker if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
4471*6777b538SAndroid Build Coastguard Worker (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
4472*6777b538SAndroid Build Coastguard Worker if (xmlAddRef(ctxt, doc, value, (xmlAttrPtr) ns) == NULL)
4473*6777b538SAndroid Build Coastguard Worker ret = 0;
4474*6777b538SAndroid Build Coastguard Worker }
4475*6777b538SAndroid Build Coastguard Worker #endif
4476*6777b538SAndroid Build Coastguard Worker
4477*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: Notation Attributes */
4478*6777b538SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
4479*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attrDecl->tree;
4480*6777b538SAndroid Build Coastguard Worker xmlNotationPtr nota;
4481*6777b538SAndroid Build Coastguard Worker
4482*6777b538SAndroid Build Coastguard Worker /* First check that the given NOTATION was declared */
4483*6777b538SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->intSubset, value);
4484*6777b538SAndroid Build Coastguard Worker if (nota == NULL)
4485*6777b538SAndroid Build Coastguard Worker nota = xmlGetDtdNotationDesc(doc->extSubset, value);
4486*6777b538SAndroid Build Coastguard Worker
4487*6777b538SAndroid Build Coastguard Worker if (nota == NULL) {
4488*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4489*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4490*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns:%s of %s is not a declared Notation\n",
4491*6777b538SAndroid Build Coastguard Worker value, ns->prefix, elem->name);
4492*6777b538SAndroid Build Coastguard Worker } else {
4493*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION,
4494*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns of %s is not a declared Notation\n",
4495*6777b538SAndroid Build Coastguard Worker value, elem->name, NULL);
4496*6777b538SAndroid Build Coastguard Worker }
4497*6777b538SAndroid Build Coastguard Worker ret = 0;
4498*6777b538SAndroid Build Coastguard Worker }
4499*6777b538SAndroid Build Coastguard Worker
4500*6777b538SAndroid Build Coastguard Worker /* Second, verify that it's among the list */
4501*6777b538SAndroid Build Coastguard Worker while (tree != NULL) {
4502*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, value)) break;
4503*6777b538SAndroid Build Coastguard Worker tree = tree->next;
4504*6777b538SAndroid Build Coastguard Worker }
4505*6777b538SAndroid Build Coastguard Worker if (tree == NULL) {
4506*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4507*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4508*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated notations\n",
4509*6777b538SAndroid Build Coastguard Worker value, ns->prefix, elem->name);
4510*6777b538SAndroid Build Coastguard Worker } else {
4511*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE,
4512*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns of %s is not among the enumerated notations\n",
4513*6777b538SAndroid Build Coastguard Worker value, elem->name, NULL);
4514*6777b538SAndroid Build Coastguard Worker }
4515*6777b538SAndroid Build Coastguard Worker ret = 0;
4516*6777b538SAndroid Build Coastguard Worker }
4517*6777b538SAndroid Build Coastguard Worker }
4518*6777b538SAndroid Build Coastguard Worker
4519*6777b538SAndroid Build Coastguard Worker /* Validity Constraint: Enumeration */
4520*6777b538SAndroid Build Coastguard Worker if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
4521*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr tree = attrDecl->tree;
4522*6777b538SAndroid Build Coastguard Worker while (tree != NULL) {
4523*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(tree->name, value)) break;
4524*6777b538SAndroid Build Coastguard Worker tree = tree->next;
4525*6777b538SAndroid Build Coastguard Worker }
4526*6777b538SAndroid Build Coastguard Worker if (tree == NULL) {
4527*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4528*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4529*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated set\n",
4530*6777b538SAndroid Build Coastguard Worker value, ns->prefix, elem->name);
4531*6777b538SAndroid Build Coastguard Worker } else {
4532*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
4533*6777b538SAndroid Build Coastguard Worker "Value \"%s\" for attribute xmlns of %s is not among the enumerated set\n",
4534*6777b538SAndroid Build Coastguard Worker value, elem->name, NULL);
4535*6777b538SAndroid Build Coastguard Worker }
4536*6777b538SAndroid Build Coastguard Worker ret = 0;
4537*6777b538SAndroid Build Coastguard Worker }
4538*6777b538SAndroid Build Coastguard Worker }
4539*6777b538SAndroid Build Coastguard Worker
4540*6777b538SAndroid Build Coastguard Worker /* Fixed Attribute Default */
4541*6777b538SAndroid Build Coastguard Worker if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
4542*6777b538SAndroid Build Coastguard Worker (!xmlStrEqual(attrDecl->defaultValue, value))) {
4543*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4544*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
4545*6777b538SAndroid Build Coastguard Worker "Value for attribute xmlns:%s of %s must be \"%s\"\n",
4546*6777b538SAndroid Build Coastguard Worker ns->prefix, elem->name, attrDecl->defaultValue);
4547*6777b538SAndroid Build Coastguard Worker } else {
4548*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
4549*6777b538SAndroid Build Coastguard Worker "Value for attribute xmlns of %s must be \"%s\"\n",
4550*6777b538SAndroid Build Coastguard Worker elem->name, attrDecl->defaultValue, NULL);
4551*6777b538SAndroid Build Coastguard Worker }
4552*6777b538SAndroid Build Coastguard Worker ret = 0;
4553*6777b538SAndroid Build Coastguard Worker }
4554*6777b538SAndroid Build Coastguard Worker
4555*6777b538SAndroid Build Coastguard Worker /* Extra check for the attribute value */
4556*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
4557*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateAttributeValue2(ctxt, doc, ns->prefix,
4558*6777b538SAndroid Build Coastguard Worker attrDecl->atype, value);
4559*6777b538SAndroid Build Coastguard Worker } else {
4560*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateAttributeValue2(ctxt, doc, BAD_CAST "xmlns",
4561*6777b538SAndroid Build Coastguard Worker attrDecl->atype, value);
4562*6777b538SAndroid Build Coastguard Worker }
4563*6777b538SAndroid Build Coastguard Worker
4564*6777b538SAndroid Build Coastguard Worker return(ret);
4565*6777b538SAndroid Build Coastguard Worker }
4566*6777b538SAndroid Build Coastguard Worker
4567*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_REGEXP_ENABLED
4568*6777b538SAndroid Build Coastguard Worker /**
4569*6777b538SAndroid Build Coastguard Worker * xmlValidateSkipIgnorable:
4570*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
4571*6777b538SAndroid Build Coastguard Worker * @child: the child list
4572*6777b538SAndroid Build Coastguard Worker *
4573*6777b538SAndroid Build Coastguard Worker * Skip ignorable elements w.r.t. the validation process
4574*6777b538SAndroid Build Coastguard Worker *
4575*6777b538SAndroid Build Coastguard Worker * returns the first element to consider for validation of the content model
4576*6777b538SAndroid Build Coastguard Worker */
4577*6777b538SAndroid Build Coastguard Worker
4578*6777b538SAndroid Build Coastguard Worker static xmlNodePtr
xmlValidateSkipIgnorable(xmlNodePtr child)4579*6777b538SAndroid Build Coastguard Worker xmlValidateSkipIgnorable(xmlNodePtr child) {
4580*6777b538SAndroid Build Coastguard Worker while (child != NULL) {
4581*6777b538SAndroid Build Coastguard Worker switch (child->type) {
4582*6777b538SAndroid Build Coastguard Worker /* These things are ignored (skipped) during validation. */
4583*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
4584*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
4585*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
4586*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
4587*6777b538SAndroid Build Coastguard Worker child = child->next;
4588*6777b538SAndroid Build Coastguard Worker break;
4589*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
4590*6777b538SAndroid Build Coastguard Worker if (xmlIsBlankNode(child))
4591*6777b538SAndroid Build Coastguard Worker child = child->next;
4592*6777b538SAndroid Build Coastguard Worker else
4593*6777b538SAndroid Build Coastguard Worker return(child);
4594*6777b538SAndroid Build Coastguard Worker break;
4595*6777b538SAndroid Build Coastguard Worker /* keep current node */
4596*6777b538SAndroid Build Coastguard Worker default:
4597*6777b538SAndroid Build Coastguard Worker return(child);
4598*6777b538SAndroid Build Coastguard Worker }
4599*6777b538SAndroid Build Coastguard Worker }
4600*6777b538SAndroid Build Coastguard Worker return(child);
4601*6777b538SAndroid Build Coastguard Worker }
4602*6777b538SAndroid Build Coastguard Worker
4603*6777b538SAndroid Build Coastguard Worker /**
4604*6777b538SAndroid Build Coastguard Worker * xmlValidateElementType:
4605*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
4606*6777b538SAndroid Build Coastguard Worker *
4607*6777b538SAndroid Build Coastguard Worker * Try to validate the content model of an element internal function
4608*6777b538SAndroid Build Coastguard Worker *
4609*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 ,-1 in case of error, -2 if an entity
4610*6777b538SAndroid Build Coastguard Worker * reference is found and -3 if the validation succeeded but
4611*6777b538SAndroid Build Coastguard Worker * the content model is not determinist.
4612*6777b538SAndroid Build Coastguard Worker */
4613*6777b538SAndroid Build Coastguard Worker
4614*6777b538SAndroid Build Coastguard Worker static int
xmlValidateElementType(xmlValidCtxtPtr ctxt)4615*6777b538SAndroid Build Coastguard Worker xmlValidateElementType(xmlValidCtxtPtr ctxt) {
4616*6777b538SAndroid Build Coastguard Worker int ret = -1;
4617*6777b538SAndroid Build Coastguard Worker int determinist = 1;
4618*6777b538SAndroid Build Coastguard Worker
4619*6777b538SAndroid Build Coastguard Worker NODE = xmlValidateSkipIgnorable(NODE);
4620*6777b538SAndroid Build Coastguard Worker if ((NODE == NULL) && (CONT == NULL))
4621*6777b538SAndroid Build Coastguard Worker return(1);
4622*6777b538SAndroid Build Coastguard Worker if ((NODE == NULL) &&
4623*6777b538SAndroid Build Coastguard Worker ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
4624*6777b538SAndroid Build Coastguard Worker (CONT->ocur == XML_ELEMENT_CONTENT_OPT))) {
4625*6777b538SAndroid Build Coastguard Worker return(1);
4626*6777b538SAndroid Build Coastguard Worker }
4627*6777b538SAndroid Build Coastguard Worker if (CONT == NULL) return(-1);
4628*6777b538SAndroid Build Coastguard Worker if ((NODE != NULL) && (NODE->type == XML_ENTITY_REF_NODE))
4629*6777b538SAndroid Build Coastguard Worker return(-2);
4630*6777b538SAndroid Build Coastguard Worker
4631*6777b538SAndroid Build Coastguard Worker /*
4632*6777b538SAndroid Build Coastguard Worker * We arrive here when more states need to be examined
4633*6777b538SAndroid Build Coastguard Worker */
4634*6777b538SAndroid Build Coastguard Worker cont:
4635*6777b538SAndroid Build Coastguard Worker
4636*6777b538SAndroid Build Coastguard Worker /*
4637*6777b538SAndroid Build Coastguard Worker * We just recovered from a rollback generated by a possible
4638*6777b538SAndroid Build Coastguard Worker * epsilon transition, go directly to the analysis phase
4639*6777b538SAndroid Build Coastguard Worker */
4640*6777b538SAndroid Build Coastguard Worker if (STATE == ROLLBACK_PARENT) {
4641*6777b538SAndroid Build Coastguard Worker ret = 1;
4642*6777b538SAndroid Build Coastguard Worker goto analyze;
4643*6777b538SAndroid Build Coastguard Worker }
4644*6777b538SAndroid Build Coastguard Worker
4645*6777b538SAndroid Build Coastguard Worker /*
4646*6777b538SAndroid Build Coastguard Worker * we may have to save a backup state here. This is the equivalent
4647*6777b538SAndroid Build Coastguard Worker * of handling epsilon transition in NFAs.
4648*6777b538SAndroid Build Coastguard Worker */
4649*6777b538SAndroid Build Coastguard Worker if ((CONT != NULL) &&
4650*6777b538SAndroid Build Coastguard Worker ((CONT->parent == NULL) ||
4651*6777b538SAndroid Build Coastguard Worker (CONT->parent == (xmlElementContentPtr) 1) ||
4652*6777b538SAndroid Build Coastguard Worker (CONT->parent->type != XML_ELEMENT_CONTENT_OR)) &&
4653*6777b538SAndroid Build Coastguard Worker ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
4654*6777b538SAndroid Build Coastguard Worker (CONT->ocur == XML_ELEMENT_CONTENT_OPT) ||
4655*6777b538SAndroid Build Coastguard Worker ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) {
4656*6777b538SAndroid Build Coastguard Worker if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0)
4657*6777b538SAndroid Build Coastguard Worker return(0);
4658*6777b538SAndroid Build Coastguard Worker }
4659*6777b538SAndroid Build Coastguard Worker
4660*6777b538SAndroid Build Coastguard Worker
4661*6777b538SAndroid Build Coastguard Worker /*
4662*6777b538SAndroid Build Coastguard Worker * Check first if the content matches
4663*6777b538SAndroid Build Coastguard Worker */
4664*6777b538SAndroid Build Coastguard Worker switch (CONT->type) {
4665*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
4666*6777b538SAndroid Build Coastguard Worker if (NODE == NULL) {
4667*6777b538SAndroid Build Coastguard Worker ret = 0;
4668*6777b538SAndroid Build Coastguard Worker break;
4669*6777b538SAndroid Build Coastguard Worker }
4670*6777b538SAndroid Build Coastguard Worker if (NODE->type == XML_TEXT_NODE) {
4671*6777b538SAndroid Build Coastguard Worker /*
4672*6777b538SAndroid Build Coastguard Worker * go to next element in the content model
4673*6777b538SAndroid Build Coastguard Worker * skipping ignorable elems
4674*6777b538SAndroid Build Coastguard Worker */
4675*6777b538SAndroid Build Coastguard Worker do {
4676*6777b538SAndroid Build Coastguard Worker NODE = NODE->next;
4677*6777b538SAndroid Build Coastguard Worker NODE = xmlValidateSkipIgnorable(NODE);
4678*6777b538SAndroid Build Coastguard Worker if ((NODE != NULL) &&
4679*6777b538SAndroid Build Coastguard Worker (NODE->type == XML_ENTITY_REF_NODE))
4680*6777b538SAndroid Build Coastguard Worker return(-2);
4681*6777b538SAndroid Build Coastguard Worker } while ((NODE != NULL) &&
4682*6777b538SAndroid Build Coastguard Worker ((NODE->type != XML_ELEMENT_NODE) &&
4683*6777b538SAndroid Build Coastguard Worker (NODE->type != XML_TEXT_NODE) &&
4684*6777b538SAndroid Build Coastguard Worker (NODE->type != XML_CDATA_SECTION_NODE)));
4685*6777b538SAndroid Build Coastguard Worker ret = 1;
4686*6777b538SAndroid Build Coastguard Worker break;
4687*6777b538SAndroid Build Coastguard Worker } else {
4688*6777b538SAndroid Build Coastguard Worker ret = 0;
4689*6777b538SAndroid Build Coastguard Worker break;
4690*6777b538SAndroid Build Coastguard Worker }
4691*6777b538SAndroid Build Coastguard Worker break;
4692*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
4693*6777b538SAndroid Build Coastguard Worker if (NODE == NULL) {
4694*6777b538SAndroid Build Coastguard Worker ret = 0;
4695*6777b538SAndroid Build Coastguard Worker break;
4696*6777b538SAndroid Build Coastguard Worker }
4697*6777b538SAndroid Build Coastguard Worker ret = ((NODE->type == XML_ELEMENT_NODE) &&
4698*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(NODE->name, CONT->name)));
4699*6777b538SAndroid Build Coastguard Worker if (ret == 1) {
4700*6777b538SAndroid Build Coastguard Worker if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4701*6777b538SAndroid Build Coastguard Worker ret = (CONT->prefix == NULL);
4702*6777b538SAndroid Build Coastguard Worker } else if (CONT->prefix == NULL) {
4703*6777b538SAndroid Build Coastguard Worker ret = 0;
4704*6777b538SAndroid Build Coastguard Worker } else {
4705*6777b538SAndroid Build Coastguard Worker ret = xmlStrEqual(NODE->ns->prefix, CONT->prefix);
4706*6777b538SAndroid Build Coastguard Worker }
4707*6777b538SAndroid Build Coastguard Worker }
4708*6777b538SAndroid Build Coastguard Worker if (ret == 1) {
4709*6777b538SAndroid Build Coastguard Worker /*
4710*6777b538SAndroid Build Coastguard Worker * go to next element in the content model
4711*6777b538SAndroid Build Coastguard Worker * skipping ignorable elems
4712*6777b538SAndroid Build Coastguard Worker */
4713*6777b538SAndroid Build Coastguard Worker do {
4714*6777b538SAndroid Build Coastguard Worker NODE = NODE->next;
4715*6777b538SAndroid Build Coastguard Worker NODE = xmlValidateSkipIgnorable(NODE);
4716*6777b538SAndroid Build Coastguard Worker if ((NODE != NULL) &&
4717*6777b538SAndroid Build Coastguard Worker (NODE->type == XML_ENTITY_REF_NODE))
4718*6777b538SAndroid Build Coastguard Worker return(-2);
4719*6777b538SAndroid Build Coastguard Worker } while ((NODE != NULL) &&
4720*6777b538SAndroid Build Coastguard Worker ((NODE->type != XML_ELEMENT_NODE) &&
4721*6777b538SAndroid Build Coastguard Worker (NODE->type != XML_TEXT_NODE) &&
4722*6777b538SAndroid Build Coastguard Worker (NODE->type != XML_CDATA_SECTION_NODE)));
4723*6777b538SAndroid Build Coastguard Worker } else {
4724*6777b538SAndroid Build Coastguard Worker ret = 0;
4725*6777b538SAndroid Build Coastguard Worker break;
4726*6777b538SAndroid Build Coastguard Worker }
4727*6777b538SAndroid Build Coastguard Worker break;
4728*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
4729*6777b538SAndroid Build Coastguard Worker /*
4730*6777b538SAndroid Build Coastguard Worker * Small optimization.
4731*6777b538SAndroid Build Coastguard Worker */
4732*6777b538SAndroid Build Coastguard Worker if (CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
4733*6777b538SAndroid Build Coastguard Worker if ((NODE == NULL) ||
4734*6777b538SAndroid Build Coastguard Worker (!xmlStrEqual(NODE->name, CONT->c1->name))) {
4735*6777b538SAndroid Build Coastguard Worker DEPTH++;
4736*6777b538SAndroid Build Coastguard Worker CONT = CONT->c2;
4737*6777b538SAndroid Build Coastguard Worker goto cont;
4738*6777b538SAndroid Build Coastguard Worker }
4739*6777b538SAndroid Build Coastguard Worker if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4740*6777b538SAndroid Build Coastguard Worker ret = (CONT->c1->prefix == NULL);
4741*6777b538SAndroid Build Coastguard Worker } else if (CONT->c1->prefix == NULL) {
4742*6777b538SAndroid Build Coastguard Worker ret = 0;
4743*6777b538SAndroid Build Coastguard Worker } else {
4744*6777b538SAndroid Build Coastguard Worker ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
4745*6777b538SAndroid Build Coastguard Worker }
4746*6777b538SAndroid Build Coastguard Worker if (ret == 0) {
4747*6777b538SAndroid Build Coastguard Worker DEPTH++;
4748*6777b538SAndroid Build Coastguard Worker CONT = CONT->c2;
4749*6777b538SAndroid Build Coastguard Worker goto cont;
4750*6777b538SAndroid Build Coastguard Worker }
4751*6777b538SAndroid Build Coastguard Worker }
4752*6777b538SAndroid Build Coastguard Worker
4753*6777b538SAndroid Build Coastguard Worker /*
4754*6777b538SAndroid Build Coastguard Worker * save the second branch 'or' branch
4755*6777b538SAndroid Build Coastguard Worker */
4756*6777b538SAndroid Build Coastguard Worker if (vstateVPush(ctxt, CONT->c2, NODE, DEPTH + 1,
4757*6777b538SAndroid Build Coastguard Worker OCCURS, ROLLBACK_OR) < 0)
4758*6777b538SAndroid Build Coastguard Worker return(-1);
4759*6777b538SAndroid Build Coastguard Worker DEPTH++;
4760*6777b538SAndroid Build Coastguard Worker CONT = CONT->c1;
4761*6777b538SAndroid Build Coastguard Worker goto cont;
4762*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
4763*6777b538SAndroid Build Coastguard Worker /*
4764*6777b538SAndroid Build Coastguard Worker * Small optimization.
4765*6777b538SAndroid Build Coastguard Worker */
4766*6777b538SAndroid Build Coastguard Worker if ((CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) &&
4767*6777b538SAndroid Build Coastguard Worker ((CONT->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
4768*6777b538SAndroid Build Coastguard Worker (CONT->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
4769*6777b538SAndroid Build Coastguard Worker if ((NODE == NULL) ||
4770*6777b538SAndroid Build Coastguard Worker (!xmlStrEqual(NODE->name, CONT->c1->name))) {
4771*6777b538SAndroid Build Coastguard Worker DEPTH++;
4772*6777b538SAndroid Build Coastguard Worker CONT = CONT->c2;
4773*6777b538SAndroid Build Coastguard Worker goto cont;
4774*6777b538SAndroid Build Coastguard Worker }
4775*6777b538SAndroid Build Coastguard Worker if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) {
4776*6777b538SAndroid Build Coastguard Worker ret = (CONT->c1->prefix == NULL);
4777*6777b538SAndroid Build Coastguard Worker } else if (CONT->c1->prefix == NULL) {
4778*6777b538SAndroid Build Coastguard Worker ret = 0;
4779*6777b538SAndroid Build Coastguard Worker } else {
4780*6777b538SAndroid Build Coastguard Worker ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix);
4781*6777b538SAndroid Build Coastguard Worker }
4782*6777b538SAndroid Build Coastguard Worker if (ret == 0) {
4783*6777b538SAndroid Build Coastguard Worker DEPTH++;
4784*6777b538SAndroid Build Coastguard Worker CONT = CONT->c2;
4785*6777b538SAndroid Build Coastguard Worker goto cont;
4786*6777b538SAndroid Build Coastguard Worker }
4787*6777b538SAndroid Build Coastguard Worker }
4788*6777b538SAndroid Build Coastguard Worker DEPTH++;
4789*6777b538SAndroid Build Coastguard Worker CONT = CONT->c1;
4790*6777b538SAndroid Build Coastguard Worker goto cont;
4791*6777b538SAndroid Build Coastguard Worker }
4792*6777b538SAndroid Build Coastguard Worker
4793*6777b538SAndroid Build Coastguard Worker /*
4794*6777b538SAndroid Build Coastguard Worker * At this point handle going up in the tree
4795*6777b538SAndroid Build Coastguard Worker */
4796*6777b538SAndroid Build Coastguard Worker if (ret == -1) {
4797*6777b538SAndroid Build Coastguard Worker return(ret);
4798*6777b538SAndroid Build Coastguard Worker }
4799*6777b538SAndroid Build Coastguard Worker analyze:
4800*6777b538SAndroid Build Coastguard Worker while (CONT != NULL) {
4801*6777b538SAndroid Build Coastguard Worker /*
4802*6777b538SAndroid Build Coastguard Worker * First do the analysis depending on the occurrence model at
4803*6777b538SAndroid Build Coastguard Worker * this level.
4804*6777b538SAndroid Build Coastguard Worker */
4805*6777b538SAndroid Build Coastguard Worker if (ret == 0) {
4806*6777b538SAndroid Build Coastguard Worker switch (CONT->ocur) {
4807*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
4808*6777b538SAndroid Build Coastguard Worker
4809*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
4810*6777b538SAndroid Build Coastguard Worker cur = ctxt->vstate->node;
4811*6777b538SAndroid Build Coastguard Worker if (vstateVPop(ctxt) < 0 ) {
4812*6777b538SAndroid Build Coastguard Worker return(0);
4813*6777b538SAndroid Build Coastguard Worker }
4814*6777b538SAndroid Build Coastguard Worker if (cur != ctxt->vstate->node)
4815*6777b538SAndroid Build Coastguard Worker determinist = -3;
4816*6777b538SAndroid Build Coastguard Worker goto cont;
4817*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
4818*6777b538SAndroid Build Coastguard Worker if (OCCURRENCE == 0) {
4819*6777b538SAndroid Build Coastguard Worker cur = ctxt->vstate->node;
4820*6777b538SAndroid Build Coastguard Worker if (vstateVPop(ctxt) < 0 ) {
4821*6777b538SAndroid Build Coastguard Worker return(0);
4822*6777b538SAndroid Build Coastguard Worker }
4823*6777b538SAndroid Build Coastguard Worker if (cur != ctxt->vstate->node)
4824*6777b538SAndroid Build Coastguard Worker determinist = -3;
4825*6777b538SAndroid Build Coastguard Worker goto cont;
4826*6777b538SAndroid Build Coastguard Worker }
4827*6777b538SAndroid Build Coastguard Worker ret = 1;
4828*6777b538SAndroid Build Coastguard Worker break;
4829*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
4830*6777b538SAndroid Build Coastguard Worker ret = 1;
4831*6777b538SAndroid Build Coastguard Worker break;
4832*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
4833*6777b538SAndroid Build Coastguard Worker ret = 1;
4834*6777b538SAndroid Build Coastguard Worker break;
4835*6777b538SAndroid Build Coastguard Worker }
4836*6777b538SAndroid Build Coastguard Worker } else {
4837*6777b538SAndroid Build Coastguard Worker switch (CONT->ocur) {
4838*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OPT:
4839*6777b538SAndroid Build Coastguard Worker ret = 1;
4840*6777b538SAndroid Build Coastguard Worker break;
4841*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ONCE:
4842*6777b538SAndroid Build Coastguard Worker ret = 1;
4843*6777b538SAndroid Build Coastguard Worker break;
4844*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PLUS:
4845*6777b538SAndroid Build Coastguard Worker if (STATE == ROLLBACK_PARENT) {
4846*6777b538SAndroid Build Coastguard Worker ret = 1;
4847*6777b538SAndroid Build Coastguard Worker break;
4848*6777b538SAndroid Build Coastguard Worker }
4849*6777b538SAndroid Build Coastguard Worker if (NODE == NULL) {
4850*6777b538SAndroid Build Coastguard Worker ret = 1;
4851*6777b538SAndroid Build Coastguard Worker break;
4852*6777b538SAndroid Build Coastguard Worker }
4853*6777b538SAndroid Build Coastguard Worker SET_OCCURRENCE;
4854*6777b538SAndroid Build Coastguard Worker goto cont;
4855*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_MULT:
4856*6777b538SAndroid Build Coastguard Worker if (STATE == ROLLBACK_PARENT) {
4857*6777b538SAndroid Build Coastguard Worker ret = 1;
4858*6777b538SAndroid Build Coastguard Worker break;
4859*6777b538SAndroid Build Coastguard Worker }
4860*6777b538SAndroid Build Coastguard Worker if (NODE == NULL) {
4861*6777b538SAndroid Build Coastguard Worker ret = 1;
4862*6777b538SAndroid Build Coastguard Worker break;
4863*6777b538SAndroid Build Coastguard Worker }
4864*6777b538SAndroid Build Coastguard Worker /* SET_OCCURRENCE; */
4865*6777b538SAndroid Build Coastguard Worker goto cont;
4866*6777b538SAndroid Build Coastguard Worker }
4867*6777b538SAndroid Build Coastguard Worker }
4868*6777b538SAndroid Build Coastguard Worker STATE = 0;
4869*6777b538SAndroid Build Coastguard Worker
4870*6777b538SAndroid Build Coastguard Worker /*
4871*6777b538SAndroid Build Coastguard Worker * Then act accordingly at the parent level
4872*6777b538SAndroid Build Coastguard Worker */
4873*6777b538SAndroid Build Coastguard Worker RESET_OCCURRENCE;
4874*6777b538SAndroid Build Coastguard Worker if ((CONT->parent == NULL) ||
4875*6777b538SAndroid Build Coastguard Worker (CONT->parent == (xmlElementContentPtr) 1))
4876*6777b538SAndroid Build Coastguard Worker break;
4877*6777b538SAndroid Build Coastguard Worker
4878*6777b538SAndroid Build Coastguard Worker switch (CONT->parent->type) {
4879*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
4880*6777b538SAndroid Build Coastguard Worker return(-1);
4881*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
4882*6777b538SAndroid Build Coastguard Worker return(-1);
4883*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
4884*6777b538SAndroid Build Coastguard Worker if (ret == 1) {
4885*6777b538SAndroid Build Coastguard Worker CONT = CONT->parent;
4886*6777b538SAndroid Build Coastguard Worker DEPTH--;
4887*6777b538SAndroid Build Coastguard Worker } else {
4888*6777b538SAndroid Build Coastguard Worker CONT = CONT->parent;
4889*6777b538SAndroid Build Coastguard Worker DEPTH--;
4890*6777b538SAndroid Build Coastguard Worker }
4891*6777b538SAndroid Build Coastguard Worker break;
4892*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
4893*6777b538SAndroid Build Coastguard Worker if (ret == 0) {
4894*6777b538SAndroid Build Coastguard Worker CONT = CONT->parent;
4895*6777b538SAndroid Build Coastguard Worker DEPTH--;
4896*6777b538SAndroid Build Coastguard Worker } else if (CONT == CONT->parent->c1) {
4897*6777b538SAndroid Build Coastguard Worker CONT = CONT->parent->c2;
4898*6777b538SAndroid Build Coastguard Worker goto cont;
4899*6777b538SAndroid Build Coastguard Worker } else {
4900*6777b538SAndroid Build Coastguard Worker CONT = CONT->parent;
4901*6777b538SAndroid Build Coastguard Worker DEPTH--;
4902*6777b538SAndroid Build Coastguard Worker }
4903*6777b538SAndroid Build Coastguard Worker }
4904*6777b538SAndroid Build Coastguard Worker }
4905*6777b538SAndroid Build Coastguard Worker if (NODE != NULL) {
4906*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
4907*6777b538SAndroid Build Coastguard Worker
4908*6777b538SAndroid Build Coastguard Worker cur = ctxt->vstate->node;
4909*6777b538SAndroid Build Coastguard Worker if (vstateVPop(ctxt) < 0 ) {
4910*6777b538SAndroid Build Coastguard Worker return(0);
4911*6777b538SAndroid Build Coastguard Worker }
4912*6777b538SAndroid Build Coastguard Worker if (cur != ctxt->vstate->node)
4913*6777b538SAndroid Build Coastguard Worker determinist = -3;
4914*6777b538SAndroid Build Coastguard Worker goto cont;
4915*6777b538SAndroid Build Coastguard Worker }
4916*6777b538SAndroid Build Coastguard Worker if (ret == 0) {
4917*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
4918*6777b538SAndroid Build Coastguard Worker
4919*6777b538SAndroid Build Coastguard Worker cur = ctxt->vstate->node;
4920*6777b538SAndroid Build Coastguard Worker if (vstateVPop(ctxt) < 0 ) {
4921*6777b538SAndroid Build Coastguard Worker return(0);
4922*6777b538SAndroid Build Coastguard Worker }
4923*6777b538SAndroid Build Coastguard Worker if (cur != ctxt->vstate->node)
4924*6777b538SAndroid Build Coastguard Worker determinist = -3;
4925*6777b538SAndroid Build Coastguard Worker goto cont;
4926*6777b538SAndroid Build Coastguard Worker }
4927*6777b538SAndroid Build Coastguard Worker return(determinist);
4928*6777b538SAndroid Build Coastguard Worker }
4929*6777b538SAndroid Build Coastguard Worker #endif
4930*6777b538SAndroid Build Coastguard Worker
4931*6777b538SAndroid Build Coastguard Worker /**
4932*6777b538SAndroid Build Coastguard Worker * xmlSnprintfElements:
4933*6777b538SAndroid Build Coastguard Worker * @buf: an output buffer
4934*6777b538SAndroid Build Coastguard Worker * @size: the size of the buffer
4935*6777b538SAndroid Build Coastguard Worker * @content: An element
4936*6777b538SAndroid Build Coastguard Worker * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
4937*6777b538SAndroid Build Coastguard Worker *
4938*6777b538SAndroid Build Coastguard Worker * This will dump the list of elements to the buffer
4939*6777b538SAndroid Build Coastguard Worker * Intended just for the debug routine
4940*6777b538SAndroid Build Coastguard Worker */
4941*6777b538SAndroid Build Coastguard Worker static void
xmlSnprintfElements(char * buf,int size,xmlNodePtr node,int glob)4942*6777b538SAndroid Build Coastguard Worker xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) {
4943*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
4944*6777b538SAndroid Build Coastguard Worker int len;
4945*6777b538SAndroid Build Coastguard Worker
4946*6777b538SAndroid Build Coastguard Worker if (node == NULL) return;
4947*6777b538SAndroid Build Coastguard Worker if (glob) strcat(buf, "(");
4948*6777b538SAndroid Build Coastguard Worker cur = node;
4949*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
4950*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
4951*6777b538SAndroid Build Coastguard Worker if (size - len < 50) {
4952*6777b538SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
4953*6777b538SAndroid Build Coastguard Worker strcat(buf, " ...");
4954*6777b538SAndroid Build Coastguard Worker return;
4955*6777b538SAndroid Build Coastguard Worker }
4956*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
4957*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
4958*6777b538SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4959*6777b538SAndroid Build Coastguard Worker if (size - len < xmlStrlen(cur->ns->prefix) + 10) {
4960*6777b538SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
4961*6777b538SAndroid Build Coastguard Worker strcat(buf, " ...");
4962*6777b538SAndroid Build Coastguard Worker return;
4963*6777b538SAndroid Build Coastguard Worker }
4964*6777b538SAndroid Build Coastguard Worker strcat(buf, (char *) cur->ns->prefix);
4965*6777b538SAndroid Build Coastguard Worker strcat(buf, ":");
4966*6777b538SAndroid Build Coastguard Worker }
4967*6777b538SAndroid Build Coastguard Worker if (size - len < xmlStrlen(cur->name) + 10) {
4968*6777b538SAndroid Build Coastguard Worker if ((size - len > 4) && (buf[len - 1] != '.'))
4969*6777b538SAndroid Build Coastguard Worker strcat(buf, " ...");
4970*6777b538SAndroid Build Coastguard Worker return;
4971*6777b538SAndroid Build Coastguard Worker }
4972*6777b538SAndroid Build Coastguard Worker strcat(buf, (char *) cur->name);
4973*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL)
4974*6777b538SAndroid Build Coastguard Worker strcat(buf, " ");
4975*6777b538SAndroid Build Coastguard Worker break;
4976*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
4977*6777b538SAndroid Build Coastguard Worker if (xmlIsBlankNode(cur))
4978*6777b538SAndroid Build Coastguard Worker break;
4979*6777b538SAndroid Build Coastguard Worker /* Falls through. */
4980*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
4981*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
4982*6777b538SAndroid Build Coastguard Worker strcat(buf, "CDATA");
4983*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL)
4984*6777b538SAndroid Build Coastguard Worker strcat(buf, " ");
4985*6777b538SAndroid Build Coastguard Worker break;
4986*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
4987*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
4988*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
4989*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
4990*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
4991*6777b538SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
4992*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
4993*6777b538SAndroid Build Coastguard Worker strcat(buf, "???");
4994*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL)
4995*6777b538SAndroid Build Coastguard Worker strcat(buf, " ");
4996*6777b538SAndroid Build Coastguard Worker break;
4997*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
4998*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
4999*6777b538SAndroid Build Coastguard Worker case XML_DTD_NODE:
5000*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
5001*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
5002*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
5003*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
5004*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
5005*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
5006*6777b538SAndroid Build Coastguard Worker break;
5007*6777b538SAndroid Build Coastguard Worker }
5008*6777b538SAndroid Build Coastguard Worker cur = cur->next;
5009*6777b538SAndroid Build Coastguard Worker }
5010*6777b538SAndroid Build Coastguard Worker if (glob) strcat(buf, ")");
5011*6777b538SAndroid Build Coastguard Worker }
5012*6777b538SAndroid Build Coastguard Worker
5013*6777b538SAndroid Build Coastguard Worker /**
5014*6777b538SAndroid Build Coastguard Worker * xmlValidateElementContent:
5015*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
5016*6777b538SAndroid Build Coastguard Worker * @child: the child list
5017*6777b538SAndroid Build Coastguard Worker * @elemDecl: pointer to the element declaration
5018*6777b538SAndroid Build Coastguard Worker * @warn: emit the error message
5019*6777b538SAndroid Build Coastguard Worker * @parent: the parent element (for error reporting)
5020*6777b538SAndroid Build Coastguard Worker *
5021*6777b538SAndroid Build Coastguard Worker * Try to validate the content model of an element
5022*6777b538SAndroid Build Coastguard Worker *
5023*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 if not and -1 in case of error
5024*6777b538SAndroid Build Coastguard Worker */
5025*6777b538SAndroid Build Coastguard Worker
5026*6777b538SAndroid Build Coastguard Worker static int
xmlValidateElementContent(xmlValidCtxtPtr ctxt,xmlNodePtr child,xmlElementPtr elemDecl,int warn,xmlNodePtr parent)5027*6777b538SAndroid Build Coastguard Worker xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
5028*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl, int warn, xmlNodePtr parent) {
5029*6777b538SAndroid Build Coastguard Worker int ret = 1;
5030*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_REGEXP_ENABLED
5031*6777b538SAndroid Build Coastguard Worker xmlNodePtr repl = NULL, last = NULL, tmp;
5032*6777b538SAndroid Build Coastguard Worker #endif
5033*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
5034*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr cont;
5035*6777b538SAndroid Build Coastguard Worker const xmlChar *name;
5036*6777b538SAndroid Build Coastguard Worker
5037*6777b538SAndroid Build Coastguard Worker if ((elemDecl == NULL) || (parent == NULL) || (ctxt == NULL))
5038*6777b538SAndroid Build Coastguard Worker return(-1);
5039*6777b538SAndroid Build Coastguard Worker cont = elemDecl->content;
5040*6777b538SAndroid Build Coastguard Worker name = elemDecl->name;
5041*6777b538SAndroid Build Coastguard Worker
5042*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
5043*6777b538SAndroid Build Coastguard Worker /* Build the regexp associated to the content model */
5044*6777b538SAndroid Build Coastguard Worker if (elemDecl->contModel == NULL)
5045*6777b538SAndroid Build Coastguard Worker ret = xmlValidBuildContentModel(ctxt, elemDecl);
5046*6777b538SAndroid Build Coastguard Worker if (elemDecl->contModel == NULL) {
5047*6777b538SAndroid Build Coastguard Worker return(-1);
5048*6777b538SAndroid Build Coastguard Worker } else {
5049*6777b538SAndroid Build Coastguard Worker xmlRegExecCtxtPtr exec;
5050*6777b538SAndroid Build Coastguard Worker
5051*6777b538SAndroid Build Coastguard Worker if (!xmlRegexpIsDeterminist(elemDecl->contModel)) {
5052*6777b538SAndroid Build Coastguard Worker return(-1);
5053*6777b538SAndroid Build Coastguard Worker }
5054*6777b538SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
5055*6777b538SAndroid Build Coastguard Worker ctxt->nodeNr = 0;
5056*6777b538SAndroid Build Coastguard Worker ctxt->nodeTab = NULL;
5057*6777b538SAndroid Build Coastguard Worker exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL);
5058*6777b538SAndroid Build Coastguard Worker if (exec == NULL) {
5059*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5060*6777b538SAndroid Build Coastguard Worker return(-1);
5061*6777b538SAndroid Build Coastguard Worker }
5062*6777b538SAndroid Build Coastguard Worker cur = child;
5063*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
5064*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
5065*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5066*6777b538SAndroid Build Coastguard Worker /*
5067*6777b538SAndroid Build Coastguard Worker * Push the current node to be able to roll back
5068*6777b538SAndroid Build Coastguard Worker * and process within the entity
5069*6777b538SAndroid Build Coastguard Worker */
5070*6777b538SAndroid Build Coastguard Worker if ((cur->children != NULL) &&
5071*6777b538SAndroid Build Coastguard Worker (cur->children->children != NULL)) {
5072*6777b538SAndroid Build Coastguard Worker nodeVPush(ctxt, cur);
5073*6777b538SAndroid Build Coastguard Worker cur = cur->children->children;
5074*6777b538SAndroid Build Coastguard Worker continue;
5075*6777b538SAndroid Build Coastguard Worker }
5076*6777b538SAndroid Build Coastguard Worker break;
5077*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5078*6777b538SAndroid Build Coastguard Worker if (xmlIsBlankNode(cur))
5079*6777b538SAndroid Build Coastguard Worker break;
5080*6777b538SAndroid Build Coastguard Worker ret = 0;
5081*6777b538SAndroid Build Coastguard Worker goto fail;
5082*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5083*6777b538SAndroid Build Coastguard Worker /* TODO */
5084*6777b538SAndroid Build Coastguard Worker ret = 0;
5085*6777b538SAndroid Build Coastguard Worker goto fail;
5086*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
5087*6777b538SAndroid Build Coastguard Worker if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5088*6777b538SAndroid Build Coastguard Worker xmlChar fn[50];
5089*6777b538SAndroid Build Coastguard Worker xmlChar *fullname;
5090*6777b538SAndroid Build Coastguard Worker
5091*6777b538SAndroid Build Coastguard Worker fullname = xmlBuildQName(cur->name,
5092*6777b538SAndroid Build Coastguard Worker cur->ns->prefix, fn, 50);
5093*6777b538SAndroid Build Coastguard Worker if (fullname == NULL) {
5094*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5095*6777b538SAndroid Build Coastguard Worker ret = -1;
5096*6777b538SAndroid Build Coastguard Worker goto fail;
5097*6777b538SAndroid Build Coastguard Worker }
5098*6777b538SAndroid Build Coastguard Worker ret = xmlRegExecPushString(exec, fullname, NULL);
5099*6777b538SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != cur->name))
5100*6777b538SAndroid Build Coastguard Worker xmlFree(fullname);
5101*6777b538SAndroid Build Coastguard Worker } else {
5102*6777b538SAndroid Build Coastguard Worker ret = xmlRegExecPushString(exec, cur->name, NULL);
5103*6777b538SAndroid Build Coastguard Worker }
5104*6777b538SAndroid Build Coastguard Worker break;
5105*6777b538SAndroid Build Coastguard Worker default:
5106*6777b538SAndroid Build Coastguard Worker break;
5107*6777b538SAndroid Build Coastguard Worker }
5108*6777b538SAndroid Build Coastguard Worker if (ret == XML_REGEXP_OUT_OF_MEMORY)
5109*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5110*6777b538SAndroid Build Coastguard Worker /*
5111*6777b538SAndroid Build Coastguard Worker * Switch to next element
5112*6777b538SAndroid Build Coastguard Worker */
5113*6777b538SAndroid Build Coastguard Worker cur = cur->next;
5114*6777b538SAndroid Build Coastguard Worker while (cur == NULL) {
5115*6777b538SAndroid Build Coastguard Worker cur = nodeVPop(ctxt);
5116*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
5117*6777b538SAndroid Build Coastguard Worker break;
5118*6777b538SAndroid Build Coastguard Worker cur = cur->next;
5119*6777b538SAndroid Build Coastguard Worker }
5120*6777b538SAndroid Build Coastguard Worker }
5121*6777b538SAndroid Build Coastguard Worker ret = xmlRegExecPushString(exec, NULL, NULL);
5122*6777b538SAndroid Build Coastguard Worker fail:
5123*6777b538SAndroid Build Coastguard Worker xmlRegFreeExecCtxt(exec);
5124*6777b538SAndroid Build Coastguard Worker }
5125*6777b538SAndroid Build Coastguard Worker #else /* LIBXML_REGEXP_ENABLED */
5126*6777b538SAndroid Build Coastguard Worker /*
5127*6777b538SAndroid Build Coastguard Worker * Allocate the stack
5128*6777b538SAndroid Build Coastguard Worker */
5129*6777b538SAndroid Build Coastguard Worker ctxt->vstateMax = 8;
5130*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab = (xmlValidState *) xmlMalloc(
5131*6777b538SAndroid Build Coastguard Worker ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
5132*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateTab == NULL) {
5133*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5134*6777b538SAndroid Build Coastguard Worker return(-1);
5135*6777b538SAndroid Build Coastguard Worker }
5136*6777b538SAndroid Build Coastguard Worker /*
5137*6777b538SAndroid Build Coastguard Worker * The first entry in the stack is reserved to the current state
5138*6777b538SAndroid Build Coastguard Worker */
5139*6777b538SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
5140*6777b538SAndroid Build Coastguard Worker ctxt->nodeNr = 0;
5141*6777b538SAndroid Build Coastguard Worker ctxt->nodeTab = NULL;
5142*6777b538SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[0];
5143*6777b538SAndroid Build Coastguard Worker ctxt->vstateNr = 1;
5144*6777b538SAndroid Build Coastguard Worker CONT = cont;
5145*6777b538SAndroid Build Coastguard Worker NODE = child;
5146*6777b538SAndroid Build Coastguard Worker DEPTH = 0;
5147*6777b538SAndroid Build Coastguard Worker OCCURS = 0;
5148*6777b538SAndroid Build Coastguard Worker STATE = 0;
5149*6777b538SAndroid Build Coastguard Worker ret = xmlValidateElementType(ctxt);
5150*6777b538SAndroid Build Coastguard Worker if ((ret == -3) && (warn)) {
5151*6777b538SAndroid Build Coastguard Worker char expr[5000];
5152*6777b538SAndroid Build Coastguard Worker expr[0] = 0;
5153*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(expr, 5000, elemDecl->content, 1);
5154*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl,
5155*6777b538SAndroid Build Coastguard Worker XML_DTD_CONTENT_NOT_DETERMINIST,
5156*6777b538SAndroid Build Coastguard Worker "Content model of %s is not deterministic: %s\n",
5157*6777b538SAndroid Build Coastguard Worker name, BAD_CAST expr, NULL);
5158*6777b538SAndroid Build Coastguard Worker } else if (ret == -2) {
5159*6777b538SAndroid Build Coastguard Worker /*
5160*6777b538SAndroid Build Coastguard Worker * An entities reference appeared at this level.
5161*6777b538SAndroid Build Coastguard Worker * Build a minimal representation of this node content
5162*6777b538SAndroid Build Coastguard Worker * sufficient to run the validation process on it
5163*6777b538SAndroid Build Coastguard Worker */
5164*6777b538SAndroid Build Coastguard Worker cur = child;
5165*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
5166*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
5167*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5168*6777b538SAndroid Build Coastguard Worker /*
5169*6777b538SAndroid Build Coastguard Worker * Push the current node to be able to roll back
5170*6777b538SAndroid Build Coastguard Worker * and process within the entity
5171*6777b538SAndroid Build Coastguard Worker */
5172*6777b538SAndroid Build Coastguard Worker if ((cur->children != NULL) &&
5173*6777b538SAndroid Build Coastguard Worker (cur->children->children != NULL)) {
5174*6777b538SAndroid Build Coastguard Worker nodeVPush(ctxt, cur);
5175*6777b538SAndroid Build Coastguard Worker cur = cur->children->children;
5176*6777b538SAndroid Build Coastguard Worker continue;
5177*6777b538SAndroid Build Coastguard Worker }
5178*6777b538SAndroid Build Coastguard Worker break;
5179*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5180*6777b538SAndroid Build Coastguard Worker if (xmlIsBlankNode(cur))
5181*6777b538SAndroid Build Coastguard Worker break;
5182*6777b538SAndroid Build Coastguard Worker /* no break on purpose */
5183*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5184*6777b538SAndroid Build Coastguard Worker /* no break on purpose */
5185*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
5186*6777b538SAndroid Build Coastguard Worker /*
5187*6777b538SAndroid Build Coastguard Worker * Allocate a new node and minimally fills in
5188*6777b538SAndroid Build Coastguard Worker * what's required
5189*6777b538SAndroid Build Coastguard Worker */
5190*6777b538SAndroid Build Coastguard Worker tmp = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
5191*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
5192*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5193*6777b538SAndroid Build Coastguard Worker xmlFreeNodeList(repl);
5194*6777b538SAndroid Build Coastguard Worker ret = -1;
5195*6777b538SAndroid Build Coastguard Worker goto done;
5196*6777b538SAndroid Build Coastguard Worker }
5197*6777b538SAndroid Build Coastguard Worker tmp->type = cur->type;
5198*6777b538SAndroid Build Coastguard Worker tmp->name = cur->name;
5199*6777b538SAndroid Build Coastguard Worker tmp->ns = cur->ns;
5200*6777b538SAndroid Build Coastguard Worker tmp->next = NULL;
5201*6777b538SAndroid Build Coastguard Worker tmp->content = NULL;
5202*6777b538SAndroid Build Coastguard Worker if (repl == NULL)
5203*6777b538SAndroid Build Coastguard Worker repl = last = tmp;
5204*6777b538SAndroid Build Coastguard Worker else {
5205*6777b538SAndroid Build Coastguard Worker last->next = tmp;
5206*6777b538SAndroid Build Coastguard Worker last = tmp;
5207*6777b538SAndroid Build Coastguard Worker }
5208*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_CDATA_SECTION_NODE) {
5209*6777b538SAndroid Build Coastguard Worker /*
5210*6777b538SAndroid Build Coastguard Worker * E59 spaces in CDATA does not match the
5211*6777b538SAndroid Build Coastguard Worker * nonterminal S
5212*6777b538SAndroid Build Coastguard Worker */
5213*6777b538SAndroid Build Coastguard Worker tmp->content = xmlStrdup(BAD_CAST "CDATA");
5214*6777b538SAndroid Build Coastguard Worker }
5215*6777b538SAndroid Build Coastguard Worker break;
5216*6777b538SAndroid Build Coastguard Worker default:
5217*6777b538SAndroid Build Coastguard Worker break;
5218*6777b538SAndroid Build Coastguard Worker }
5219*6777b538SAndroid Build Coastguard Worker /*
5220*6777b538SAndroid Build Coastguard Worker * Switch to next element
5221*6777b538SAndroid Build Coastguard Worker */
5222*6777b538SAndroid Build Coastguard Worker cur = cur->next;
5223*6777b538SAndroid Build Coastguard Worker while (cur == NULL) {
5224*6777b538SAndroid Build Coastguard Worker cur = nodeVPop(ctxt);
5225*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
5226*6777b538SAndroid Build Coastguard Worker break;
5227*6777b538SAndroid Build Coastguard Worker cur = cur->next;
5228*6777b538SAndroid Build Coastguard Worker }
5229*6777b538SAndroid Build Coastguard Worker }
5230*6777b538SAndroid Build Coastguard Worker
5231*6777b538SAndroid Build Coastguard Worker /*
5232*6777b538SAndroid Build Coastguard Worker * Relaunch the validation
5233*6777b538SAndroid Build Coastguard Worker */
5234*6777b538SAndroid Build Coastguard Worker ctxt->vstate = &ctxt->vstateTab[0];
5235*6777b538SAndroid Build Coastguard Worker ctxt->vstateNr = 1;
5236*6777b538SAndroid Build Coastguard Worker CONT = cont;
5237*6777b538SAndroid Build Coastguard Worker NODE = repl;
5238*6777b538SAndroid Build Coastguard Worker DEPTH = 0;
5239*6777b538SAndroid Build Coastguard Worker OCCURS = 0;
5240*6777b538SAndroid Build Coastguard Worker STATE = 0;
5241*6777b538SAndroid Build Coastguard Worker ret = xmlValidateElementType(ctxt);
5242*6777b538SAndroid Build Coastguard Worker }
5243*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
5244*6777b538SAndroid Build Coastguard Worker if ((warn) && ((ret != 1) && (ret != -3))) {
5245*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL) {
5246*6777b538SAndroid Build Coastguard Worker char expr[5000];
5247*6777b538SAndroid Build Coastguard Worker char list[5000];
5248*6777b538SAndroid Build Coastguard Worker
5249*6777b538SAndroid Build Coastguard Worker expr[0] = 0;
5250*6777b538SAndroid Build Coastguard Worker xmlSnprintfElementContent(&expr[0], 5000, cont, 1);
5251*6777b538SAndroid Build Coastguard Worker list[0] = 0;
5252*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_REGEXP_ENABLED
5253*6777b538SAndroid Build Coastguard Worker if (repl != NULL)
5254*6777b538SAndroid Build Coastguard Worker xmlSnprintfElements(&list[0], 5000, repl, 1);
5255*6777b538SAndroid Build Coastguard Worker else
5256*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
5257*6777b538SAndroid Build Coastguard Worker xmlSnprintfElements(&list[0], 5000, child, 1);
5258*6777b538SAndroid Build Coastguard Worker
5259*6777b538SAndroid Build Coastguard Worker if (name != NULL) {
5260*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5261*6777b538SAndroid Build Coastguard Worker "Element %s content does not follow the DTD, expecting %s, got %s\n",
5262*6777b538SAndroid Build Coastguard Worker name, BAD_CAST expr, BAD_CAST list);
5263*6777b538SAndroid Build Coastguard Worker } else {
5264*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5265*6777b538SAndroid Build Coastguard Worker "Element content does not follow the DTD, expecting %s, got %s\n",
5266*6777b538SAndroid Build Coastguard Worker BAD_CAST expr, BAD_CAST list, NULL);
5267*6777b538SAndroid Build Coastguard Worker }
5268*6777b538SAndroid Build Coastguard Worker } else {
5269*6777b538SAndroid Build Coastguard Worker if (name != NULL) {
5270*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5271*6777b538SAndroid Build Coastguard Worker "Element %s content does not follow the DTD\n",
5272*6777b538SAndroid Build Coastguard Worker name, NULL, NULL);
5273*6777b538SAndroid Build Coastguard Worker } else {
5274*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL,
5275*6777b538SAndroid Build Coastguard Worker "Element content does not follow the DTD\n",
5276*6777b538SAndroid Build Coastguard Worker NULL, NULL, NULL);
5277*6777b538SAndroid Build Coastguard Worker }
5278*6777b538SAndroid Build Coastguard Worker }
5279*6777b538SAndroid Build Coastguard Worker ret = 0;
5280*6777b538SAndroid Build Coastguard Worker }
5281*6777b538SAndroid Build Coastguard Worker if (ret == -3)
5282*6777b538SAndroid Build Coastguard Worker ret = 1;
5283*6777b538SAndroid Build Coastguard Worker
5284*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_REGEXP_ENABLED
5285*6777b538SAndroid Build Coastguard Worker done:
5286*6777b538SAndroid Build Coastguard Worker /*
5287*6777b538SAndroid Build Coastguard Worker * Deallocate the copy if done, and free up the validation stack
5288*6777b538SAndroid Build Coastguard Worker */
5289*6777b538SAndroid Build Coastguard Worker while (repl != NULL) {
5290*6777b538SAndroid Build Coastguard Worker tmp = repl->next;
5291*6777b538SAndroid Build Coastguard Worker xmlFree(repl);
5292*6777b538SAndroid Build Coastguard Worker repl = tmp;
5293*6777b538SAndroid Build Coastguard Worker }
5294*6777b538SAndroid Build Coastguard Worker ctxt->vstateMax = 0;
5295*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateTab != NULL) {
5296*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->vstateTab);
5297*6777b538SAndroid Build Coastguard Worker ctxt->vstateTab = NULL;
5298*6777b538SAndroid Build Coastguard Worker }
5299*6777b538SAndroid Build Coastguard Worker #endif
5300*6777b538SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
5301*6777b538SAndroid Build Coastguard Worker ctxt->nodeNr = 0;
5302*6777b538SAndroid Build Coastguard Worker if (ctxt->nodeTab != NULL) {
5303*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->nodeTab);
5304*6777b538SAndroid Build Coastguard Worker ctxt->nodeTab = NULL;
5305*6777b538SAndroid Build Coastguard Worker }
5306*6777b538SAndroid Build Coastguard Worker return(ret);
5307*6777b538SAndroid Build Coastguard Worker
5308*6777b538SAndroid Build Coastguard Worker }
5309*6777b538SAndroid Build Coastguard Worker
5310*6777b538SAndroid Build Coastguard Worker /**
5311*6777b538SAndroid Build Coastguard Worker * xmlValidateCdataElement:
5312*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
5313*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
5314*6777b538SAndroid Build Coastguard Worker * @elem: an element instance
5315*6777b538SAndroid Build Coastguard Worker *
5316*6777b538SAndroid Build Coastguard Worker * Check that an element follows #CDATA
5317*6777b538SAndroid Build Coastguard Worker *
5318*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
5319*6777b538SAndroid Build Coastguard Worker */
5320*6777b538SAndroid Build Coastguard Worker static int
xmlValidateOneCdataElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem)5321*6777b538SAndroid Build Coastguard Worker xmlValidateOneCdataElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5322*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem) {
5323*6777b538SAndroid Build Coastguard Worker int ret = 1;
5324*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur, child;
5325*6777b538SAndroid Build Coastguard Worker
5326*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (doc == NULL) || (elem == NULL) ||
5327*6777b538SAndroid Build Coastguard Worker (elem->type != XML_ELEMENT_NODE))
5328*6777b538SAndroid Build Coastguard Worker return(0);
5329*6777b538SAndroid Build Coastguard Worker
5330*6777b538SAndroid Build Coastguard Worker child = elem->children;
5331*6777b538SAndroid Build Coastguard Worker
5332*6777b538SAndroid Build Coastguard Worker cur = child;
5333*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
5334*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
5335*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5336*6777b538SAndroid Build Coastguard Worker /*
5337*6777b538SAndroid Build Coastguard Worker * Push the current node to be able to roll back
5338*6777b538SAndroid Build Coastguard Worker * and process within the entity
5339*6777b538SAndroid Build Coastguard Worker */
5340*6777b538SAndroid Build Coastguard Worker if ((cur->children != NULL) &&
5341*6777b538SAndroid Build Coastguard Worker (cur->children->children != NULL)) {
5342*6777b538SAndroid Build Coastguard Worker nodeVPush(ctxt, cur);
5343*6777b538SAndroid Build Coastguard Worker cur = cur->children->children;
5344*6777b538SAndroid Build Coastguard Worker continue;
5345*6777b538SAndroid Build Coastguard Worker }
5346*6777b538SAndroid Build Coastguard Worker break;
5347*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
5348*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
5349*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5350*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5351*6777b538SAndroid Build Coastguard Worker break;
5352*6777b538SAndroid Build Coastguard Worker default:
5353*6777b538SAndroid Build Coastguard Worker ret = 0;
5354*6777b538SAndroid Build Coastguard Worker goto done;
5355*6777b538SAndroid Build Coastguard Worker }
5356*6777b538SAndroid Build Coastguard Worker /*
5357*6777b538SAndroid Build Coastguard Worker * Switch to next element
5358*6777b538SAndroid Build Coastguard Worker */
5359*6777b538SAndroid Build Coastguard Worker cur = cur->next;
5360*6777b538SAndroid Build Coastguard Worker while (cur == NULL) {
5361*6777b538SAndroid Build Coastguard Worker cur = nodeVPop(ctxt);
5362*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
5363*6777b538SAndroid Build Coastguard Worker break;
5364*6777b538SAndroid Build Coastguard Worker cur = cur->next;
5365*6777b538SAndroid Build Coastguard Worker }
5366*6777b538SAndroid Build Coastguard Worker }
5367*6777b538SAndroid Build Coastguard Worker done:
5368*6777b538SAndroid Build Coastguard Worker ctxt->nodeMax = 0;
5369*6777b538SAndroid Build Coastguard Worker ctxt->nodeNr = 0;
5370*6777b538SAndroid Build Coastguard Worker if (ctxt->nodeTab != NULL) {
5371*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->nodeTab);
5372*6777b538SAndroid Build Coastguard Worker ctxt->nodeTab = NULL;
5373*6777b538SAndroid Build Coastguard Worker }
5374*6777b538SAndroid Build Coastguard Worker return(ret);
5375*6777b538SAndroid Build Coastguard Worker }
5376*6777b538SAndroid Build Coastguard Worker
5377*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
5378*6777b538SAndroid Build Coastguard Worker /**
5379*6777b538SAndroid Build Coastguard Worker * xmlValidateCheckMixed:
5380*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
5381*6777b538SAndroid Build Coastguard Worker * @cont: the mixed content model
5382*6777b538SAndroid Build Coastguard Worker * @qname: the qualified name as appearing in the serialization
5383*6777b538SAndroid Build Coastguard Worker *
5384*6777b538SAndroid Build Coastguard Worker * Check if the given node is part of the content model.
5385*6777b538SAndroid Build Coastguard Worker *
5386*6777b538SAndroid Build Coastguard Worker * Returns 1 if yes, 0 if no, -1 in case of error
5387*6777b538SAndroid Build Coastguard Worker */
5388*6777b538SAndroid Build Coastguard Worker static int
xmlValidateCheckMixed(xmlValidCtxtPtr ctxt,xmlElementContentPtr cont,const xmlChar * qname)5389*6777b538SAndroid Build Coastguard Worker xmlValidateCheckMixed(xmlValidCtxtPtr ctxt,
5390*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr cont, const xmlChar *qname) {
5391*6777b538SAndroid Build Coastguard Worker const xmlChar *name;
5392*6777b538SAndroid Build Coastguard Worker int plen;
5393*6777b538SAndroid Build Coastguard Worker name = xmlSplitQName3(qname, &plen);
5394*6777b538SAndroid Build Coastguard Worker
5395*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
5396*6777b538SAndroid Build Coastguard Worker while (cont != NULL) {
5397*6777b538SAndroid Build Coastguard Worker if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5398*6777b538SAndroid Build Coastguard Worker if ((cont->prefix == NULL) && (xmlStrEqual(cont->name, qname)))
5399*6777b538SAndroid Build Coastguard Worker return(1);
5400*6777b538SAndroid Build Coastguard Worker } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5401*6777b538SAndroid Build Coastguard Worker (cont->c1 != NULL) &&
5402*6777b538SAndroid Build Coastguard Worker (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5403*6777b538SAndroid Build Coastguard Worker if ((cont->c1->prefix == NULL) &&
5404*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(cont->c1->name, qname)))
5405*6777b538SAndroid Build Coastguard Worker return(1);
5406*6777b538SAndroid Build Coastguard Worker } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5407*6777b538SAndroid Build Coastguard Worker (cont->c1 == NULL) ||
5408*6777b538SAndroid Build Coastguard Worker (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5409*6777b538SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
5410*6777b538SAndroid Build Coastguard Worker "Internal: MIXED struct corrupted\n",
5411*6777b538SAndroid Build Coastguard Worker NULL);
5412*6777b538SAndroid Build Coastguard Worker break;
5413*6777b538SAndroid Build Coastguard Worker }
5414*6777b538SAndroid Build Coastguard Worker cont = cont->c2;
5415*6777b538SAndroid Build Coastguard Worker }
5416*6777b538SAndroid Build Coastguard Worker } else {
5417*6777b538SAndroid Build Coastguard Worker while (cont != NULL) {
5418*6777b538SAndroid Build Coastguard Worker if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5419*6777b538SAndroid Build Coastguard Worker if ((cont->prefix != NULL) &&
5420*6777b538SAndroid Build Coastguard Worker (xmlStrncmp(cont->prefix, qname, plen) == 0) &&
5421*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(cont->name, name)))
5422*6777b538SAndroid Build Coastguard Worker return(1);
5423*6777b538SAndroid Build Coastguard Worker } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5424*6777b538SAndroid Build Coastguard Worker (cont->c1 != NULL) &&
5425*6777b538SAndroid Build Coastguard Worker (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5426*6777b538SAndroid Build Coastguard Worker if ((cont->c1->prefix != NULL) &&
5427*6777b538SAndroid Build Coastguard Worker (xmlStrncmp(cont->c1->prefix, qname, plen) == 0) &&
5428*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(cont->c1->name, name)))
5429*6777b538SAndroid Build Coastguard Worker return(1);
5430*6777b538SAndroid Build Coastguard Worker } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5431*6777b538SAndroid Build Coastguard Worker (cont->c1 == NULL) ||
5432*6777b538SAndroid Build Coastguard Worker (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5433*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
5434*6777b538SAndroid Build Coastguard Worker "Internal: MIXED struct corrupted\n",
5435*6777b538SAndroid Build Coastguard Worker NULL);
5436*6777b538SAndroid Build Coastguard Worker break;
5437*6777b538SAndroid Build Coastguard Worker }
5438*6777b538SAndroid Build Coastguard Worker cont = cont->c2;
5439*6777b538SAndroid Build Coastguard Worker }
5440*6777b538SAndroid Build Coastguard Worker }
5441*6777b538SAndroid Build Coastguard Worker return(0);
5442*6777b538SAndroid Build Coastguard Worker }
5443*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
5444*6777b538SAndroid Build Coastguard Worker
5445*6777b538SAndroid Build Coastguard Worker /**
5446*6777b538SAndroid Build Coastguard Worker * xmlValidGetElemDecl:
5447*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
5448*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
5449*6777b538SAndroid Build Coastguard Worker * @elem: an element instance
5450*6777b538SAndroid Build Coastguard Worker * @extsubset: pointer, (out) indicate if the declaration was found
5451*6777b538SAndroid Build Coastguard Worker * in the external subset.
5452*6777b538SAndroid Build Coastguard Worker *
5453*6777b538SAndroid Build Coastguard Worker * Finds a declaration associated to an element in the document.
5454*6777b538SAndroid Build Coastguard Worker *
5455*6777b538SAndroid Build Coastguard Worker * returns the pointer to the declaration or NULL if not found.
5456*6777b538SAndroid Build Coastguard Worker */
5457*6777b538SAndroid Build Coastguard Worker static xmlElementPtr
xmlValidGetElemDecl(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,int * extsubset)5458*6777b538SAndroid Build Coastguard Worker xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5459*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem, int *extsubset) {
5460*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl = NULL;
5461*6777b538SAndroid Build Coastguard Worker const xmlChar *prefix = NULL;
5462*6777b538SAndroid Build Coastguard Worker
5463*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (doc == NULL) ||
5464*6777b538SAndroid Build Coastguard Worker (elem == NULL) || (elem->name == NULL))
5465*6777b538SAndroid Build Coastguard Worker return(NULL);
5466*6777b538SAndroid Build Coastguard Worker if (extsubset != NULL)
5467*6777b538SAndroid Build Coastguard Worker *extsubset = 0;
5468*6777b538SAndroid Build Coastguard Worker
5469*6777b538SAndroid Build Coastguard Worker /*
5470*6777b538SAndroid Build Coastguard Worker * Fetch the declaration for the qualified name
5471*6777b538SAndroid Build Coastguard Worker */
5472*6777b538SAndroid Build Coastguard Worker if ((elem->ns != NULL) && (elem->ns->prefix != NULL))
5473*6777b538SAndroid Build Coastguard Worker prefix = elem->ns->prefix;
5474*6777b538SAndroid Build Coastguard Worker
5475*6777b538SAndroid Build Coastguard Worker if (prefix != NULL) {
5476*6777b538SAndroid Build Coastguard Worker elemDecl = xmlGetDtdQElementDesc(doc->intSubset,
5477*6777b538SAndroid Build Coastguard Worker elem->name, prefix);
5478*6777b538SAndroid Build Coastguard Worker if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
5479*6777b538SAndroid Build Coastguard Worker elemDecl = xmlGetDtdQElementDesc(doc->extSubset,
5480*6777b538SAndroid Build Coastguard Worker elem->name, prefix);
5481*6777b538SAndroid Build Coastguard Worker if ((elemDecl != NULL) && (extsubset != NULL))
5482*6777b538SAndroid Build Coastguard Worker *extsubset = 1;
5483*6777b538SAndroid Build Coastguard Worker }
5484*6777b538SAndroid Build Coastguard Worker }
5485*6777b538SAndroid Build Coastguard Worker
5486*6777b538SAndroid Build Coastguard Worker /*
5487*6777b538SAndroid Build Coastguard Worker * Fetch the declaration for the non qualified name
5488*6777b538SAndroid Build Coastguard Worker * This is "non-strict" validation should be done on the
5489*6777b538SAndroid Build Coastguard Worker * full QName but in that case being flexible makes sense.
5490*6777b538SAndroid Build Coastguard Worker */
5491*6777b538SAndroid Build Coastguard Worker if (elemDecl == NULL) {
5492*6777b538SAndroid Build Coastguard Worker elemDecl = xmlGetDtdQElementDesc(doc->intSubset, elem->name, NULL);
5493*6777b538SAndroid Build Coastguard Worker if ((elemDecl == NULL) && (doc->extSubset != NULL)) {
5494*6777b538SAndroid Build Coastguard Worker elemDecl = xmlGetDtdQElementDesc(doc->extSubset, elem->name, NULL);
5495*6777b538SAndroid Build Coastguard Worker if ((elemDecl != NULL) && (extsubset != NULL))
5496*6777b538SAndroid Build Coastguard Worker *extsubset = 1;
5497*6777b538SAndroid Build Coastguard Worker }
5498*6777b538SAndroid Build Coastguard Worker }
5499*6777b538SAndroid Build Coastguard Worker if (elemDecl == NULL) {
5500*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem,
5501*6777b538SAndroid Build Coastguard Worker XML_DTD_UNKNOWN_ELEM,
5502*6777b538SAndroid Build Coastguard Worker "No declaration for element %s\n",
5503*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5504*6777b538SAndroid Build Coastguard Worker }
5505*6777b538SAndroid Build Coastguard Worker return(elemDecl);
5506*6777b538SAndroid Build Coastguard Worker }
5507*6777b538SAndroid Build Coastguard Worker
5508*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
5509*6777b538SAndroid Build Coastguard Worker /**
5510*6777b538SAndroid Build Coastguard Worker * xmlValidatePushElement:
5511*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
5512*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
5513*6777b538SAndroid Build Coastguard Worker * @elem: an element instance
5514*6777b538SAndroid Build Coastguard Worker * @qname: the qualified name as appearing in the serialization
5515*6777b538SAndroid Build Coastguard Worker *
5516*6777b538SAndroid Build Coastguard Worker * Push a new element start on the validation stack.
5517*6777b538SAndroid Build Coastguard Worker *
5518*6777b538SAndroid Build Coastguard Worker * returns 1 if no validation problem was found or 0 otherwise
5519*6777b538SAndroid Build Coastguard Worker */
5520*6777b538SAndroid Build Coastguard Worker int
xmlValidatePushElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem,const xmlChar * qname)5521*6777b538SAndroid Build Coastguard Worker xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5522*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem, const xmlChar *qname) {
5523*6777b538SAndroid Build Coastguard Worker int ret = 1;
5524*6777b538SAndroid Build Coastguard Worker xmlElementPtr eDecl;
5525*6777b538SAndroid Build Coastguard Worker int extsubset = 0;
5526*6777b538SAndroid Build Coastguard Worker
5527*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
5528*6777b538SAndroid Build Coastguard Worker return(0);
5529*6777b538SAndroid Build Coastguard Worker /* printf("PushElem %s\n", qname); */
5530*6777b538SAndroid Build Coastguard Worker if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5531*6777b538SAndroid Build Coastguard Worker xmlValidStatePtr state = ctxt->vstate;
5532*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
5533*6777b538SAndroid Build Coastguard Worker
5534*6777b538SAndroid Build Coastguard Worker /*
5535*6777b538SAndroid Build Coastguard Worker * Check the new element against the content model of the new elem.
5536*6777b538SAndroid Build Coastguard Worker */
5537*6777b538SAndroid Build Coastguard Worker if (state->elemDecl != NULL) {
5538*6777b538SAndroid Build Coastguard Worker elemDecl = state->elemDecl;
5539*6777b538SAndroid Build Coastguard Worker
5540*6777b538SAndroid Build Coastguard Worker switch(elemDecl->etype) {
5541*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_UNDEFINED:
5542*6777b538SAndroid Build Coastguard Worker ret = 0;
5543*6777b538SAndroid Build Coastguard Worker break;
5544*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
5545*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5546*6777b538SAndroid Build Coastguard Worker XML_DTD_NOT_EMPTY,
5547*6777b538SAndroid Build Coastguard Worker "Element %s was declared EMPTY this one has content\n",
5548*6777b538SAndroid Build Coastguard Worker state->node->name, NULL, NULL);
5549*6777b538SAndroid Build Coastguard Worker ret = 0;
5550*6777b538SAndroid Build Coastguard Worker break;
5551*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
5552*6777b538SAndroid Build Coastguard Worker /* I don't think anything is required then */
5553*6777b538SAndroid Build Coastguard Worker break;
5554*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
5555*6777b538SAndroid Build Coastguard Worker /* simple case of declared as #PCDATA */
5556*6777b538SAndroid Build Coastguard Worker if ((elemDecl->content != NULL) &&
5557*6777b538SAndroid Build Coastguard Worker (elemDecl->content->type ==
5558*6777b538SAndroid Build Coastguard Worker XML_ELEMENT_CONTENT_PCDATA)) {
5559*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5560*6777b538SAndroid Build Coastguard Worker XML_DTD_NOT_PCDATA,
5561*6777b538SAndroid Build Coastguard Worker "Element %s was declared #PCDATA but contains non text nodes\n",
5562*6777b538SAndroid Build Coastguard Worker state->node->name, NULL, NULL);
5563*6777b538SAndroid Build Coastguard Worker ret = 0;
5564*6777b538SAndroid Build Coastguard Worker } else {
5565*6777b538SAndroid Build Coastguard Worker ret = xmlValidateCheckMixed(ctxt, elemDecl->content,
5566*6777b538SAndroid Build Coastguard Worker qname);
5567*6777b538SAndroid Build Coastguard Worker if (ret != 1) {
5568*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5569*6777b538SAndroid Build Coastguard Worker XML_DTD_INVALID_CHILD,
5570*6777b538SAndroid Build Coastguard Worker "Element %s is not declared in %s list of possible children\n",
5571*6777b538SAndroid Build Coastguard Worker qname, state->node->name, NULL);
5572*6777b538SAndroid Build Coastguard Worker }
5573*6777b538SAndroid Build Coastguard Worker }
5574*6777b538SAndroid Build Coastguard Worker break;
5575*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT:
5576*6777b538SAndroid Build Coastguard Worker /*
5577*6777b538SAndroid Build Coastguard Worker * TODO:
5578*6777b538SAndroid Build Coastguard Worker * VC: Standalone Document Declaration
5579*6777b538SAndroid Build Coastguard Worker * - element types with element content, if white space
5580*6777b538SAndroid Build Coastguard Worker * occurs directly within any instance of those types.
5581*6777b538SAndroid Build Coastguard Worker */
5582*6777b538SAndroid Build Coastguard Worker if (state->exec != NULL) {
5583*6777b538SAndroid Build Coastguard Worker ret = xmlRegExecPushString(state->exec, qname, NULL);
5584*6777b538SAndroid Build Coastguard Worker if (ret == XML_REGEXP_OUT_OF_MEMORY) {
5585*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
5586*6777b538SAndroid Build Coastguard Worker return(0);
5587*6777b538SAndroid Build Coastguard Worker }
5588*6777b538SAndroid Build Coastguard Worker if (ret < 0) {
5589*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5590*6777b538SAndroid Build Coastguard Worker XML_DTD_CONTENT_MODEL,
5591*6777b538SAndroid Build Coastguard Worker "Element %s content does not follow the DTD, Misplaced %s\n",
5592*6777b538SAndroid Build Coastguard Worker state->node->name, qname, NULL);
5593*6777b538SAndroid Build Coastguard Worker ret = 0;
5594*6777b538SAndroid Build Coastguard Worker } else {
5595*6777b538SAndroid Build Coastguard Worker ret = 1;
5596*6777b538SAndroid Build Coastguard Worker }
5597*6777b538SAndroid Build Coastguard Worker }
5598*6777b538SAndroid Build Coastguard Worker break;
5599*6777b538SAndroid Build Coastguard Worker }
5600*6777b538SAndroid Build Coastguard Worker }
5601*6777b538SAndroid Build Coastguard Worker }
5602*6777b538SAndroid Build Coastguard Worker eDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
5603*6777b538SAndroid Build Coastguard Worker vstateVPush(ctxt, eDecl, elem);
5604*6777b538SAndroid Build Coastguard Worker return(ret);
5605*6777b538SAndroid Build Coastguard Worker }
5606*6777b538SAndroid Build Coastguard Worker
5607*6777b538SAndroid Build Coastguard Worker /**
5608*6777b538SAndroid Build Coastguard Worker * xmlValidatePushCData:
5609*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
5610*6777b538SAndroid Build Coastguard Worker * @data: some character data read
5611*6777b538SAndroid Build Coastguard Worker * @len: the length of the data
5612*6777b538SAndroid Build Coastguard Worker *
5613*6777b538SAndroid Build Coastguard Worker * check the CData parsed for validation in the current stack
5614*6777b538SAndroid Build Coastguard Worker *
5615*6777b538SAndroid Build Coastguard Worker * returns 1 if no validation problem was found or 0 otherwise
5616*6777b538SAndroid Build Coastguard Worker */
5617*6777b538SAndroid Build Coastguard Worker int
xmlValidatePushCData(xmlValidCtxtPtr ctxt,const xmlChar * data,int len)5618*6777b538SAndroid Build Coastguard Worker xmlValidatePushCData(xmlValidCtxtPtr ctxt, const xmlChar *data, int len) {
5619*6777b538SAndroid Build Coastguard Worker int ret = 1;
5620*6777b538SAndroid Build Coastguard Worker
5621*6777b538SAndroid Build Coastguard Worker /* printf("CDATA %s %d\n", data, len); */
5622*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
5623*6777b538SAndroid Build Coastguard Worker return(0);
5624*6777b538SAndroid Build Coastguard Worker if (len <= 0)
5625*6777b538SAndroid Build Coastguard Worker return(ret);
5626*6777b538SAndroid Build Coastguard Worker if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5627*6777b538SAndroid Build Coastguard Worker xmlValidStatePtr state = ctxt->vstate;
5628*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
5629*6777b538SAndroid Build Coastguard Worker
5630*6777b538SAndroid Build Coastguard Worker /*
5631*6777b538SAndroid Build Coastguard Worker * Check the new element against the content model of the new elem.
5632*6777b538SAndroid Build Coastguard Worker */
5633*6777b538SAndroid Build Coastguard Worker if (state->elemDecl != NULL) {
5634*6777b538SAndroid Build Coastguard Worker elemDecl = state->elemDecl;
5635*6777b538SAndroid Build Coastguard Worker
5636*6777b538SAndroid Build Coastguard Worker switch(elemDecl->etype) {
5637*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_UNDEFINED:
5638*6777b538SAndroid Build Coastguard Worker ret = 0;
5639*6777b538SAndroid Build Coastguard Worker break;
5640*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
5641*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5642*6777b538SAndroid Build Coastguard Worker XML_DTD_NOT_EMPTY,
5643*6777b538SAndroid Build Coastguard Worker "Element %s was declared EMPTY this one has content\n",
5644*6777b538SAndroid Build Coastguard Worker state->node->name, NULL, NULL);
5645*6777b538SAndroid Build Coastguard Worker ret = 0;
5646*6777b538SAndroid Build Coastguard Worker break;
5647*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
5648*6777b538SAndroid Build Coastguard Worker break;
5649*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
5650*6777b538SAndroid Build Coastguard Worker break;
5651*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT: {
5652*6777b538SAndroid Build Coastguard Worker int i;
5653*6777b538SAndroid Build Coastguard Worker
5654*6777b538SAndroid Build Coastguard Worker for (i = 0;i < len;i++) {
5655*6777b538SAndroid Build Coastguard Worker if (!IS_BLANK_CH(data[i])) {
5656*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5657*6777b538SAndroid Build Coastguard Worker XML_DTD_CONTENT_MODEL,
5658*6777b538SAndroid Build Coastguard Worker "Element %s content does not follow the DTD, Text not allowed\n",
5659*6777b538SAndroid Build Coastguard Worker state->node->name, NULL, NULL);
5660*6777b538SAndroid Build Coastguard Worker ret = 0;
5661*6777b538SAndroid Build Coastguard Worker goto done;
5662*6777b538SAndroid Build Coastguard Worker }
5663*6777b538SAndroid Build Coastguard Worker }
5664*6777b538SAndroid Build Coastguard Worker /*
5665*6777b538SAndroid Build Coastguard Worker * TODO:
5666*6777b538SAndroid Build Coastguard Worker * VC: Standalone Document Declaration
5667*6777b538SAndroid Build Coastguard Worker * element types with element content, if white space
5668*6777b538SAndroid Build Coastguard Worker * occurs directly within any instance of those types.
5669*6777b538SAndroid Build Coastguard Worker */
5670*6777b538SAndroid Build Coastguard Worker break;
5671*6777b538SAndroid Build Coastguard Worker }
5672*6777b538SAndroid Build Coastguard Worker }
5673*6777b538SAndroid Build Coastguard Worker }
5674*6777b538SAndroid Build Coastguard Worker }
5675*6777b538SAndroid Build Coastguard Worker done:
5676*6777b538SAndroid Build Coastguard Worker return(ret);
5677*6777b538SAndroid Build Coastguard Worker }
5678*6777b538SAndroid Build Coastguard Worker
5679*6777b538SAndroid Build Coastguard Worker /**
5680*6777b538SAndroid Build Coastguard Worker * xmlValidatePopElement:
5681*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
5682*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
5683*6777b538SAndroid Build Coastguard Worker * @elem: an element instance
5684*6777b538SAndroid Build Coastguard Worker * @qname: the qualified name as appearing in the serialization
5685*6777b538SAndroid Build Coastguard Worker *
5686*6777b538SAndroid Build Coastguard Worker * Pop the element end from the validation stack.
5687*6777b538SAndroid Build Coastguard Worker *
5688*6777b538SAndroid Build Coastguard Worker * returns 1 if no validation problem was found or 0 otherwise
5689*6777b538SAndroid Build Coastguard Worker */
5690*6777b538SAndroid Build Coastguard Worker int
xmlValidatePopElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc ATTRIBUTE_UNUSED,xmlNodePtr elem ATTRIBUTE_UNUSED,const xmlChar * qname ATTRIBUTE_UNUSED)5691*6777b538SAndroid Build Coastguard Worker xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED,
5692*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem ATTRIBUTE_UNUSED,
5693*6777b538SAndroid Build Coastguard Worker const xmlChar *qname ATTRIBUTE_UNUSED) {
5694*6777b538SAndroid Build Coastguard Worker int ret = 1;
5695*6777b538SAndroid Build Coastguard Worker
5696*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
5697*6777b538SAndroid Build Coastguard Worker return(0);
5698*6777b538SAndroid Build Coastguard Worker /* printf("PopElem %s\n", qname); */
5699*6777b538SAndroid Build Coastguard Worker if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) {
5700*6777b538SAndroid Build Coastguard Worker xmlValidStatePtr state = ctxt->vstate;
5701*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl;
5702*6777b538SAndroid Build Coastguard Worker
5703*6777b538SAndroid Build Coastguard Worker /*
5704*6777b538SAndroid Build Coastguard Worker * Check the new element against the content model of the new elem.
5705*6777b538SAndroid Build Coastguard Worker */
5706*6777b538SAndroid Build Coastguard Worker if (state->elemDecl != NULL) {
5707*6777b538SAndroid Build Coastguard Worker elemDecl = state->elemDecl;
5708*6777b538SAndroid Build Coastguard Worker
5709*6777b538SAndroid Build Coastguard Worker if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) {
5710*6777b538SAndroid Build Coastguard Worker if (state->exec != NULL) {
5711*6777b538SAndroid Build Coastguard Worker ret = xmlRegExecPushString(state->exec, NULL, NULL);
5712*6777b538SAndroid Build Coastguard Worker if (ret <= 0) {
5713*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, state->node,
5714*6777b538SAndroid Build Coastguard Worker XML_DTD_CONTENT_MODEL,
5715*6777b538SAndroid Build Coastguard Worker "Element %s content does not follow the DTD, Expecting more children\n",
5716*6777b538SAndroid Build Coastguard Worker state->node->name, NULL,NULL);
5717*6777b538SAndroid Build Coastguard Worker ret = 0;
5718*6777b538SAndroid Build Coastguard Worker } else {
5719*6777b538SAndroid Build Coastguard Worker /*
5720*6777b538SAndroid Build Coastguard Worker * previous validation errors should not generate
5721*6777b538SAndroid Build Coastguard Worker * a new one here
5722*6777b538SAndroid Build Coastguard Worker */
5723*6777b538SAndroid Build Coastguard Worker ret = 1;
5724*6777b538SAndroid Build Coastguard Worker }
5725*6777b538SAndroid Build Coastguard Worker }
5726*6777b538SAndroid Build Coastguard Worker }
5727*6777b538SAndroid Build Coastguard Worker }
5728*6777b538SAndroid Build Coastguard Worker vstateVPop(ctxt);
5729*6777b538SAndroid Build Coastguard Worker }
5730*6777b538SAndroid Build Coastguard Worker return(ret);
5731*6777b538SAndroid Build Coastguard Worker }
5732*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
5733*6777b538SAndroid Build Coastguard Worker
5734*6777b538SAndroid Build Coastguard Worker /**
5735*6777b538SAndroid Build Coastguard Worker * xmlValidateOneElement:
5736*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
5737*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
5738*6777b538SAndroid Build Coastguard Worker * @elem: an element instance
5739*6777b538SAndroid Build Coastguard Worker *
5740*6777b538SAndroid Build Coastguard Worker * Try to validate a single element and it's attributes,
5741*6777b538SAndroid Build Coastguard Worker * basically it does the following checks as described by the
5742*6777b538SAndroid Build Coastguard Worker * XML-1.0 recommendation:
5743*6777b538SAndroid Build Coastguard Worker * - [ VC: Element Valid ]
5744*6777b538SAndroid Build Coastguard Worker * - [ VC: Required Attribute ]
5745*6777b538SAndroid Build Coastguard Worker * Then call xmlValidateOneAttribute() for each attribute present.
5746*6777b538SAndroid Build Coastguard Worker *
5747*6777b538SAndroid Build Coastguard Worker * The ID/IDREF checkings are done separately
5748*6777b538SAndroid Build Coastguard Worker *
5749*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
5750*6777b538SAndroid Build Coastguard Worker */
5751*6777b538SAndroid Build Coastguard Worker
5752*6777b538SAndroid Build Coastguard Worker int
xmlValidateOneElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr elem)5753*6777b538SAndroid Build Coastguard Worker xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
5754*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem) {
5755*6777b538SAndroid Build Coastguard Worker xmlElementPtr elemDecl = NULL;
5756*6777b538SAndroid Build Coastguard Worker xmlElementContentPtr cont;
5757*6777b538SAndroid Build Coastguard Worker xmlAttributePtr attr;
5758*6777b538SAndroid Build Coastguard Worker xmlNodePtr child;
5759*6777b538SAndroid Build Coastguard Worker int ret = 1, tmp;
5760*6777b538SAndroid Build Coastguard Worker const xmlChar *name;
5761*6777b538SAndroid Build Coastguard Worker int extsubset = 0;
5762*6777b538SAndroid Build Coastguard Worker
5763*6777b538SAndroid Build Coastguard Worker CHECK_DTD;
5764*6777b538SAndroid Build Coastguard Worker
5765*6777b538SAndroid Build Coastguard Worker if (elem == NULL) return(0);
5766*6777b538SAndroid Build Coastguard Worker switch (elem->type) {
5767*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
5768*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5769*6777b538SAndroid Build Coastguard Worker "Attribute element not expected\n", NULL, NULL ,NULL);
5770*6777b538SAndroid Build Coastguard Worker return(0);
5771*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5772*6777b538SAndroid Build Coastguard Worker if (elem->children != NULL) {
5773*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5774*6777b538SAndroid Build Coastguard Worker "Text element has children !\n",
5775*6777b538SAndroid Build Coastguard Worker NULL,NULL,NULL);
5776*6777b538SAndroid Build Coastguard Worker return(0);
5777*6777b538SAndroid Build Coastguard Worker }
5778*6777b538SAndroid Build Coastguard Worker if (elem->ns != NULL) {
5779*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5780*6777b538SAndroid Build Coastguard Worker "Text element has namespace !\n",
5781*6777b538SAndroid Build Coastguard Worker NULL,NULL,NULL);
5782*6777b538SAndroid Build Coastguard Worker return(0);
5783*6777b538SAndroid Build Coastguard Worker }
5784*6777b538SAndroid Build Coastguard Worker if (elem->content == NULL) {
5785*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5786*6777b538SAndroid Build Coastguard Worker "Text element has no content !\n",
5787*6777b538SAndroid Build Coastguard Worker NULL,NULL,NULL);
5788*6777b538SAndroid Build Coastguard Worker return(0);
5789*6777b538SAndroid Build Coastguard Worker }
5790*6777b538SAndroid Build Coastguard Worker return(1);
5791*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
5792*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
5793*6777b538SAndroid Build Coastguard Worker return(1);
5794*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5795*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
5796*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
5797*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
5798*6777b538SAndroid Build Coastguard Worker return(1);
5799*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
5800*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5801*6777b538SAndroid Build Coastguard Worker "Entity element not expected\n", NULL, NULL ,NULL);
5802*6777b538SAndroid Build Coastguard Worker return(0);
5803*6777b538SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
5804*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5805*6777b538SAndroid Build Coastguard Worker "Notation element not expected\n", NULL, NULL ,NULL);
5806*6777b538SAndroid Build Coastguard Worker return(0);
5807*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
5808*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
5809*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
5810*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5811*6777b538SAndroid Build Coastguard Worker "Document element not expected\n", NULL, NULL ,NULL);
5812*6777b538SAndroid Build Coastguard Worker return(0);
5813*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
5814*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5815*6777b538SAndroid Build Coastguard Worker "HTML Document not expected\n", NULL, NULL ,NULL);
5816*6777b538SAndroid Build Coastguard Worker return(0);
5817*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
5818*6777b538SAndroid Build Coastguard Worker break;
5819*6777b538SAndroid Build Coastguard Worker default:
5820*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
5821*6777b538SAndroid Build Coastguard Worker "unknown element type\n", NULL, NULL ,NULL);
5822*6777b538SAndroid Build Coastguard Worker return(0);
5823*6777b538SAndroid Build Coastguard Worker }
5824*6777b538SAndroid Build Coastguard Worker
5825*6777b538SAndroid Build Coastguard Worker /*
5826*6777b538SAndroid Build Coastguard Worker * Fetch the declaration
5827*6777b538SAndroid Build Coastguard Worker */
5828*6777b538SAndroid Build Coastguard Worker elemDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset);
5829*6777b538SAndroid Build Coastguard Worker if (elemDecl == NULL)
5830*6777b538SAndroid Build Coastguard Worker return(0);
5831*6777b538SAndroid Build Coastguard Worker
5832*6777b538SAndroid Build Coastguard Worker /*
5833*6777b538SAndroid Build Coastguard Worker * If vstateNr is not zero that means continuous validation is
5834*6777b538SAndroid Build Coastguard Worker * activated, do not try to check the content model at that level.
5835*6777b538SAndroid Build Coastguard Worker */
5836*6777b538SAndroid Build Coastguard Worker if (ctxt->vstateNr == 0) {
5837*6777b538SAndroid Build Coastguard Worker /* Check that the element content matches the definition */
5838*6777b538SAndroid Build Coastguard Worker switch (elemDecl->etype) {
5839*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_UNDEFINED:
5840*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ELEM,
5841*6777b538SAndroid Build Coastguard Worker "No declaration for element %s\n",
5842*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5843*6777b538SAndroid Build Coastguard Worker return(0);
5844*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_EMPTY:
5845*6777b538SAndroid Build Coastguard Worker if (elem->children != NULL) {
5846*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOT_EMPTY,
5847*6777b538SAndroid Build Coastguard Worker "Element %s was declared EMPTY this one has content\n",
5848*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5849*6777b538SAndroid Build Coastguard Worker ret = 0;
5850*6777b538SAndroid Build Coastguard Worker }
5851*6777b538SAndroid Build Coastguard Worker break;
5852*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ANY:
5853*6777b538SAndroid Build Coastguard Worker /* I don't think anything is required then */
5854*6777b538SAndroid Build Coastguard Worker break;
5855*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_MIXED:
5856*6777b538SAndroid Build Coastguard Worker
5857*6777b538SAndroid Build Coastguard Worker /* simple case of declared as #PCDATA */
5858*6777b538SAndroid Build Coastguard Worker if ((elemDecl->content != NULL) &&
5859*6777b538SAndroid Build Coastguard Worker (elemDecl->content->type == XML_ELEMENT_CONTENT_PCDATA)) {
5860*6777b538SAndroid Build Coastguard Worker ret = xmlValidateOneCdataElement(ctxt, doc, elem);
5861*6777b538SAndroid Build Coastguard Worker if (!ret) {
5862*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_NOT_PCDATA,
5863*6777b538SAndroid Build Coastguard Worker "Element %s was declared #PCDATA but contains non text nodes\n",
5864*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5865*6777b538SAndroid Build Coastguard Worker }
5866*6777b538SAndroid Build Coastguard Worker break;
5867*6777b538SAndroid Build Coastguard Worker }
5868*6777b538SAndroid Build Coastguard Worker child = elem->children;
5869*6777b538SAndroid Build Coastguard Worker /* Hum, this start to get messy */
5870*6777b538SAndroid Build Coastguard Worker while (child != NULL) {
5871*6777b538SAndroid Build Coastguard Worker if (child->type == XML_ELEMENT_NODE) {
5872*6777b538SAndroid Build Coastguard Worker name = child->name;
5873*6777b538SAndroid Build Coastguard Worker if ((child->ns != NULL) && (child->ns->prefix != NULL)) {
5874*6777b538SAndroid Build Coastguard Worker xmlChar fn[50];
5875*6777b538SAndroid Build Coastguard Worker xmlChar *fullname;
5876*6777b538SAndroid Build Coastguard Worker
5877*6777b538SAndroid Build Coastguard Worker fullname = xmlBuildQName(child->name, child->ns->prefix,
5878*6777b538SAndroid Build Coastguard Worker fn, 50);
5879*6777b538SAndroid Build Coastguard Worker if (fullname == NULL)
5880*6777b538SAndroid Build Coastguard Worker return(0);
5881*6777b538SAndroid Build Coastguard Worker cont = elemDecl->content;
5882*6777b538SAndroid Build Coastguard Worker while (cont != NULL) {
5883*6777b538SAndroid Build Coastguard Worker if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5884*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(cont->name, fullname))
5885*6777b538SAndroid Build Coastguard Worker break;
5886*6777b538SAndroid Build Coastguard Worker } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5887*6777b538SAndroid Build Coastguard Worker (cont->c1 != NULL) &&
5888*6777b538SAndroid Build Coastguard Worker (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
5889*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(cont->c1->name, fullname))
5890*6777b538SAndroid Build Coastguard Worker break;
5891*6777b538SAndroid Build Coastguard Worker } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5892*6777b538SAndroid Build Coastguard Worker (cont->c1 == NULL) ||
5893*6777b538SAndroid Build Coastguard Worker (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
5894*6777b538SAndroid Build Coastguard Worker xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT,
5895*6777b538SAndroid Build Coastguard Worker "Internal: MIXED struct corrupted\n",
5896*6777b538SAndroid Build Coastguard Worker NULL);
5897*6777b538SAndroid Build Coastguard Worker break;
5898*6777b538SAndroid Build Coastguard Worker }
5899*6777b538SAndroid Build Coastguard Worker cont = cont->c2;
5900*6777b538SAndroid Build Coastguard Worker }
5901*6777b538SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != child->name))
5902*6777b538SAndroid Build Coastguard Worker xmlFree(fullname);
5903*6777b538SAndroid Build Coastguard Worker if (cont != NULL)
5904*6777b538SAndroid Build Coastguard Worker goto child_ok;
5905*6777b538SAndroid Build Coastguard Worker }
5906*6777b538SAndroid Build Coastguard Worker cont = elemDecl->content;
5907*6777b538SAndroid Build Coastguard Worker while (cont != NULL) {
5908*6777b538SAndroid Build Coastguard Worker if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
5909*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(cont->name, name)) break;
5910*6777b538SAndroid Build Coastguard Worker } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
5911*6777b538SAndroid Build Coastguard Worker (cont->c1 != NULL) &&
5912*6777b538SAndroid Build Coastguard Worker (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)) {
5913*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(cont->c1->name, name)) break;
5914*6777b538SAndroid Build Coastguard Worker } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
5915*6777b538SAndroid Build Coastguard Worker (cont->c1 == NULL) ||
5916*6777b538SAndroid Build Coastguard Worker (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)) {
5917*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT,
5918*6777b538SAndroid Build Coastguard Worker "Internal: MIXED struct corrupted\n",
5919*6777b538SAndroid Build Coastguard Worker NULL);
5920*6777b538SAndroid Build Coastguard Worker break;
5921*6777b538SAndroid Build Coastguard Worker }
5922*6777b538SAndroid Build Coastguard Worker cont = cont->c2;
5923*6777b538SAndroid Build Coastguard Worker }
5924*6777b538SAndroid Build Coastguard Worker if (cont == NULL) {
5925*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_CHILD,
5926*6777b538SAndroid Build Coastguard Worker "Element %s is not declared in %s list of possible children\n",
5927*6777b538SAndroid Build Coastguard Worker name, elem->name, NULL);
5928*6777b538SAndroid Build Coastguard Worker ret = 0;
5929*6777b538SAndroid Build Coastguard Worker }
5930*6777b538SAndroid Build Coastguard Worker }
5931*6777b538SAndroid Build Coastguard Worker child_ok:
5932*6777b538SAndroid Build Coastguard Worker child = child->next;
5933*6777b538SAndroid Build Coastguard Worker }
5934*6777b538SAndroid Build Coastguard Worker break;
5935*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_TYPE_ELEMENT:
5936*6777b538SAndroid Build Coastguard Worker if ((doc->standalone == 1) && (extsubset == 1)) {
5937*6777b538SAndroid Build Coastguard Worker /*
5938*6777b538SAndroid Build Coastguard Worker * VC: Standalone Document Declaration
5939*6777b538SAndroid Build Coastguard Worker * - element types with element content, if white space
5940*6777b538SAndroid Build Coastguard Worker * occurs directly within any instance of those types.
5941*6777b538SAndroid Build Coastguard Worker */
5942*6777b538SAndroid Build Coastguard Worker child = elem->children;
5943*6777b538SAndroid Build Coastguard Worker while (child != NULL) {
5944*6777b538SAndroid Build Coastguard Worker if (child->type == XML_TEXT_NODE) {
5945*6777b538SAndroid Build Coastguard Worker const xmlChar *content = child->content;
5946*6777b538SAndroid Build Coastguard Worker
5947*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*content))
5948*6777b538SAndroid Build Coastguard Worker content++;
5949*6777b538SAndroid Build Coastguard Worker if (*content == 0) {
5950*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem,
5951*6777b538SAndroid Build Coastguard Worker XML_DTD_STANDALONE_WHITE_SPACE,
5952*6777b538SAndroid Build Coastguard Worker "standalone: %s declared in the external subset contains white spaces nodes\n",
5953*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
5954*6777b538SAndroid Build Coastguard Worker ret = 0;
5955*6777b538SAndroid Build Coastguard Worker break;
5956*6777b538SAndroid Build Coastguard Worker }
5957*6777b538SAndroid Build Coastguard Worker }
5958*6777b538SAndroid Build Coastguard Worker child =child->next;
5959*6777b538SAndroid Build Coastguard Worker }
5960*6777b538SAndroid Build Coastguard Worker }
5961*6777b538SAndroid Build Coastguard Worker child = elem->children;
5962*6777b538SAndroid Build Coastguard Worker cont = elemDecl->content;
5963*6777b538SAndroid Build Coastguard Worker tmp = xmlValidateElementContent(ctxt, child, elemDecl, 1, elem);
5964*6777b538SAndroid Build Coastguard Worker if (tmp <= 0)
5965*6777b538SAndroid Build Coastguard Worker ret = tmp;
5966*6777b538SAndroid Build Coastguard Worker break;
5967*6777b538SAndroid Build Coastguard Worker }
5968*6777b538SAndroid Build Coastguard Worker } /* not continuous */
5969*6777b538SAndroid Build Coastguard Worker
5970*6777b538SAndroid Build Coastguard Worker /* [ VC: Required Attribute ] */
5971*6777b538SAndroid Build Coastguard Worker attr = elemDecl->attributes;
5972*6777b538SAndroid Build Coastguard Worker while (attr != NULL) {
5973*6777b538SAndroid Build Coastguard Worker if (attr->def == XML_ATTRIBUTE_REQUIRED) {
5974*6777b538SAndroid Build Coastguard Worker int qualified = -1;
5975*6777b538SAndroid Build Coastguard Worker
5976*6777b538SAndroid Build Coastguard Worker if ((attr->prefix == NULL) &&
5977*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
5978*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns;
5979*6777b538SAndroid Build Coastguard Worker
5980*6777b538SAndroid Build Coastguard Worker ns = elem->nsDef;
5981*6777b538SAndroid Build Coastguard Worker while (ns != NULL) {
5982*6777b538SAndroid Build Coastguard Worker if (ns->prefix == NULL)
5983*6777b538SAndroid Build Coastguard Worker goto found;
5984*6777b538SAndroid Build Coastguard Worker ns = ns->next;
5985*6777b538SAndroid Build Coastguard Worker }
5986*6777b538SAndroid Build Coastguard Worker } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
5987*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns;
5988*6777b538SAndroid Build Coastguard Worker
5989*6777b538SAndroid Build Coastguard Worker ns = elem->nsDef;
5990*6777b538SAndroid Build Coastguard Worker while (ns != NULL) {
5991*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(attr->name, ns->prefix))
5992*6777b538SAndroid Build Coastguard Worker goto found;
5993*6777b538SAndroid Build Coastguard Worker ns = ns->next;
5994*6777b538SAndroid Build Coastguard Worker }
5995*6777b538SAndroid Build Coastguard Worker } else {
5996*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attrib;
5997*6777b538SAndroid Build Coastguard Worker
5998*6777b538SAndroid Build Coastguard Worker attrib = elem->properties;
5999*6777b538SAndroid Build Coastguard Worker while (attrib != NULL) {
6000*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(attrib->name, attr->name)) {
6001*6777b538SAndroid Build Coastguard Worker if (attr->prefix != NULL) {
6002*6777b538SAndroid Build Coastguard Worker xmlNsPtr nameSpace = attrib->ns;
6003*6777b538SAndroid Build Coastguard Worker
6004*6777b538SAndroid Build Coastguard Worker if (nameSpace == NULL)
6005*6777b538SAndroid Build Coastguard Worker nameSpace = elem->ns;
6006*6777b538SAndroid Build Coastguard Worker /*
6007*6777b538SAndroid Build Coastguard Worker * qualified names handling is problematic, having a
6008*6777b538SAndroid Build Coastguard Worker * different prefix should be possible but DTDs don't
6009*6777b538SAndroid Build Coastguard Worker * allow to define the URI instead of the prefix :-(
6010*6777b538SAndroid Build Coastguard Worker */
6011*6777b538SAndroid Build Coastguard Worker if (nameSpace == NULL) {
6012*6777b538SAndroid Build Coastguard Worker if (qualified < 0)
6013*6777b538SAndroid Build Coastguard Worker qualified = 0;
6014*6777b538SAndroid Build Coastguard Worker } else if (!xmlStrEqual(nameSpace->prefix,
6015*6777b538SAndroid Build Coastguard Worker attr->prefix)) {
6016*6777b538SAndroid Build Coastguard Worker if (qualified < 1)
6017*6777b538SAndroid Build Coastguard Worker qualified = 1;
6018*6777b538SAndroid Build Coastguard Worker } else
6019*6777b538SAndroid Build Coastguard Worker goto found;
6020*6777b538SAndroid Build Coastguard Worker } else {
6021*6777b538SAndroid Build Coastguard Worker /*
6022*6777b538SAndroid Build Coastguard Worker * We should allow applications to define namespaces
6023*6777b538SAndroid Build Coastguard Worker * for their application even if the DTD doesn't
6024*6777b538SAndroid Build Coastguard Worker * carry one, otherwise, basically we would always
6025*6777b538SAndroid Build Coastguard Worker * break.
6026*6777b538SAndroid Build Coastguard Worker */
6027*6777b538SAndroid Build Coastguard Worker goto found;
6028*6777b538SAndroid Build Coastguard Worker }
6029*6777b538SAndroid Build Coastguard Worker }
6030*6777b538SAndroid Build Coastguard Worker attrib = attrib->next;
6031*6777b538SAndroid Build Coastguard Worker }
6032*6777b538SAndroid Build Coastguard Worker }
6033*6777b538SAndroid Build Coastguard Worker if (qualified == -1) {
6034*6777b538SAndroid Build Coastguard Worker if (attr->prefix == NULL) {
6035*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
6036*6777b538SAndroid Build Coastguard Worker "Element %s does not carry attribute %s\n",
6037*6777b538SAndroid Build Coastguard Worker elem->name, attr->name, NULL);
6038*6777b538SAndroid Build Coastguard Worker ret = 0;
6039*6777b538SAndroid Build Coastguard Worker } else {
6040*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE,
6041*6777b538SAndroid Build Coastguard Worker "Element %s does not carry attribute %s:%s\n",
6042*6777b538SAndroid Build Coastguard Worker elem->name, attr->prefix,attr->name);
6043*6777b538SAndroid Build Coastguard Worker ret = 0;
6044*6777b538SAndroid Build Coastguard Worker }
6045*6777b538SAndroid Build Coastguard Worker } else if (qualified == 0) {
6046*6777b538SAndroid Build Coastguard Worker xmlErrValidWarning(ctxt, elem, XML_DTD_NO_PREFIX,
6047*6777b538SAndroid Build Coastguard Worker "Element %s required attribute %s:%s has no prefix\n",
6048*6777b538SAndroid Build Coastguard Worker elem->name, attr->prefix, attr->name);
6049*6777b538SAndroid Build Coastguard Worker } else if (qualified == 1) {
6050*6777b538SAndroid Build Coastguard Worker xmlErrValidWarning(ctxt, elem, XML_DTD_DIFFERENT_PREFIX,
6051*6777b538SAndroid Build Coastguard Worker "Element %s required attribute %s:%s has different prefix\n",
6052*6777b538SAndroid Build Coastguard Worker elem->name, attr->prefix, attr->name);
6053*6777b538SAndroid Build Coastguard Worker }
6054*6777b538SAndroid Build Coastguard Worker } else if (attr->def == XML_ATTRIBUTE_FIXED) {
6055*6777b538SAndroid Build Coastguard Worker /*
6056*6777b538SAndroid Build Coastguard Worker * Special tests checking #FIXED namespace declarations
6057*6777b538SAndroid Build Coastguard Worker * have the right value since this is not done as an
6058*6777b538SAndroid Build Coastguard Worker * attribute checking
6059*6777b538SAndroid Build Coastguard Worker */
6060*6777b538SAndroid Build Coastguard Worker if ((attr->prefix == NULL) &&
6061*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) {
6062*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns;
6063*6777b538SAndroid Build Coastguard Worker
6064*6777b538SAndroid Build Coastguard Worker ns = elem->nsDef;
6065*6777b538SAndroid Build Coastguard Worker while (ns != NULL) {
6066*6777b538SAndroid Build Coastguard Worker if (ns->prefix == NULL) {
6067*6777b538SAndroid Build Coastguard Worker if (!xmlStrEqual(attr->defaultValue, ns->href)) {
6068*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem,
6069*6777b538SAndroid Build Coastguard Worker XML_DTD_ELEM_DEFAULT_NAMESPACE,
6070*6777b538SAndroid Build Coastguard Worker "Element %s namespace name for default namespace does not match the DTD\n",
6071*6777b538SAndroid Build Coastguard Worker elem->name, NULL, NULL);
6072*6777b538SAndroid Build Coastguard Worker ret = 0;
6073*6777b538SAndroid Build Coastguard Worker }
6074*6777b538SAndroid Build Coastguard Worker goto found;
6075*6777b538SAndroid Build Coastguard Worker }
6076*6777b538SAndroid Build Coastguard Worker ns = ns->next;
6077*6777b538SAndroid Build Coastguard Worker }
6078*6777b538SAndroid Build Coastguard Worker } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) {
6079*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns;
6080*6777b538SAndroid Build Coastguard Worker
6081*6777b538SAndroid Build Coastguard Worker ns = elem->nsDef;
6082*6777b538SAndroid Build Coastguard Worker while (ns != NULL) {
6083*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(attr->name, ns->prefix)) {
6084*6777b538SAndroid Build Coastguard Worker if (!xmlStrEqual(attr->defaultValue, ns->href)) {
6085*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE,
6086*6777b538SAndroid Build Coastguard Worker "Element %s namespace name for %s does not match the DTD\n",
6087*6777b538SAndroid Build Coastguard Worker elem->name, ns->prefix, NULL);
6088*6777b538SAndroid Build Coastguard Worker ret = 0;
6089*6777b538SAndroid Build Coastguard Worker }
6090*6777b538SAndroid Build Coastguard Worker goto found;
6091*6777b538SAndroid Build Coastguard Worker }
6092*6777b538SAndroid Build Coastguard Worker ns = ns->next;
6093*6777b538SAndroid Build Coastguard Worker }
6094*6777b538SAndroid Build Coastguard Worker }
6095*6777b538SAndroid Build Coastguard Worker }
6096*6777b538SAndroid Build Coastguard Worker found:
6097*6777b538SAndroid Build Coastguard Worker attr = attr->nexth;
6098*6777b538SAndroid Build Coastguard Worker }
6099*6777b538SAndroid Build Coastguard Worker return(ret);
6100*6777b538SAndroid Build Coastguard Worker }
6101*6777b538SAndroid Build Coastguard Worker
6102*6777b538SAndroid Build Coastguard Worker /**
6103*6777b538SAndroid Build Coastguard Worker * xmlValidateRoot:
6104*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
6105*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
6106*6777b538SAndroid Build Coastguard Worker *
6107*6777b538SAndroid Build Coastguard Worker * Try to validate a the root element
6108*6777b538SAndroid Build Coastguard Worker * basically it does the following check as described by the
6109*6777b538SAndroid Build Coastguard Worker * XML-1.0 recommendation:
6110*6777b538SAndroid Build Coastguard Worker * - [ VC: Root Element Type ]
6111*6777b538SAndroid Build Coastguard Worker * it doesn't try to recurse or apply other check to the element
6112*6777b538SAndroid Build Coastguard Worker *
6113*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6114*6777b538SAndroid Build Coastguard Worker */
6115*6777b538SAndroid Build Coastguard Worker
6116*6777b538SAndroid Build Coastguard Worker int
xmlValidateRoot(xmlValidCtxtPtr ctxt,xmlDocPtr doc)6117*6777b538SAndroid Build Coastguard Worker xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6118*6777b538SAndroid Build Coastguard Worker xmlNodePtr root;
6119*6777b538SAndroid Build Coastguard Worker int ret;
6120*6777b538SAndroid Build Coastguard Worker
6121*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(0);
6122*6777b538SAndroid Build Coastguard Worker
6123*6777b538SAndroid Build Coastguard Worker root = xmlDocGetRootElement(doc);
6124*6777b538SAndroid Build Coastguard Worker if ((root == NULL) || (root->name == NULL)) {
6125*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_NO_ROOT,
6126*6777b538SAndroid Build Coastguard Worker "no root element\n", NULL);
6127*6777b538SAndroid Build Coastguard Worker return(0);
6128*6777b538SAndroid Build Coastguard Worker }
6129*6777b538SAndroid Build Coastguard Worker
6130*6777b538SAndroid Build Coastguard Worker /*
6131*6777b538SAndroid Build Coastguard Worker * When doing post validation against a separate DTD, those may
6132*6777b538SAndroid Build Coastguard Worker * no internal subset has been generated
6133*6777b538SAndroid Build Coastguard Worker */
6134*6777b538SAndroid Build Coastguard Worker if ((doc->intSubset != NULL) &&
6135*6777b538SAndroid Build Coastguard Worker (doc->intSubset->name != NULL)) {
6136*6777b538SAndroid Build Coastguard Worker /*
6137*6777b538SAndroid Build Coastguard Worker * Check first the document root against the NQName
6138*6777b538SAndroid Build Coastguard Worker */
6139*6777b538SAndroid Build Coastguard Worker if (!xmlStrEqual(doc->intSubset->name, root->name)) {
6140*6777b538SAndroid Build Coastguard Worker if ((root->ns != NULL) && (root->ns->prefix != NULL)) {
6141*6777b538SAndroid Build Coastguard Worker xmlChar fn[50];
6142*6777b538SAndroid Build Coastguard Worker xmlChar *fullname;
6143*6777b538SAndroid Build Coastguard Worker
6144*6777b538SAndroid Build Coastguard Worker fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50);
6145*6777b538SAndroid Build Coastguard Worker if (fullname == NULL) {
6146*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6147*6777b538SAndroid Build Coastguard Worker return(0);
6148*6777b538SAndroid Build Coastguard Worker }
6149*6777b538SAndroid Build Coastguard Worker ret = xmlStrEqual(doc->intSubset->name, fullname);
6150*6777b538SAndroid Build Coastguard Worker if ((fullname != fn) && (fullname != root->name))
6151*6777b538SAndroid Build Coastguard Worker xmlFree(fullname);
6152*6777b538SAndroid Build Coastguard Worker if (ret == 1)
6153*6777b538SAndroid Build Coastguard Worker goto name_ok;
6154*6777b538SAndroid Build Coastguard Worker }
6155*6777b538SAndroid Build Coastguard Worker if ((xmlStrEqual(doc->intSubset->name, BAD_CAST "HTML")) &&
6156*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(root->name, BAD_CAST "html")))
6157*6777b538SAndroid Build Coastguard Worker goto name_ok;
6158*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, root, XML_DTD_ROOT_NAME,
6159*6777b538SAndroid Build Coastguard Worker "root and DTD name do not match '%s' and '%s'\n",
6160*6777b538SAndroid Build Coastguard Worker root->name, doc->intSubset->name, NULL);
6161*6777b538SAndroid Build Coastguard Worker return(0);
6162*6777b538SAndroid Build Coastguard Worker }
6163*6777b538SAndroid Build Coastguard Worker }
6164*6777b538SAndroid Build Coastguard Worker name_ok:
6165*6777b538SAndroid Build Coastguard Worker return(1);
6166*6777b538SAndroid Build Coastguard Worker }
6167*6777b538SAndroid Build Coastguard Worker
6168*6777b538SAndroid Build Coastguard Worker
6169*6777b538SAndroid Build Coastguard Worker /**
6170*6777b538SAndroid Build Coastguard Worker * xmlValidateElement:
6171*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
6172*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
6173*6777b538SAndroid Build Coastguard Worker * @root: an element instance
6174*6777b538SAndroid Build Coastguard Worker *
6175*6777b538SAndroid Build Coastguard Worker * Try to validate the subtree under an element
6176*6777b538SAndroid Build Coastguard Worker *
6177*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6178*6777b538SAndroid Build Coastguard Worker */
6179*6777b538SAndroid Build Coastguard Worker
6180*6777b538SAndroid Build Coastguard Worker int
xmlValidateElement(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlNodePtr root)6181*6777b538SAndroid Build Coastguard Worker xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) {
6182*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem;
6183*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attr;
6184*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns;
6185*6777b538SAndroid Build Coastguard Worker const xmlChar *value;
6186*6777b538SAndroid Build Coastguard Worker int ret = 1;
6187*6777b538SAndroid Build Coastguard Worker
6188*6777b538SAndroid Build Coastguard Worker if (root == NULL) return(0);
6189*6777b538SAndroid Build Coastguard Worker
6190*6777b538SAndroid Build Coastguard Worker CHECK_DTD;
6191*6777b538SAndroid Build Coastguard Worker
6192*6777b538SAndroid Build Coastguard Worker elem = root;
6193*6777b538SAndroid Build Coastguard Worker while (1) {
6194*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateOneElement(ctxt, doc, elem);
6195*6777b538SAndroid Build Coastguard Worker
6196*6777b538SAndroid Build Coastguard Worker if (elem->type == XML_ELEMENT_NODE) {
6197*6777b538SAndroid Build Coastguard Worker attr = elem->properties;
6198*6777b538SAndroid Build Coastguard Worker while (attr != NULL) {
6199*6777b538SAndroid Build Coastguard Worker value = xmlNodeListGetString(doc, attr->children, 0);
6200*6777b538SAndroid Build Coastguard Worker if (value == NULL)
6201*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6202*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
6203*6777b538SAndroid Build Coastguard Worker if (value != NULL)
6204*6777b538SAndroid Build Coastguard Worker xmlFree((char *)value);
6205*6777b538SAndroid Build Coastguard Worker attr= attr->next;
6206*6777b538SAndroid Build Coastguard Worker }
6207*6777b538SAndroid Build Coastguard Worker
6208*6777b538SAndroid Build Coastguard Worker ns = elem->nsDef;
6209*6777b538SAndroid Build Coastguard Worker while (ns != NULL) {
6210*6777b538SAndroid Build Coastguard Worker if (elem->ns == NULL)
6211*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
6212*6777b538SAndroid Build Coastguard Worker ns, ns->href);
6213*6777b538SAndroid Build Coastguard Worker else
6214*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateOneNamespace(ctxt, doc, elem,
6215*6777b538SAndroid Build Coastguard Worker elem->ns->prefix, ns,
6216*6777b538SAndroid Build Coastguard Worker ns->href);
6217*6777b538SAndroid Build Coastguard Worker ns = ns->next;
6218*6777b538SAndroid Build Coastguard Worker }
6219*6777b538SAndroid Build Coastguard Worker
6220*6777b538SAndroid Build Coastguard Worker if (elem->children != NULL) {
6221*6777b538SAndroid Build Coastguard Worker elem = elem->children;
6222*6777b538SAndroid Build Coastguard Worker continue;
6223*6777b538SAndroid Build Coastguard Worker }
6224*6777b538SAndroid Build Coastguard Worker }
6225*6777b538SAndroid Build Coastguard Worker
6226*6777b538SAndroid Build Coastguard Worker while (1) {
6227*6777b538SAndroid Build Coastguard Worker if (elem == root)
6228*6777b538SAndroid Build Coastguard Worker goto done;
6229*6777b538SAndroid Build Coastguard Worker if (elem->next != NULL)
6230*6777b538SAndroid Build Coastguard Worker break;
6231*6777b538SAndroid Build Coastguard Worker elem = elem->parent;
6232*6777b538SAndroid Build Coastguard Worker }
6233*6777b538SAndroid Build Coastguard Worker elem = elem->next;
6234*6777b538SAndroid Build Coastguard Worker }
6235*6777b538SAndroid Build Coastguard Worker
6236*6777b538SAndroid Build Coastguard Worker done:
6237*6777b538SAndroid Build Coastguard Worker return(ret);
6238*6777b538SAndroid Build Coastguard Worker }
6239*6777b538SAndroid Build Coastguard Worker
6240*6777b538SAndroid Build Coastguard Worker /**
6241*6777b538SAndroid Build Coastguard Worker * xmlValidateRef:
6242*6777b538SAndroid Build Coastguard Worker * @ref: A reference to be validated
6243*6777b538SAndroid Build Coastguard Worker * @ctxt: Validation context
6244*6777b538SAndroid Build Coastguard Worker * @name: Name of ID we are searching for
6245*6777b538SAndroid Build Coastguard Worker *
6246*6777b538SAndroid Build Coastguard Worker */
6247*6777b538SAndroid Build Coastguard Worker static void
xmlValidateRef(xmlRefPtr ref,xmlValidCtxtPtr ctxt,const xmlChar * name)6248*6777b538SAndroid Build Coastguard Worker xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
6249*6777b538SAndroid Build Coastguard Worker const xmlChar *name) {
6250*6777b538SAndroid Build Coastguard Worker xmlAttrPtr id;
6251*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attr;
6252*6777b538SAndroid Build Coastguard Worker
6253*6777b538SAndroid Build Coastguard Worker if (ref == NULL)
6254*6777b538SAndroid Build Coastguard Worker return;
6255*6777b538SAndroid Build Coastguard Worker if ((ref->attr == NULL) && (ref->name == NULL))
6256*6777b538SAndroid Build Coastguard Worker return;
6257*6777b538SAndroid Build Coastguard Worker attr = ref->attr;
6258*6777b538SAndroid Build Coastguard Worker if (attr == NULL) {
6259*6777b538SAndroid Build Coastguard Worker xmlChar *dup, *str = NULL, *cur, save;
6260*6777b538SAndroid Build Coastguard Worker
6261*6777b538SAndroid Build Coastguard Worker dup = xmlStrdup(name);
6262*6777b538SAndroid Build Coastguard Worker if (dup == NULL) {
6263*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6264*6777b538SAndroid Build Coastguard Worker return;
6265*6777b538SAndroid Build Coastguard Worker }
6266*6777b538SAndroid Build Coastguard Worker cur = dup;
6267*6777b538SAndroid Build Coastguard Worker while (*cur != 0) {
6268*6777b538SAndroid Build Coastguard Worker str = cur;
6269*6777b538SAndroid Build Coastguard Worker while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
6270*6777b538SAndroid Build Coastguard Worker save = *cur;
6271*6777b538SAndroid Build Coastguard Worker *cur = 0;
6272*6777b538SAndroid Build Coastguard Worker id = xmlGetID(ctxt->doc, str);
6273*6777b538SAndroid Build Coastguard Worker if (id == NULL) {
6274*6777b538SAndroid Build Coastguard Worker xmlErrValidNodeNr(ctxt, NULL, XML_DTD_UNKNOWN_ID,
6275*6777b538SAndroid Build Coastguard Worker "attribute %s line %d references an unknown ID \"%s\"\n",
6276*6777b538SAndroid Build Coastguard Worker ref->name, ref->lineno, str);
6277*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
6278*6777b538SAndroid Build Coastguard Worker }
6279*6777b538SAndroid Build Coastguard Worker if (save == 0)
6280*6777b538SAndroid Build Coastguard Worker break;
6281*6777b538SAndroid Build Coastguard Worker *cur = save;
6282*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
6283*6777b538SAndroid Build Coastguard Worker }
6284*6777b538SAndroid Build Coastguard Worker xmlFree(dup);
6285*6777b538SAndroid Build Coastguard Worker } else if (attr->atype == XML_ATTRIBUTE_IDREF) {
6286*6777b538SAndroid Build Coastguard Worker id = xmlGetID(ctxt->doc, name);
6287*6777b538SAndroid Build Coastguard Worker if (id == NULL) {
6288*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
6289*6777b538SAndroid Build Coastguard Worker "IDREF attribute %s references an unknown ID \"%s\"\n",
6290*6777b538SAndroid Build Coastguard Worker attr->name, name, NULL);
6291*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
6292*6777b538SAndroid Build Coastguard Worker }
6293*6777b538SAndroid Build Coastguard Worker } else if (attr->atype == XML_ATTRIBUTE_IDREFS) {
6294*6777b538SAndroid Build Coastguard Worker xmlChar *dup, *str = NULL, *cur, save;
6295*6777b538SAndroid Build Coastguard Worker
6296*6777b538SAndroid Build Coastguard Worker dup = xmlStrdup(name);
6297*6777b538SAndroid Build Coastguard Worker if (dup == NULL) {
6298*6777b538SAndroid Build Coastguard Worker xmlVErrMemory(ctxt);
6299*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
6300*6777b538SAndroid Build Coastguard Worker return;
6301*6777b538SAndroid Build Coastguard Worker }
6302*6777b538SAndroid Build Coastguard Worker cur = dup;
6303*6777b538SAndroid Build Coastguard Worker while (*cur != 0) {
6304*6777b538SAndroid Build Coastguard Worker str = cur;
6305*6777b538SAndroid Build Coastguard Worker while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
6306*6777b538SAndroid Build Coastguard Worker save = *cur;
6307*6777b538SAndroid Build Coastguard Worker *cur = 0;
6308*6777b538SAndroid Build Coastguard Worker id = xmlGetID(ctxt->doc, str);
6309*6777b538SAndroid Build Coastguard Worker if (id == NULL) {
6310*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
6311*6777b538SAndroid Build Coastguard Worker "IDREFS attribute %s references an unknown ID \"%s\"\n",
6312*6777b538SAndroid Build Coastguard Worker attr->name, str, NULL);
6313*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
6314*6777b538SAndroid Build Coastguard Worker }
6315*6777b538SAndroid Build Coastguard Worker if (save == 0)
6316*6777b538SAndroid Build Coastguard Worker break;
6317*6777b538SAndroid Build Coastguard Worker *cur = save;
6318*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
6319*6777b538SAndroid Build Coastguard Worker }
6320*6777b538SAndroid Build Coastguard Worker xmlFree(dup);
6321*6777b538SAndroid Build Coastguard Worker }
6322*6777b538SAndroid Build Coastguard Worker }
6323*6777b538SAndroid Build Coastguard Worker
6324*6777b538SAndroid Build Coastguard Worker /**
6325*6777b538SAndroid Build Coastguard Worker * xmlWalkValidateList:
6326*6777b538SAndroid Build Coastguard Worker * @data: Contents of current link
6327*6777b538SAndroid Build Coastguard Worker * @user: Value supplied by the user
6328*6777b538SAndroid Build Coastguard Worker *
6329*6777b538SAndroid Build Coastguard Worker * Returns 0 to abort the walk or 1 to continue
6330*6777b538SAndroid Build Coastguard Worker */
6331*6777b538SAndroid Build Coastguard Worker static int
xmlWalkValidateList(const void * data,void * user)6332*6777b538SAndroid Build Coastguard Worker xmlWalkValidateList(const void *data, void *user)
6333*6777b538SAndroid Build Coastguard Worker {
6334*6777b538SAndroid Build Coastguard Worker xmlValidateMemoPtr memo = (xmlValidateMemoPtr)user;
6335*6777b538SAndroid Build Coastguard Worker xmlValidateRef((xmlRefPtr)data, memo->ctxt, memo->name);
6336*6777b538SAndroid Build Coastguard Worker return 1;
6337*6777b538SAndroid Build Coastguard Worker }
6338*6777b538SAndroid Build Coastguard Worker
6339*6777b538SAndroid Build Coastguard Worker /**
6340*6777b538SAndroid Build Coastguard Worker * xmlValidateCheckRefCallback:
6341*6777b538SAndroid Build Coastguard Worker * @ref_list: List of references
6342*6777b538SAndroid Build Coastguard Worker * @ctxt: Validation context
6343*6777b538SAndroid Build Coastguard Worker * @name: Name of ID we are searching for
6344*6777b538SAndroid Build Coastguard Worker *
6345*6777b538SAndroid Build Coastguard Worker */
6346*6777b538SAndroid Build Coastguard Worker static void
xmlValidateCheckRefCallback(void * payload,void * data,const xmlChar * name)6347*6777b538SAndroid Build Coastguard Worker xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) {
6348*6777b538SAndroid Build Coastguard Worker xmlListPtr ref_list = (xmlListPtr) payload;
6349*6777b538SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
6350*6777b538SAndroid Build Coastguard Worker xmlValidateMemo memo;
6351*6777b538SAndroid Build Coastguard Worker
6352*6777b538SAndroid Build Coastguard Worker if (ref_list == NULL)
6353*6777b538SAndroid Build Coastguard Worker return;
6354*6777b538SAndroid Build Coastguard Worker memo.ctxt = ctxt;
6355*6777b538SAndroid Build Coastguard Worker memo.name = name;
6356*6777b538SAndroid Build Coastguard Worker
6357*6777b538SAndroid Build Coastguard Worker xmlListWalk(ref_list, xmlWalkValidateList, &memo);
6358*6777b538SAndroid Build Coastguard Worker
6359*6777b538SAndroid Build Coastguard Worker }
6360*6777b538SAndroid Build Coastguard Worker
6361*6777b538SAndroid Build Coastguard Worker /**
6362*6777b538SAndroid Build Coastguard Worker * xmlValidateDocumentFinal:
6363*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
6364*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
6365*6777b538SAndroid Build Coastguard Worker *
6366*6777b538SAndroid Build Coastguard Worker * Does the final step for the document validation once all the
6367*6777b538SAndroid Build Coastguard Worker * incremental validation steps have been completed
6368*6777b538SAndroid Build Coastguard Worker *
6369*6777b538SAndroid Build Coastguard Worker * basically it does the following checks described by the XML Rec
6370*6777b538SAndroid Build Coastguard Worker *
6371*6777b538SAndroid Build Coastguard Worker * Check all the IDREF/IDREFS attributes definition for validity
6372*6777b538SAndroid Build Coastguard Worker *
6373*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6374*6777b538SAndroid Build Coastguard Worker */
6375*6777b538SAndroid Build Coastguard Worker
6376*6777b538SAndroid Build Coastguard Worker int
xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt,xmlDocPtr doc)6377*6777b538SAndroid Build Coastguard Worker xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6378*6777b538SAndroid Build Coastguard Worker xmlRefTablePtr table;
6379*6777b538SAndroid Build Coastguard Worker xmlParserCtxtPtr pctxt = NULL;
6380*6777b538SAndroid Build Coastguard Worker xmlParserInputPtr oldInput = NULL;
6381*6777b538SAndroid Build Coastguard Worker
6382*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
6383*6777b538SAndroid Build Coastguard Worker return(0);
6384*6777b538SAndroid Build Coastguard Worker if (doc == NULL) {
6385*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_NO_DOC,
6386*6777b538SAndroid Build Coastguard Worker "xmlValidateDocumentFinal: doc == NULL\n", NULL);
6387*6777b538SAndroid Build Coastguard Worker return(0);
6388*6777b538SAndroid Build Coastguard Worker }
6389*6777b538SAndroid Build Coastguard Worker
6390*6777b538SAndroid Build Coastguard Worker /*
6391*6777b538SAndroid Build Coastguard Worker * Check all the NOTATION/NOTATIONS attributes
6392*6777b538SAndroid Build Coastguard Worker */
6393*6777b538SAndroid Build Coastguard Worker /*
6394*6777b538SAndroid Build Coastguard Worker * Check all the ENTITY/ENTITIES attributes definition for validity
6395*6777b538SAndroid Build Coastguard Worker */
6396*6777b538SAndroid Build Coastguard Worker /*
6397*6777b538SAndroid Build Coastguard Worker * Check all the IDREF/IDREFS attributes definition for validity
6398*6777b538SAndroid Build Coastguard Worker */
6399*6777b538SAndroid Build Coastguard Worker
6400*6777b538SAndroid Build Coastguard Worker /*
6401*6777b538SAndroid Build Coastguard Worker * Don't print line numbers.
6402*6777b538SAndroid Build Coastguard Worker */
6403*6777b538SAndroid Build Coastguard Worker if (ctxt->flags & XML_VCTXT_USE_PCTXT) {
6404*6777b538SAndroid Build Coastguard Worker pctxt = ctxt->userData;
6405*6777b538SAndroid Build Coastguard Worker oldInput = pctxt->input;
6406*6777b538SAndroid Build Coastguard Worker pctxt->input = NULL;
6407*6777b538SAndroid Build Coastguard Worker }
6408*6777b538SAndroid Build Coastguard Worker
6409*6777b538SAndroid Build Coastguard Worker table = (xmlRefTablePtr) doc->refs;
6410*6777b538SAndroid Build Coastguard Worker ctxt->doc = doc;
6411*6777b538SAndroid Build Coastguard Worker ctxt->valid = 1;
6412*6777b538SAndroid Build Coastguard Worker xmlHashScan(table, xmlValidateCheckRefCallback, ctxt);
6413*6777b538SAndroid Build Coastguard Worker
6414*6777b538SAndroid Build Coastguard Worker if (ctxt->flags & XML_VCTXT_USE_PCTXT)
6415*6777b538SAndroid Build Coastguard Worker pctxt->input = oldInput;
6416*6777b538SAndroid Build Coastguard Worker
6417*6777b538SAndroid Build Coastguard Worker return(ctxt->valid);
6418*6777b538SAndroid Build Coastguard Worker }
6419*6777b538SAndroid Build Coastguard Worker
6420*6777b538SAndroid Build Coastguard Worker /**
6421*6777b538SAndroid Build Coastguard Worker * xmlValidateDtd:
6422*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
6423*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
6424*6777b538SAndroid Build Coastguard Worker * @dtd: a dtd instance
6425*6777b538SAndroid Build Coastguard Worker *
6426*6777b538SAndroid Build Coastguard Worker * Try to validate the document against the dtd instance
6427*6777b538SAndroid Build Coastguard Worker *
6428*6777b538SAndroid Build Coastguard Worker * Basically it does check all the definitions in the DtD.
6429*6777b538SAndroid Build Coastguard Worker * Note the the internal subset (if present) is de-coupled
6430*6777b538SAndroid Build Coastguard Worker * (i.e. not used), which could give problems if ID or IDREF
6431*6777b538SAndroid Build Coastguard Worker * is present.
6432*6777b538SAndroid Build Coastguard Worker *
6433*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6434*6777b538SAndroid Build Coastguard Worker */
6435*6777b538SAndroid Build Coastguard Worker
6436*6777b538SAndroid Build Coastguard Worker int
xmlValidateDtd(xmlValidCtxtPtr ctxt,xmlDocPtr doc,xmlDtdPtr dtd)6437*6777b538SAndroid Build Coastguard Worker xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
6438*6777b538SAndroid Build Coastguard Worker int ret;
6439*6777b538SAndroid Build Coastguard Worker xmlDtdPtr oldExt, oldInt;
6440*6777b538SAndroid Build Coastguard Worker xmlNodePtr root;
6441*6777b538SAndroid Build Coastguard Worker
6442*6777b538SAndroid Build Coastguard Worker if (dtd == NULL) return(0);
6443*6777b538SAndroid Build Coastguard Worker if (doc == NULL) return(0);
6444*6777b538SAndroid Build Coastguard Worker oldExt = doc->extSubset;
6445*6777b538SAndroid Build Coastguard Worker oldInt = doc->intSubset;
6446*6777b538SAndroid Build Coastguard Worker doc->extSubset = dtd;
6447*6777b538SAndroid Build Coastguard Worker doc->intSubset = NULL;
6448*6777b538SAndroid Build Coastguard Worker ret = xmlValidateRoot(ctxt, doc);
6449*6777b538SAndroid Build Coastguard Worker if (ret == 0) {
6450*6777b538SAndroid Build Coastguard Worker doc->extSubset = oldExt;
6451*6777b538SAndroid Build Coastguard Worker doc->intSubset = oldInt;
6452*6777b538SAndroid Build Coastguard Worker return(ret);
6453*6777b538SAndroid Build Coastguard Worker }
6454*6777b538SAndroid Build Coastguard Worker if (doc->ids != NULL) {
6455*6777b538SAndroid Build Coastguard Worker xmlFreeIDTable(doc->ids);
6456*6777b538SAndroid Build Coastguard Worker doc->ids = NULL;
6457*6777b538SAndroid Build Coastguard Worker }
6458*6777b538SAndroid Build Coastguard Worker if (doc->refs != NULL) {
6459*6777b538SAndroid Build Coastguard Worker xmlFreeRefTable(doc->refs);
6460*6777b538SAndroid Build Coastguard Worker doc->refs = NULL;
6461*6777b538SAndroid Build Coastguard Worker }
6462*6777b538SAndroid Build Coastguard Worker root = xmlDocGetRootElement(doc);
6463*6777b538SAndroid Build Coastguard Worker ret = xmlValidateElement(ctxt, doc, root);
6464*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateDocumentFinal(ctxt, doc);
6465*6777b538SAndroid Build Coastguard Worker doc->extSubset = oldExt;
6466*6777b538SAndroid Build Coastguard Worker doc->intSubset = oldInt;
6467*6777b538SAndroid Build Coastguard Worker return(ret);
6468*6777b538SAndroid Build Coastguard Worker }
6469*6777b538SAndroid Build Coastguard Worker
6470*6777b538SAndroid Build Coastguard Worker static void
xmlValidateNotationCallback(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)6471*6777b538SAndroid Build Coastguard Worker xmlValidateNotationCallback(void *payload, void *data,
6472*6777b538SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
6473*6777b538SAndroid Build Coastguard Worker xmlEntityPtr cur = (xmlEntityPtr) payload;
6474*6777b538SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
6475*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
6476*6777b538SAndroid Build Coastguard Worker return;
6477*6777b538SAndroid Build Coastguard Worker if (cur->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
6478*6777b538SAndroid Build Coastguard Worker xmlChar *notation = cur->content;
6479*6777b538SAndroid Build Coastguard Worker
6480*6777b538SAndroid Build Coastguard Worker if (notation != NULL) {
6481*6777b538SAndroid Build Coastguard Worker int ret;
6482*6777b538SAndroid Build Coastguard Worker
6483*6777b538SAndroid Build Coastguard Worker ret = xmlValidateNotationUse(ctxt, cur->doc, notation);
6484*6777b538SAndroid Build Coastguard Worker if (ret != 1) {
6485*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
6486*6777b538SAndroid Build Coastguard Worker }
6487*6777b538SAndroid Build Coastguard Worker }
6488*6777b538SAndroid Build Coastguard Worker }
6489*6777b538SAndroid Build Coastguard Worker }
6490*6777b538SAndroid Build Coastguard Worker
6491*6777b538SAndroid Build Coastguard Worker static void
xmlValidateAttributeCallback(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)6492*6777b538SAndroid Build Coastguard Worker xmlValidateAttributeCallback(void *payload, void *data,
6493*6777b538SAndroid Build Coastguard Worker const xmlChar *name ATTRIBUTE_UNUSED) {
6494*6777b538SAndroid Build Coastguard Worker xmlAttributePtr cur = (xmlAttributePtr) payload;
6495*6777b538SAndroid Build Coastguard Worker xmlValidCtxtPtr ctxt = (xmlValidCtxtPtr) data;
6496*6777b538SAndroid Build Coastguard Worker int ret;
6497*6777b538SAndroid Build Coastguard Worker xmlDocPtr doc;
6498*6777b538SAndroid Build Coastguard Worker xmlElementPtr elem = NULL;
6499*6777b538SAndroid Build Coastguard Worker
6500*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
6501*6777b538SAndroid Build Coastguard Worker return;
6502*6777b538SAndroid Build Coastguard Worker switch (cur->atype) {
6503*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_CDATA:
6504*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ID:
6505*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREF :
6506*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_IDREFS:
6507*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKEN:
6508*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NMTOKENS:
6509*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENUMERATION:
6510*6777b538SAndroid Build Coastguard Worker break;
6511*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITY:
6512*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_ENTITIES:
6513*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NOTATION:
6514*6777b538SAndroid Build Coastguard Worker if (cur->defaultValue != NULL) {
6515*6777b538SAndroid Build Coastguard Worker
6516*6777b538SAndroid Build Coastguard Worker ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, cur->name,
6517*6777b538SAndroid Build Coastguard Worker cur->atype, cur->defaultValue);
6518*6777b538SAndroid Build Coastguard Worker if ((ret == 0) && (ctxt->valid == 1))
6519*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
6520*6777b538SAndroid Build Coastguard Worker }
6521*6777b538SAndroid Build Coastguard Worker if (cur->tree != NULL) {
6522*6777b538SAndroid Build Coastguard Worker xmlEnumerationPtr tree = cur->tree;
6523*6777b538SAndroid Build Coastguard Worker while (tree != NULL) {
6524*6777b538SAndroid Build Coastguard Worker ret = xmlValidateAttributeValue2(ctxt, ctxt->doc,
6525*6777b538SAndroid Build Coastguard Worker cur->name, cur->atype, tree->name);
6526*6777b538SAndroid Build Coastguard Worker if ((ret == 0) && (ctxt->valid == 1))
6527*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
6528*6777b538SAndroid Build Coastguard Worker tree = tree->next;
6529*6777b538SAndroid Build Coastguard Worker }
6530*6777b538SAndroid Build Coastguard Worker }
6531*6777b538SAndroid Build Coastguard Worker }
6532*6777b538SAndroid Build Coastguard Worker if (cur->atype == XML_ATTRIBUTE_NOTATION) {
6533*6777b538SAndroid Build Coastguard Worker doc = cur->doc;
6534*6777b538SAndroid Build Coastguard Worker if (cur->elem == NULL) {
6535*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
6536*6777b538SAndroid Build Coastguard Worker "xmlValidateAttributeCallback(%s): internal error\n",
6537*6777b538SAndroid Build Coastguard Worker (const char *) cur->name);
6538*6777b538SAndroid Build Coastguard Worker return;
6539*6777b538SAndroid Build Coastguard Worker }
6540*6777b538SAndroid Build Coastguard Worker
6541*6777b538SAndroid Build Coastguard Worker if (doc != NULL)
6542*6777b538SAndroid Build Coastguard Worker elem = xmlCtxtGetDtdElementDesc(ctxt, doc->intSubset, cur->elem);
6543*6777b538SAndroid Build Coastguard Worker if ((elem == NULL) && (doc != NULL))
6544*6777b538SAndroid Build Coastguard Worker elem = xmlCtxtGetDtdElementDesc(ctxt, doc->extSubset, cur->elem);
6545*6777b538SAndroid Build Coastguard Worker if ((elem == NULL) && (cur->parent != NULL) &&
6546*6777b538SAndroid Build Coastguard Worker (cur->parent->type == XML_DTD_NODE))
6547*6777b538SAndroid Build Coastguard Worker elem = xmlCtxtGetDtdElementDesc(ctxt, (xmlDtdPtr) cur->parent,
6548*6777b538SAndroid Build Coastguard Worker cur->elem);
6549*6777b538SAndroid Build Coastguard Worker if (elem == NULL) {
6550*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, NULL, XML_DTD_UNKNOWN_ELEM,
6551*6777b538SAndroid Build Coastguard Worker "attribute %s: could not find decl for element %s\n",
6552*6777b538SAndroid Build Coastguard Worker cur->name, cur->elem, NULL);
6553*6777b538SAndroid Build Coastguard Worker return;
6554*6777b538SAndroid Build Coastguard Worker }
6555*6777b538SAndroid Build Coastguard Worker if (elem->etype == XML_ELEMENT_TYPE_EMPTY) {
6556*6777b538SAndroid Build Coastguard Worker xmlErrValidNode(ctxt, NULL, XML_DTD_EMPTY_NOTATION,
6557*6777b538SAndroid Build Coastguard Worker "NOTATION attribute %s declared for EMPTY element %s\n",
6558*6777b538SAndroid Build Coastguard Worker cur->name, cur->elem, NULL);
6559*6777b538SAndroid Build Coastguard Worker ctxt->valid = 0;
6560*6777b538SAndroid Build Coastguard Worker }
6561*6777b538SAndroid Build Coastguard Worker }
6562*6777b538SAndroid Build Coastguard Worker }
6563*6777b538SAndroid Build Coastguard Worker
6564*6777b538SAndroid Build Coastguard Worker /**
6565*6777b538SAndroid Build Coastguard Worker * xmlValidateDtdFinal:
6566*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
6567*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
6568*6777b538SAndroid Build Coastguard Worker *
6569*6777b538SAndroid Build Coastguard Worker * Does the final step for the dtds validation once all the
6570*6777b538SAndroid Build Coastguard Worker * subsets have been parsed
6571*6777b538SAndroid Build Coastguard Worker *
6572*6777b538SAndroid Build Coastguard Worker * basically it does the following checks described by the XML Rec
6573*6777b538SAndroid Build Coastguard Worker * - check that ENTITY and ENTITIES type attributes default or
6574*6777b538SAndroid Build Coastguard Worker * possible values matches one of the defined entities.
6575*6777b538SAndroid Build Coastguard Worker * - check that NOTATION type attributes default or
6576*6777b538SAndroid Build Coastguard Worker * possible values matches one of the defined notations.
6577*6777b538SAndroid Build Coastguard Worker *
6578*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 if invalid and -1 if not well-formed
6579*6777b538SAndroid Build Coastguard Worker */
6580*6777b538SAndroid Build Coastguard Worker
6581*6777b538SAndroid Build Coastguard Worker int
xmlValidateDtdFinal(xmlValidCtxtPtr ctxt,xmlDocPtr doc)6582*6777b538SAndroid Build Coastguard Worker xmlValidateDtdFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6583*6777b538SAndroid Build Coastguard Worker xmlDtdPtr dtd;
6584*6777b538SAndroid Build Coastguard Worker xmlAttributeTablePtr table;
6585*6777b538SAndroid Build Coastguard Worker xmlEntitiesTablePtr entities;
6586*6777b538SAndroid Build Coastguard Worker
6587*6777b538SAndroid Build Coastguard Worker if ((doc == NULL) || (ctxt == NULL)) return(0);
6588*6777b538SAndroid Build Coastguard Worker if ((doc->intSubset == NULL) && (doc->extSubset == NULL))
6589*6777b538SAndroid Build Coastguard Worker return(0);
6590*6777b538SAndroid Build Coastguard Worker ctxt->doc = doc;
6591*6777b538SAndroid Build Coastguard Worker ctxt->valid = 1;
6592*6777b538SAndroid Build Coastguard Worker dtd = doc->intSubset;
6593*6777b538SAndroid Build Coastguard Worker if ((dtd != NULL) && (dtd->attributes != NULL)) {
6594*6777b538SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
6595*6777b538SAndroid Build Coastguard Worker xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
6596*6777b538SAndroid Build Coastguard Worker }
6597*6777b538SAndroid Build Coastguard Worker if ((dtd != NULL) && (dtd->entities != NULL)) {
6598*6777b538SAndroid Build Coastguard Worker entities = (xmlEntitiesTablePtr) dtd->entities;
6599*6777b538SAndroid Build Coastguard Worker xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
6600*6777b538SAndroid Build Coastguard Worker }
6601*6777b538SAndroid Build Coastguard Worker dtd = doc->extSubset;
6602*6777b538SAndroid Build Coastguard Worker if ((dtd != NULL) && (dtd->attributes != NULL)) {
6603*6777b538SAndroid Build Coastguard Worker table = (xmlAttributeTablePtr) dtd->attributes;
6604*6777b538SAndroid Build Coastguard Worker xmlHashScan(table, xmlValidateAttributeCallback, ctxt);
6605*6777b538SAndroid Build Coastguard Worker }
6606*6777b538SAndroid Build Coastguard Worker if ((dtd != NULL) && (dtd->entities != NULL)) {
6607*6777b538SAndroid Build Coastguard Worker entities = (xmlEntitiesTablePtr) dtd->entities;
6608*6777b538SAndroid Build Coastguard Worker xmlHashScan(entities, xmlValidateNotationCallback, ctxt);
6609*6777b538SAndroid Build Coastguard Worker }
6610*6777b538SAndroid Build Coastguard Worker return(ctxt->valid);
6611*6777b538SAndroid Build Coastguard Worker }
6612*6777b538SAndroid Build Coastguard Worker
6613*6777b538SAndroid Build Coastguard Worker /**
6614*6777b538SAndroid Build Coastguard Worker * xmlValidateDocument:
6615*6777b538SAndroid Build Coastguard Worker * @ctxt: the validation context
6616*6777b538SAndroid Build Coastguard Worker * @doc: a document instance
6617*6777b538SAndroid Build Coastguard Worker *
6618*6777b538SAndroid Build Coastguard Worker * Try to validate the document instance
6619*6777b538SAndroid Build Coastguard Worker *
6620*6777b538SAndroid Build Coastguard Worker * basically it does the all the checks described by the XML Rec
6621*6777b538SAndroid Build Coastguard Worker * i.e. validates the internal and external subset (if present)
6622*6777b538SAndroid Build Coastguard Worker * and validate the document tree.
6623*6777b538SAndroid Build Coastguard Worker *
6624*6777b538SAndroid Build Coastguard Worker * returns 1 if valid or 0 otherwise
6625*6777b538SAndroid Build Coastguard Worker */
6626*6777b538SAndroid Build Coastguard Worker
6627*6777b538SAndroid Build Coastguard Worker int
xmlValidateDocument(xmlValidCtxtPtr ctxt,xmlDocPtr doc)6628*6777b538SAndroid Build Coastguard Worker xmlValidateDocument(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
6629*6777b538SAndroid Build Coastguard Worker int ret;
6630*6777b538SAndroid Build Coastguard Worker xmlNodePtr root;
6631*6777b538SAndroid Build Coastguard Worker
6632*6777b538SAndroid Build Coastguard Worker if (doc == NULL)
6633*6777b538SAndroid Build Coastguard Worker return(0);
6634*6777b538SAndroid Build Coastguard Worker if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
6635*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_NO_DTD,
6636*6777b538SAndroid Build Coastguard Worker "no DTD found!\n", NULL);
6637*6777b538SAndroid Build Coastguard Worker return(0);
6638*6777b538SAndroid Build Coastguard Worker }
6639*6777b538SAndroid Build Coastguard Worker if ((doc->intSubset != NULL) && ((doc->intSubset->SystemID != NULL) ||
6640*6777b538SAndroid Build Coastguard Worker (doc->intSubset->ExternalID != NULL)) && (doc->extSubset == NULL)) {
6641*6777b538SAndroid Build Coastguard Worker xmlChar *sysID;
6642*6777b538SAndroid Build Coastguard Worker if (doc->intSubset->SystemID != NULL) {
6643*6777b538SAndroid Build Coastguard Worker sysID = xmlBuildURI(doc->intSubset->SystemID,
6644*6777b538SAndroid Build Coastguard Worker doc->URL);
6645*6777b538SAndroid Build Coastguard Worker if (sysID == NULL) {
6646*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6647*6777b538SAndroid Build Coastguard Worker "Could not build URI for external subset \"%s\"\n",
6648*6777b538SAndroid Build Coastguard Worker (const char *) doc->intSubset->SystemID);
6649*6777b538SAndroid Build Coastguard Worker return 0;
6650*6777b538SAndroid Build Coastguard Worker }
6651*6777b538SAndroid Build Coastguard Worker } else
6652*6777b538SAndroid Build Coastguard Worker sysID = NULL;
6653*6777b538SAndroid Build Coastguard Worker doc->extSubset = xmlParseDTD(doc->intSubset->ExternalID,
6654*6777b538SAndroid Build Coastguard Worker (const xmlChar *)sysID);
6655*6777b538SAndroid Build Coastguard Worker if (sysID != NULL)
6656*6777b538SAndroid Build Coastguard Worker xmlFree(sysID);
6657*6777b538SAndroid Build Coastguard Worker if (doc->extSubset == NULL) {
6658*6777b538SAndroid Build Coastguard Worker if (doc->intSubset->SystemID != NULL) {
6659*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6660*6777b538SAndroid Build Coastguard Worker "Could not load the external subset \"%s\"\n",
6661*6777b538SAndroid Build Coastguard Worker (const char *) doc->intSubset->SystemID);
6662*6777b538SAndroid Build Coastguard Worker } else {
6663*6777b538SAndroid Build Coastguard Worker xmlErrValid(ctxt, XML_DTD_LOAD_ERROR,
6664*6777b538SAndroid Build Coastguard Worker "Could not load the external subset \"%s\"\n",
6665*6777b538SAndroid Build Coastguard Worker (const char *) doc->intSubset->ExternalID);
6666*6777b538SAndroid Build Coastguard Worker }
6667*6777b538SAndroid Build Coastguard Worker return(0);
6668*6777b538SAndroid Build Coastguard Worker }
6669*6777b538SAndroid Build Coastguard Worker }
6670*6777b538SAndroid Build Coastguard Worker
6671*6777b538SAndroid Build Coastguard Worker if (doc->ids != NULL) {
6672*6777b538SAndroid Build Coastguard Worker xmlFreeIDTable(doc->ids);
6673*6777b538SAndroid Build Coastguard Worker doc->ids = NULL;
6674*6777b538SAndroid Build Coastguard Worker }
6675*6777b538SAndroid Build Coastguard Worker if (doc->refs != NULL) {
6676*6777b538SAndroid Build Coastguard Worker xmlFreeRefTable(doc->refs);
6677*6777b538SAndroid Build Coastguard Worker doc->refs = NULL;
6678*6777b538SAndroid Build Coastguard Worker }
6679*6777b538SAndroid Build Coastguard Worker ret = xmlValidateDtdFinal(ctxt, doc);
6680*6777b538SAndroid Build Coastguard Worker if (!xmlValidateRoot(ctxt, doc)) return(0);
6681*6777b538SAndroid Build Coastguard Worker
6682*6777b538SAndroid Build Coastguard Worker root = xmlDocGetRootElement(doc);
6683*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateElement(ctxt, doc, root);
6684*6777b538SAndroid Build Coastguard Worker ret &= xmlValidateDocumentFinal(ctxt, doc);
6685*6777b538SAndroid Build Coastguard Worker return(ret);
6686*6777b538SAndroid Build Coastguard Worker }
6687*6777b538SAndroid Build Coastguard Worker
6688*6777b538SAndroid Build Coastguard Worker /************************************************************************
6689*6777b538SAndroid Build Coastguard Worker * *
6690*6777b538SAndroid Build Coastguard Worker * Routines for dynamic validation editing *
6691*6777b538SAndroid Build Coastguard Worker * *
6692*6777b538SAndroid Build Coastguard Worker ************************************************************************/
6693*6777b538SAndroid Build Coastguard Worker
6694*6777b538SAndroid Build Coastguard Worker /**
6695*6777b538SAndroid Build Coastguard Worker * xmlValidGetPotentialChildren:
6696*6777b538SAndroid Build Coastguard Worker * @ctree: an element content tree
6697*6777b538SAndroid Build Coastguard Worker * @names: an array to store the list of child names
6698*6777b538SAndroid Build Coastguard Worker * @len: a pointer to the number of element in the list
6699*6777b538SAndroid Build Coastguard Worker * @max: the size of the array
6700*6777b538SAndroid Build Coastguard Worker *
6701*6777b538SAndroid Build Coastguard Worker * Build/extend a list of potential children allowed by the content tree
6702*6777b538SAndroid Build Coastguard Worker *
6703*6777b538SAndroid Build Coastguard Worker * returns the number of element in the list, or -1 in case of error.
6704*6777b538SAndroid Build Coastguard Worker */
6705*6777b538SAndroid Build Coastguard Worker
6706*6777b538SAndroid Build Coastguard Worker int
xmlValidGetPotentialChildren(xmlElementContent * ctree,const xmlChar ** names,int * len,int max)6707*6777b538SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(xmlElementContent *ctree,
6708*6777b538SAndroid Build Coastguard Worker const xmlChar **names,
6709*6777b538SAndroid Build Coastguard Worker int *len, int max) {
6710*6777b538SAndroid Build Coastguard Worker int i;
6711*6777b538SAndroid Build Coastguard Worker
6712*6777b538SAndroid Build Coastguard Worker if ((ctree == NULL) || (names == NULL) || (len == NULL))
6713*6777b538SAndroid Build Coastguard Worker return(-1);
6714*6777b538SAndroid Build Coastguard Worker if (*len >= max) return(*len);
6715*6777b538SAndroid Build Coastguard Worker
6716*6777b538SAndroid Build Coastguard Worker switch (ctree->type) {
6717*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_PCDATA:
6718*6777b538SAndroid Build Coastguard Worker for (i = 0; i < *len;i++)
6719*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(BAD_CAST "#PCDATA", names[i])) return(*len);
6720*6777b538SAndroid Build Coastguard Worker names[(*len)++] = BAD_CAST "#PCDATA";
6721*6777b538SAndroid Build Coastguard Worker break;
6722*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_ELEMENT:
6723*6777b538SAndroid Build Coastguard Worker for (i = 0; i < *len;i++)
6724*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(ctree->name, names[i])) return(*len);
6725*6777b538SAndroid Build Coastguard Worker names[(*len)++] = ctree->name;
6726*6777b538SAndroid Build Coastguard Worker break;
6727*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_SEQ:
6728*6777b538SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(ctree->c1, names, len, max);
6729*6777b538SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(ctree->c2, names, len, max);
6730*6777b538SAndroid Build Coastguard Worker break;
6731*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_CONTENT_OR:
6732*6777b538SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(ctree->c1, names, len, max);
6733*6777b538SAndroid Build Coastguard Worker xmlValidGetPotentialChildren(ctree->c2, names, len, max);
6734*6777b538SAndroid Build Coastguard Worker break;
6735*6777b538SAndroid Build Coastguard Worker }
6736*6777b538SAndroid Build Coastguard Worker
6737*6777b538SAndroid Build Coastguard Worker return(*len);
6738*6777b538SAndroid Build Coastguard Worker }
6739*6777b538SAndroid Build Coastguard Worker
6740*6777b538SAndroid Build Coastguard Worker /*
6741*6777b538SAndroid Build Coastguard Worker * Dummy function to suppress messages while we try out valid elements
6742*6777b538SAndroid Build Coastguard Worker */
xmlNoValidityErr(void * ctx ATTRIBUTE_UNUSED,const char * msg ATTRIBUTE_UNUSED,...)6743*6777b538SAndroid Build Coastguard Worker static void xmlNoValidityErr(void *ctx ATTRIBUTE_UNUSED,
6744*6777b538SAndroid Build Coastguard Worker const char *msg ATTRIBUTE_UNUSED, ...) {
6745*6777b538SAndroid Build Coastguard Worker return;
6746*6777b538SAndroid Build Coastguard Worker }
6747*6777b538SAndroid Build Coastguard Worker
6748*6777b538SAndroid Build Coastguard Worker /**
6749*6777b538SAndroid Build Coastguard Worker * xmlValidGetValidElements:
6750*6777b538SAndroid Build Coastguard Worker * @prev: an element to insert after
6751*6777b538SAndroid Build Coastguard Worker * @next: an element to insert next
6752*6777b538SAndroid Build Coastguard Worker * @names: an array to store the list of child names
6753*6777b538SAndroid Build Coastguard Worker * @max: the size of the array
6754*6777b538SAndroid Build Coastguard Worker *
6755*6777b538SAndroid Build Coastguard Worker * This function returns the list of authorized children to insert
6756*6777b538SAndroid Build Coastguard Worker * within an existing tree while respecting the validity constraints
6757*6777b538SAndroid Build Coastguard Worker * forced by the Dtd. The insertion point is defined using @prev and
6758*6777b538SAndroid Build Coastguard Worker * @next in the following ways:
6759*6777b538SAndroid Build Coastguard Worker * to insert before 'node': xmlValidGetValidElements(node->prev, node, ...
6760*6777b538SAndroid Build Coastguard Worker * to insert next 'node': xmlValidGetValidElements(node, node->next, ...
6761*6777b538SAndroid Build Coastguard Worker * to replace 'node': xmlValidGetValidElements(node->prev, node->next, ...
6762*6777b538SAndroid Build Coastguard Worker * to prepend a child to 'node': xmlValidGetValidElements(NULL, node->childs,
6763*6777b538SAndroid Build Coastguard Worker * to append a child to 'node': xmlValidGetValidElements(node->last, NULL, ...
6764*6777b538SAndroid Build Coastguard Worker *
6765*6777b538SAndroid Build Coastguard Worker * pointers to the element names are inserted at the beginning of the array
6766*6777b538SAndroid Build Coastguard Worker * and do not need to be freed.
6767*6777b538SAndroid Build Coastguard Worker *
6768*6777b538SAndroid Build Coastguard Worker * returns the number of element in the list, or -1 in case of error. If
6769*6777b538SAndroid Build Coastguard Worker * the function returns the value @max the caller is invited to grow the
6770*6777b538SAndroid Build Coastguard Worker * receiving array and retry.
6771*6777b538SAndroid Build Coastguard Worker */
6772*6777b538SAndroid Build Coastguard Worker
6773*6777b538SAndroid Build Coastguard Worker int
xmlValidGetValidElements(xmlNode * prev,xmlNode * next,const xmlChar ** names,int max)6774*6777b538SAndroid Build Coastguard Worker xmlValidGetValidElements(xmlNode *prev, xmlNode *next, const xmlChar **names,
6775*6777b538SAndroid Build Coastguard Worker int max) {
6776*6777b538SAndroid Build Coastguard Worker xmlValidCtxt vctxt;
6777*6777b538SAndroid Build Coastguard Worker int nb_valid_elements = 0;
6778*6777b538SAndroid Build Coastguard Worker const xmlChar *elements[256]={0};
6779*6777b538SAndroid Build Coastguard Worker int nb_elements = 0, i;
6780*6777b538SAndroid Build Coastguard Worker const xmlChar *name;
6781*6777b538SAndroid Build Coastguard Worker
6782*6777b538SAndroid Build Coastguard Worker xmlNode *ref_node;
6783*6777b538SAndroid Build Coastguard Worker xmlNode *parent;
6784*6777b538SAndroid Build Coastguard Worker xmlNode *test_node;
6785*6777b538SAndroid Build Coastguard Worker
6786*6777b538SAndroid Build Coastguard Worker xmlNode *prev_next;
6787*6777b538SAndroid Build Coastguard Worker xmlNode *next_prev;
6788*6777b538SAndroid Build Coastguard Worker xmlNode *parent_childs;
6789*6777b538SAndroid Build Coastguard Worker xmlNode *parent_last;
6790*6777b538SAndroid Build Coastguard Worker
6791*6777b538SAndroid Build Coastguard Worker xmlElement *element_desc;
6792*6777b538SAndroid Build Coastguard Worker
6793*6777b538SAndroid Build Coastguard Worker if (prev == NULL && next == NULL)
6794*6777b538SAndroid Build Coastguard Worker return(-1);
6795*6777b538SAndroid Build Coastguard Worker
6796*6777b538SAndroid Build Coastguard Worker if (names == NULL) return(-1);
6797*6777b538SAndroid Build Coastguard Worker if (max <= 0) return(-1);
6798*6777b538SAndroid Build Coastguard Worker
6799*6777b538SAndroid Build Coastguard Worker memset(&vctxt, 0, sizeof (xmlValidCtxt));
6800*6777b538SAndroid Build Coastguard Worker vctxt.error = xmlNoValidityErr; /* this suppresses err/warn output */
6801*6777b538SAndroid Build Coastguard Worker
6802*6777b538SAndroid Build Coastguard Worker nb_valid_elements = 0;
6803*6777b538SAndroid Build Coastguard Worker ref_node = prev ? prev : next;
6804*6777b538SAndroid Build Coastguard Worker parent = ref_node->parent;
6805*6777b538SAndroid Build Coastguard Worker
6806*6777b538SAndroid Build Coastguard Worker /*
6807*6777b538SAndroid Build Coastguard Worker * Retrieves the parent element declaration
6808*6777b538SAndroid Build Coastguard Worker */
6809*6777b538SAndroid Build Coastguard Worker element_desc = xmlGetDtdElementDesc(parent->doc->intSubset,
6810*6777b538SAndroid Build Coastguard Worker parent->name);
6811*6777b538SAndroid Build Coastguard Worker if ((element_desc == NULL) && (parent->doc->extSubset != NULL))
6812*6777b538SAndroid Build Coastguard Worker element_desc = xmlGetDtdElementDesc(parent->doc->extSubset,
6813*6777b538SAndroid Build Coastguard Worker parent->name);
6814*6777b538SAndroid Build Coastguard Worker if (element_desc == NULL) return(-1);
6815*6777b538SAndroid Build Coastguard Worker
6816*6777b538SAndroid Build Coastguard Worker /*
6817*6777b538SAndroid Build Coastguard Worker * Do a backup of the current tree structure
6818*6777b538SAndroid Build Coastguard Worker */
6819*6777b538SAndroid Build Coastguard Worker prev_next = prev ? prev->next : NULL;
6820*6777b538SAndroid Build Coastguard Worker next_prev = next ? next->prev : NULL;
6821*6777b538SAndroid Build Coastguard Worker parent_childs = parent->children;
6822*6777b538SAndroid Build Coastguard Worker parent_last = parent->last;
6823*6777b538SAndroid Build Coastguard Worker
6824*6777b538SAndroid Build Coastguard Worker /*
6825*6777b538SAndroid Build Coastguard Worker * Creates a dummy node and insert it into the tree
6826*6777b538SAndroid Build Coastguard Worker */
6827*6777b538SAndroid Build Coastguard Worker test_node = xmlNewDocNode (ref_node->doc, NULL, BAD_CAST "<!dummy?>", NULL);
6828*6777b538SAndroid Build Coastguard Worker if (test_node == NULL)
6829*6777b538SAndroid Build Coastguard Worker return(-1);
6830*6777b538SAndroid Build Coastguard Worker
6831*6777b538SAndroid Build Coastguard Worker test_node->parent = parent;
6832*6777b538SAndroid Build Coastguard Worker test_node->prev = prev;
6833*6777b538SAndroid Build Coastguard Worker test_node->next = next;
6834*6777b538SAndroid Build Coastguard Worker name = test_node->name;
6835*6777b538SAndroid Build Coastguard Worker
6836*6777b538SAndroid Build Coastguard Worker if (prev) prev->next = test_node;
6837*6777b538SAndroid Build Coastguard Worker else parent->children = test_node;
6838*6777b538SAndroid Build Coastguard Worker
6839*6777b538SAndroid Build Coastguard Worker if (next) next->prev = test_node;
6840*6777b538SAndroid Build Coastguard Worker else parent->last = test_node;
6841*6777b538SAndroid Build Coastguard Worker
6842*6777b538SAndroid Build Coastguard Worker /*
6843*6777b538SAndroid Build Coastguard Worker * Insert each potential child node and check if the parent is
6844*6777b538SAndroid Build Coastguard Worker * still valid
6845*6777b538SAndroid Build Coastguard Worker */
6846*6777b538SAndroid Build Coastguard Worker nb_elements = xmlValidGetPotentialChildren(element_desc->content,
6847*6777b538SAndroid Build Coastguard Worker elements, &nb_elements, 256);
6848*6777b538SAndroid Build Coastguard Worker
6849*6777b538SAndroid Build Coastguard Worker for (i = 0;i < nb_elements;i++) {
6850*6777b538SAndroid Build Coastguard Worker test_node->name = elements[i];
6851*6777b538SAndroid Build Coastguard Worker if (xmlValidateOneElement(&vctxt, parent->doc, parent)) {
6852*6777b538SAndroid Build Coastguard Worker int j;
6853*6777b538SAndroid Build Coastguard Worker
6854*6777b538SAndroid Build Coastguard Worker for (j = 0; j < nb_valid_elements;j++)
6855*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(elements[i], names[j])) break;
6856*6777b538SAndroid Build Coastguard Worker names[nb_valid_elements++] = elements[i];
6857*6777b538SAndroid Build Coastguard Worker if (nb_valid_elements >= max) break;
6858*6777b538SAndroid Build Coastguard Worker }
6859*6777b538SAndroid Build Coastguard Worker }
6860*6777b538SAndroid Build Coastguard Worker
6861*6777b538SAndroid Build Coastguard Worker /*
6862*6777b538SAndroid Build Coastguard Worker * Restore the tree structure
6863*6777b538SAndroid Build Coastguard Worker */
6864*6777b538SAndroid Build Coastguard Worker if (prev) prev->next = prev_next;
6865*6777b538SAndroid Build Coastguard Worker if (next) next->prev = next_prev;
6866*6777b538SAndroid Build Coastguard Worker parent->children = parent_childs;
6867*6777b538SAndroid Build Coastguard Worker parent->last = parent_last;
6868*6777b538SAndroid Build Coastguard Worker
6869*6777b538SAndroid Build Coastguard Worker /*
6870*6777b538SAndroid Build Coastguard Worker * Free up the dummy node
6871*6777b538SAndroid Build Coastguard Worker */
6872*6777b538SAndroid Build Coastguard Worker test_node->name = name;
6873*6777b538SAndroid Build Coastguard Worker xmlFreeNode(test_node);
6874*6777b538SAndroid Build Coastguard Worker
6875*6777b538SAndroid Build Coastguard Worker return(nb_valid_elements);
6876*6777b538SAndroid Build Coastguard Worker }
6877*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_VALID_ENABLED */
6878*6777b538SAndroid Build Coastguard Worker
6879