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