xref: /aosp_15_r20/external/cronet/third_party/libxml/src/valid.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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