Newer
Older
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id$
*/
#include <xercesc/xinclude/XIncludeUtils.hpp>
#include <xercesc/xinclude/XIncludeLocation.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/util/XMLUri.hpp>
#include <xercesc/util/XMLMsgLoader.hpp>
#include <xercesc/util/XMLResourceIdentifier.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
Alberto Massari
committed
#include <xercesc/internal/XMLInternalErrorHandler.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/sax/InputSource.hpp>
#include <xercesc/framework/URLInputSource.hpp>
XERCES_CPP_NAMESPACE_BEGIN
XIncludeUtils::XIncludeUtils(XMLErrorReporter *errorReporter){
fErrorReporter = errorReporter;
fIncludeHistoryHead = NULL;
}
XIncludeUtils::~XIncludeUtils(){
freeInclusionHistory();
}
// ---------------------------------------------------------------------------
// Generic function to parse a dom node performing any Xinclude's it ecounters,
// storing its results in parsedDocument, which is expected to be a real
// document. sourceNode is the current location in parsedDocument, and
// all xinclude manipulation is done in place (i.e. source is manipulated).
// ---------------------------------------------------------------------------
bool
XIncludeUtils::parseDOMNodeDoingXInclude(DOMNode *sourceNode, DOMDocument *parsedDocument, XMLEntityHandler* entityResolver){
int included = 0;
if (sourceNode) {
/* create the list of child elements here, since it gets changed during the parse */
RefVectorOf<DOMNode> children(10, false);
for (DOMNode *child = sourceNode->getFirstChild(); child != NULL; child = child->getNextSibling()){
children.addElement(child);
}
if (sourceNode->getNodeType() == DOMNode::ELEMENT_NODE){
if (isXIIncludeDOMNode(sourceNode)){
/* once we do an include on the source element, it is unsafe to do the include
on the children, since they will have been changed by the top level include */
bool success = doDOMNodeXInclude(sourceNode, parsedDocument, entityResolver);
//popFromCurrentInclusionHistoryStack(NULL);
/* return here as we do not want to fall through to the parsing of the children below
- they should have been replaced by the XInclude */
return success;
} else if (isXIFallbackDOMNode(sourceNode)){
/* This must be a fallback element that is not a child of an include element.
This is defined as a fatal error */
XIncludeUtils::reportError(sourceNode, XMLErrs::XIncludeOrphanFallback,
NULL, parsedDocument->getDocumentURI());
return false;
}
}
/* to have got here, we must not have found an xinclude element in the current element, so
need to walk the entire child list parsing for each. An xinclude in a
node does not affect a peer, so we can simply parse each child in turn */
for (unsigned int i = 0; i < children.size(); i++){
parseDOMNodeDoingXInclude(children.elementAt(i), parsedDocument, entityResolver);
}
}
return (included)?true:false;
}
// ---------------------------------------------------------------------------
// utility func to extract a DOMNodes Base attr value if present
// ---------------------------------------------------------------------------
static const XMLCh *
getBaseAttrValue(DOMNode *node){
if (node->getNodeType() == DOMNode::ELEMENT_NODE){
DOMElement *elem = (DOMElement *)node;
if(elem->hasAttributes()) {
/* get all the attributes of the node */
DOMNamedNodeMap *pAttributes = elem->getAttributes();
Alberto Massari
committed
unsigned int nSize = pAttributes->getLength();
for(unsigned int i=0;i<nSize;++i) {
DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->item(i);
/* get attribute name */
if (XMLString::equals(pAttributeNode->getName(), XIncludeUtils::fgXIBaseAttrName)){
/*if (namespace == XMLUni::fgXMLString){
}*/
return pAttributeNode->getValue();
}
}
}
}
return NULL;
}
// ---------------------------------------------------------------------------
// This method assumes that currentNode is an xinclude element and parses
// it accordingly, acting on what it finds.
// ---------------------------------------------------------------------------
bool
XIncludeUtils::doDOMNodeXInclude(DOMNode *xincludeNode, DOMDocument *parsedDocument, XMLEntityHandler* entityResolver){
bool modifiedNode = false;
/* the relevant attributes to look for */
const XMLCh *href = NULL;
const XMLCh *parse = NULL;
const XMLCh *xpointer = NULL;
const XMLCh *encoding = NULL;
const XMLCh *accept = NULL;
const XMLCh *acceptlanguage = NULL;
DOMNode *includeParent = xincludeNode->getParentNode();
if(xincludeNode->hasAttributes()) {
/* get all the attributes of the node */
DOMNamedNodeMap *pAttributes = xincludeNode->getAttributes();
Alberto Massari
committed
unsigned int nSize = pAttributes->getLength();
for(unsigned int i=0;i<nSize;++i) {
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->item(i);
const XMLCh *attrName = pAttributeNode->getName();
/* check each attribute against the potential useful names */
if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeHREFAttrName)){
href = pAttributeNode->getValue();
} else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeParseAttrName)){
parse = pAttributeNode->getValue();
} else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeXPointerAttrName)){
xpointer = pAttributeNode->getValue();
} else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeEncodingAttrName)){
encoding = pAttributeNode->getValue();
} else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeAcceptAttrName)){
accept = pAttributeNode->getValue();
} else if (XMLString::equals(attrName, XIncludeUtils::fgXIIncludeAcceptLanguageAttrName)){
acceptlanguage = pAttributeNode->getValue();
} else {
/* if any other attribute is in the xi namespace, it's an error */
const XMLCh *attrNamespaceURI = pAttributeNode->getNamespaceURI();
if (attrNamespaceURI && XMLString::equals(attrNamespaceURI, XIncludeUtils::fgXIIIncludeNamespaceURI)){
} else {
/* ignore - any other attribute is allowed according to spec,
and must be ignored */
}
}
}
}
Alberto Massari
committed
// 3.1 xi:include Element
// The children property of the xi:include element may include a single xi:fallback element;
// the appearance of more than one xi:fallback element, an xi:include element,
// or any other element from the XInclude namespace is a fatal error.
DOMNode *child;
DOMElement *fallback = NULL;
for (child = xincludeNode->getFirstChild(); child != 0; child=child->getNextSibling()){
if(child->getNodeType()!=DOMNode::ELEMENT_NODE)
continue;
if ( isXIFallbackDOMNode(child) ){
if (fallback != NULL){
/* fatal error - there are more than one fallback children */
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeMultipleFallbackElems,
parsedDocument->getDocumentURI(), parsedDocument->getDocumentURI());
return false;
}
fallback = (DOMElement*)child;
}
else if(isXIIncludeDOMNode(child) || XMLString::equals(child->getNamespaceURI(), XIncludeUtils::fgXIIIncludeNamespaceURI)) {
/* fatal error - an xi element different from xi:fallback is a child of xi:include */
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeDisallowedChild,
child->getNodeName(), parsedDocument->getDocumentURI());
return false;
}
}
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
if (href == NULL){
/* this is an unrecoverable error until we have xpointer support -
if there is an xpointer, the current document is assumed
however, there is no xpointer support yet */
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeNoHref,
NULL, parsedDocument->getDocumentURI());
return false;
}
/* set up the accept and accept-language values */
if (accept != NULL){
}
if (parse == NULL){
/* use the default, as specified */
parse = XIncludeUtils::fgXIIncludeParseAttrXMLValue;
}
if (xpointer != NULL){
/* not supported yet */
/* Note that finding an xpointer attr along with parse="text" is a Fatal Error
* - http://www.w3.org/TR/xinclude/#include-location */
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeXPointerNotSupported,
NULL, href);
return false;
}
/* set up the href according to what has gone before */
Alberto Massari
committed
XIncludeLocation hrefLoc(href);
XIncludeLocation relativeLocation(href);
const XMLCh *includeBase = xincludeNode->getBaseURI();
if (includeBase != NULL){
Alberto Massari
committed
hrefLoc.prependPath(includeBase);
}
if (getBaseAttrValue(xincludeNode) != NULL){
Alberto Massari
committed
relativeLocation.prependPath(getBaseAttrValue(xincludeNode));
}
/* Take the relevant action - we need to retrieve the target as a whole before
we can know if it was successful or not, therefore the do* methods do
not modify the parsedDocument. Swapping the results in is left to the
caller (i.e. here) */
DOMText *includedText = NULL;
DOMDocument *includedDoc = NULL;
if (XMLString::equals(parse, XIncludeUtils::fgXIIncludeParseAttrXMLValue)){
/* including a XML element */
includedDoc = doXIncludeXMLFileDOM(hrefLoc.getLocation(), relativeLocation.getLocation(), xincludeNode, parsedDocument, entityResolver);
} else if (XMLString::equals(parse, XIncludeUtils::fgXIIncludeParseAttrTextValue)){
/* including a text value */
includedText = doXIncludeTEXTFileDOM(hrefLoc.getLocation(), relativeLocation.getLocation(), encoding, xincludeNode, parsedDocument, entityResolver);
} else {
/* invalid parse attribute value - fatal error according to the specification */
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeInvalidParseVal,
parse, parsedDocument->getDocumentURI());
return false;
}
Alberto Massari
committed
if (includedDoc == NULL && includedText == NULL){
/* there was an error - this is now a resource error
let's see if there is a fallback */
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeIncludeFailedResourceError,
Alberto Massari
committed
hrefLoc.getLocation(), parsedDocument->getDocumentURI());
Alberto Massari
committed
if (includeParent == NULL){
includeParent = parsedDocument;
}
if (fallback){
Alberto Massari
committed
/* baseURI fixups - see http://www.w3.org/TR/xinclude/#base for details. */
XMLUri parentURI(includeParent->getBaseURI());
XMLUri includedURI(fallback->getBaseURI());
if (fallback->hasChildNodes()){
DOMNode *child = fallback->getFirstChild();
/* add the content of the fallback element, and remove the fallback elem itself */
Alberto Massari
committed
for ( ; child != NULL ; child=child->getNextSibling()){
if (child->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE){
continue;
}
DOMNode *newNode = parsedDocument->importNode(child, true);
Alberto Massari
committed
/* if the paths differ we need to add a base attribute */
if (newNode->getNodeType()==DOMNode::ELEMENT_NODE && !XMLString::equals(parentURI.getPath(), includedURI.getPath())){
if (getBaseAttrValue(newNode) == NULL){
/* need to calculate the proper path difference to get the relativePath */
((DOMElement*)newNode)->setAttribute(fgXIBaseAttrName, getBaseAttrValue(fallback->getParentNode()));
} else {
/* the included node has base of its own which takes precedence */
XIncludeLocation xil(getBaseAttrValue(newNode));
if (getBaseAttrValue(fallback->getParentNode()) != NULL){
/* prepend any specific base modification of the xinclude node */
xil.prependPath(getBaseAttrValue(fallback->getParentNode()));
}
((DOMElement*)newNode)->setAttribute(fgXIBaseAttrName, xil.getLocation());
}
}
DOMNode *newChild = includeParent->insertBefore(newNode, xincludeNode);
parseDOMNodeDoingXInclude(newChild, parsedDocument, entityResolver);
Alberto Massari
committed
includeParent->removeChild(xincludeNode);
modifiedNode = true;
} else {
/* empty fallback element - simply remove it! */
includeParent->removeChild(xincludeNode);
modifiedNode = true;
}
} else {
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeIncludeFailedNoFallback,
parsedDocument->getDocumentURI(), parsedDocument->getDocumentURI());
return false;
}
} else {
Alberto Massari
committed
if (includedDoc){
/* record the successful include while we process the children */
addDocumentURIToCurrentInclusionHistoryStack(hrefLoc.getLocation());
/* need to import the document prolog here */
DOMNode *child = includedDoc->getFirstChild();
for (; child != NULL; child = child->getNextSibling()) {
if (child->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
continue;
// check for NOTATION or ENTITY clash
if(child->getNodeType()==DOMNode::ELEMENT_NODE && includedDoc->getDoctype()!=NULL) {
DOMNamedNodeMap *pAttributes = child->getAttributes();
Alberto Massari
committed
unsigned int nSize = pAttributes->getLength();
for(unsigned int i=0;i<nSize;++i) {
Alberto Massari
committed
DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->item(i);
const DOMTypeInfo * typeInfo=pAttributeNode->getSchemaTypeInfo();
if(typeInfo && XMLString::equals(typeInfo->getTypeNamespace(), XMLUni::fgInfosetURIName)) {
if(XMLString::equals(typeInfo->getTypeName(), XMLUni::fgNotationString)) {
const XMLCh* notationName=pAttributeNode->getNodeValue();
DOMNotation* notat=(DOMNotation*)includedDoc->getDoctype()->getNotations()->getNamedItem(notationName);
Alberto Massari
committed
// ensure we have a DTD
if(parsedDocument->getDoctype()==NULL)
parsedDocument->insertBefore(parsedDocument->createDocumentType(parsedDocument->getDocumentElement()->getNodeName(), NULL,NULL), parsedDocument->getFirstChild());
DOMNotation* myNotation=(DOMNotation*)parsedDocument->getDoctype()->getNotations()->getNamedItem(notationName);
if(myNotation==NULL)
{
// it's missing, add it
parsedDocument->getDoctype()->getNotations()->setNamedItem(parsedDocument->importNode(notat, true));
Alberto Massari
committed
}
else if(XMLString::equals(myNotation->getPublicId(), notat->getPublicId()) &&
XMLString::equals(myNotation->getSystemId(), notat->getSystemId()) &&
XMLString::equals(myNotation->getBaseURI(), notat->getBaseURI()))
Alberto Massari
committed
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
{
// it's duplicate, ignore it
}
else
{
// it's a conflict, report it
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeConflictingNotation,
notationName, parsedDocument->getDocumentURI());
}
}
else if(XMLString::equals(typeInfo->getTypeName(), XMLUni::fgEntityString)) {
const XMLCh* entityName=pAttributeNode->getNodeValue();
DOMEntity* ent=(DOMEntity*)includedDoc->getDoctype()->getEntities()->getNamedItem(entityName);
// ensure we have a DTD
if(parsedDocument->getDoctype()==NULL)
parsedDocument->insertBefore(parsedDocument->createDocumentType(parsedDocument->getDocumentElement()->getNodeName(), NULL,NULL), parsedDocument->getFirstChild());
DOMEntity* myEnt=(DOMEntity*)parsedDocument->getDoctype()->getEntities()->getNamedItem(entityName);
if(myEnt==NULL)
{
// it's missing, add it
parsedDocument->getDoctype()->getEntities()->setNamedItem(parsedDocument->importNode(ent, true));
}
else if(XMLString::equals(myEnt->getPublicId(), ent->getPublicId()) &&
XMLString::equals(myEnt->getSystemId(), ent->getSystemId()) &&
XMLString::equals(myEnt->getBaseURI(), ent->getBaseURI()))
{
// it's duplicate, ignore it
}
else
{
// it's a conflict, report it
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeConflictingEntity,
entityName, parsedDocument->getDocumentURI());
}
}
}
}
}
DOMNode *newNode = parsedDocument->importNode(child, true);
DOMNode *newChild = includeParent->insertBefore(newNode, xincludeNode);
parseDOMNodeDoingXInclude(newChild, parsedDocument, entityResolver);
Alberto Massari
committed
}
includeParent->removeChild(xincludeNode);
popFromCurrentInclusionHistoryStack(NULL);
modifiedNode = true;
} else if (includedText){
includeParent->replaceChild(includedText, xincludeNode);
modifiedNode = true;
}
}
if (includedDoc)
includedDoc->release();
return modifiedNode;
}
DOMDocument *
XIncludeUtils::doXIncludeXMLFileDOM(const XMLCh *href,
const XMLCh *relativeHref,
DOMNode *includeNode,
DOMDocument *parsedDocument,
XMLEntityHandler* entityResolver){
if (XIncludeUtils::isInCurrentInclusionHistoryStack(href)){
/* including something back up the current history */
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCircularInclusionLoop,
href, href);
return NULL;
}
if (XMLString::equals(href, parsedDocument->getBaseURI())){
Alberto Massari
committed
/* trying to include itself */
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCircularInclusionDocIncludesSelf,
Alberto Massari
committed
return NULL;
}
/* Instantiate the DOM parser. */
Alberto Massari
committed
XercesDOMParser parser;
parser.setDoNamespaces(true);
/* don't want to recurse the xi processing here */
Alberto Massari
committed
parser.setDoXInclude(false);
/* create the schema info nodes, so that we can detect conflicting notations */
parser.setCreateSchemaInfo(true);
XMLInternalErrorHandler xierrhandler;
parser.setErrorHandler(&xierrhandler);
Alberto Massari
committed
DOMDocument *includedNode = NULL;
InputSource* is=NULL;
Janitor<InputSource> janIS(is);
if(entityResolver) {
XMLResourceIdentifier resIdentifier(XMLResourceIdentifier::ExternalEntity,
relativeHref,
NULL,
NULL,
includeNode->getBaseURI());
is=entityResolver->resolveEntity(&resIdentifier);
janIS.reset(is);
}
if(janIS.get()!=NULL)
parser.parse(*janIS.get());
else
parser.parse(href);
Alberto Massari
committed
/* need to be able to release the parser but keep the document */
if (!xierrhandler.getSawError() && !xierrhandler.getSawFatal())
includedNode = parser.adoptDocument();
}
catch (const XMLException& /*toCatch*/)
{
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeResourceErrorWarning,
href, href);
}
catch (const DOMException& /*toCatch*/)
{
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeResourceErrorWarning,
href, href);
}
catch (...)
{
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeResourceErrorWarning,
href, href);
}
//addDocumentURIToCurrentInclusionHistoryStack(href);
Alberto Massari
committed
if(includedNode != NULL){
/* baseURI fixups - see http://www.w3.org/TR/xinclude/#base for details. */
DOMElement *topLevelElement = includedNode->getDocumentElement();
if (topLevelElement && topLevelElement->getNodeType() == DOMNode::ELEMENT_NODE ){
XMLUri parentURI(includeNode->getBaseURI());
XMLUri includedURI(includedNode->getBaseURI());
/* if the paths differ we need to add a base attribute */
if (!XMLString::equals(parentURI.getPath(), includedURI.getPath())){
if (getBaseAttrValue(topLevelElement) == NULL){
/* need to calculate the proper path difference to get the relativePath */
topLevelElement->setAttribute(fgXIBaseAttrName, relativeHref);
} else {
/* the included node has base of its own which takes precedence */
XIncludeLocation xil(getBaseAttrValue(topLevelElement));
if (getBaseAttrValue(includeNode) != NULL){
/* prepend any specific base modification of the xinclude node */
xil.prependPath(getBaseAttrValue(includeNode));
}
topLevelElement->setAttribute(fgXIBaseAttrName, xil.getLocation());
}
}
}
}
return includedNode;
}
DOMText *
XIncludeUtils::doXIncludeTEXTFileDOM(const XMLCh *href,
const XMLCh *relativeHref,
const XMLCh *encoding,
DOMNode *includeNode,
DOMDocument *parsedDocument,
XMLEntityHandler* entityResolver){
Alberto Massari
committed
if (encoding == NULL)
/* "UTF-8" is stipulated default by spec */
encoding = XMLUni::fgUTF8EncodingString;
XMLTransService::Codes failReason;
XMLTranscoder* transcoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, 16*1024);
Janitor<XMLTranscoder> janTranscoder(transcoder);
Alberto Massari
committed
if (failReason){
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCannotOpenFile, href, href);
return NULL;
}
//addDocumentURIToCurrentInclusionHistoryStack(href);
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
InputSource* is=NULL;
Janitor<InputSource> janIS(is);
if(entityResolver) {
XMLResourceIdentifier resIdentifier(XMLResourceIdentifier::ExternalEntity,
relativeHref,
NULL,
NULL,
includeNode->getBaseURI());
is=entityResolver->resolveEntity(&resIdentifier);
janIS.reset(is);
}
if(janIS.get()==NULL)
janIS.reset(new URLInputSource(href));
if(janIS.get()==NULL) {
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCannotOpenFile,
href, href);
return NULL;
}
BinInputStream* stream=janIS.get()->makeStream();
if(stream==NULL) {
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCannotOpenFile,
href, href);
return NULL;
}
Janitor<BinInputStream> janStream(stream);
const int maxToRead=16*1024;
XMLByte* buffer=(XMLByte*)XMLPlatformUtils::fgMemoryManager->allocate(maxToRead * sizeof(XMLByte));
if(buffer==NULL)
throw OutOfMemoryException();
ArrayJanitor<XMLByte> janBuffer(buffer, XMLPlatformUtils::fgMemoryManager);
XMLCh* xmlChars=(XMLCh*)XMLPlatformUtils::fgMemoryManager->allocate(maxToRead*2*sizeof(XMLCh));
if(xmlChars==NULL)
throw OutOfMemoryException();
ArrayJanitor<XMLCh> janUniBuffer(xmlChars, XMLPlatformUtils::fgMemoryManager);
unsigned char *charSizes = (unsigned char *)XMLPlatformUtils::fgMemoryManager->allocate(maxToRead * sizeof(unsigned char));
if(charSizes==NULL)
throw OutOfMemoryException();
ArrayJanitor<unsigned char> janCharSizes(charSizes, XMLPlatformUtils::fgMemoryManager);
Alberto Massari
committed
XMLSize_t nRead, nOffset=0;
XMLBuffer repository;
while((nRead=stream->readBytes(buffer+nOffset, maxToRead-nOffset))>0){
Alberto Massari
committed
XMLSize_t bytesEaten=0;
XMLSize_t nCount = transcoder->transcodeFrom(buffer, nRead, xmlChars, maxToRead*2, bytesEaten, charSizes);
repository.append(xmlChars, nCount);
if(bytesEaten<nRead) {
nOffset=nRead-bytesEaten;
memmove(buffer, buffer+bytesEaten, nRead-bytesEaten);
}
Alberto Massari
committed
}
return parsedDocument->createTextNode(repository.getRawBuffer());
Alberto Massari
committed
/*static*/ bool
XIncludeUtils::isXIIncludeDOMNode(DOMNode *node){
const XMLCh *nodeName = node->getLocalName();
const XMLCh *namespaceURI = node->getNamespaceURI();
return isXIIncludeElement(nodeName, namespaceURI);
}
Alberto Massari
committed
/*static*/ bool
XIncludeUtils::isXIFallbackDOMNode(DOMNode *node){
const XMLCh *nodeName = node->getLocalName();
const XMLCh *namespaceURI = node->getNamespaceURI();
return isXIFallbackElement(nodeName, namespaceURI);
}
Alberto Massari
committed
/*static*/ bool
XIncludeUtils::isXIIncludeElement(const XMLCh *name, const XMLCh *namespaceURI){
if (namespaceURI == NULL || name == NULL){
/* no namespaces not supported */
return false;
}
if (XMLString::equals(name, fgXIIncludeQName)
&& XMLString::equals(namespaceURI, fgXIIIncludeNamespaceURI)){
return true;
}
return false;
}
Alberto Massari
committed
/*static*/ bool
XIncludeUtils::isXIFallbackElement(const XMLCh *name, const XMLCh *namespaceURI){
if (namespaceURI == NULL || name == NULL){
/* no namespaces not supported */
return false;
}
if (XMLString::equals(name, fgXIFallbackQName)
&& XMLString::equals(namespaceURI, fgXIIIncludeNamespaceURI)){
return true;
}
return false;
}
/* 4.1.1 */
const XMLCh *
XIncludeUtils::getEscapedHRefAttrValue(const XMLCh * /*hrefAttrValue*/, bool & /*needsDeallocating*/){
XMLCh *escapedAttr = NULL;
return escapedAttr;
}
/* 4.1.2 */
bool
XIncludeUtils::setContentNegotiation(const XMLCh * /*acceptAttrValue*/, const XMLCh * /*acceptLangAttrValue*/){
return false;
}
bool
XIncludeUtils::checkTextIsValidForInclude(XMLCh * /*includeChars*/){
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
return false;
}
// ========================================================
// the stack utilities are slightly convoluted debug versions, they
// will be pared down for the release code
// ========================================================
static XIncludeHistoryNode *
getTopOfCurrentInclusionHistoryStack(XIncludeHistoryNode *head){
XIncludeHistoryNode *historyCursor = head;
if (historyCursor == NULL){
return NULL;
}
while (historyCursor->next != NULL){
historyCursor = historyCursor->next;
}
return historyCursor;
}
bool
XIncludeUtils::addDocumentURIToCurrentInclusionHistoryStack(const XMLCh *URItoAdd){
XIncludeHistoryNode *newNode = (XIncludeHistoryNode *)XMLPlatformUtils::fgMemoryManager->allocate(sizeof(XIncludeHistoryNode));
if (newNode == NULL){
return false;
}
newNode->URI = XMLString::replicate(URItoAdd);
newNode->next = NULL;
if (fIncludeHistoryHead == NULL){
fIncludeHistoryHead = newNode;
return true;
}
XIncludeHistoryNode *topNode = getTopOfCurrentInclusionHistoryStack(fIncludeHistoryHead);
topNode->next = newNode;
return true;
}
bool
XIncludeUtils::isInCurrentInclusionHistoryStack(const XMLCh *toFind){
XIncludeHistoryNode *historyCursor = fIncludeHistoryHead;
/* walk the list */
while (historyCursor != NULL){
if (XMLString::equals(toFind, historyCursor->URI)){
return true;
}
historyCursor = historyCursor->next;
}
return false;
}
XIncludeHistoryNode *
XIncludeUtils::popFromCurrentInclusionHistoryStack(const XMLCh * /*toPop*/){
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
XIncludeHistoryNode *historyCursor = fIncludeHistoryHead;
XIncludeHistoryNode *penultimateCursor = historyCursor;
if (fIncludeHistoryHead == NULL){
return NULL;
}
while (historyCursor->next != NULL){
penultimateCursor = historyCursor;
historyCursor = historyCursor->next;
}
if (penultimateCursor == fIncludeHistoryHead){
historyCursor = fIncludeHistoryHead;
fIncludeHistoryHead = NULL;
} else {
penultimateCursor->next = NULL;
}
// XERCES_STD_QUALIFIER cerr << "poppinURIofStack " << XMLString::transcode(historyCursor->URI) << XERCES_STD_QUALIFIER endl;
XMLString::release(&(historyCursor->URI));
XMLPlatformUtils::fgMemoryManager->deallocate((void *)historyCursor);
return NULL;
}
void
XIncludeUtils::freeInclusionHistory(){
XIncludeHistoryNode *historyCursor = XIncludeUtils::fIncludeHistoryHead;
while (historyCursor != NULL){
XIncludeHistoryNode *next = historyCursor->next;
/* XMLString::release(&(historyCursor->URI));
XMLPlatformUtils::fgMemoryManager->deallocate((void *)historyCursor); */
historyCursor = next;
}
XIncludeUtils::fIncludeHistoryHead = NULL;
}
bool
XIncludeUtils::reportError(const DOMNode* const /*errorNode*/
, XMLErrs::Codes errorType
, const XMLCh* const errorMsg
, const XMLCh * const href)
{
bool toContinueProcess = true; /* default value for no error handler */
const XMLCh* const systemId = href;
const XMLCh* const publicId = href;
/* TODO - look these up somehow? */
const unsigned long lineNum = 0;
const unsigned long colNum = 0;
if (fErrorReporter)
{
// Load the message into a local for display
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
XMLCh errText[msgSize + 1];
/* TODO - investigate whether this is complete */
XMLMsgLoader *errMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain);
if (errorMsg == NULL){
if (errMsgLoader->loadMsg(errorType, errText, msgSize))
{
// <TBD> Probably should load a default msg here
}
} else {
if (errMsgLoader->loadMsg(errorType, errText, msgSize, errorMsg))
{
// <TBD> Probably should load a default msg here
}
}
fErrorReporter->error(errorType
, XMLUni::fgXMLErrDomain //fgXMLErrDomain
, XMLErrs::errorType(errorType)
, errText
, systemId
, publicId
, lineNum
, colNum);
}
if (XMLErrs::isFatal(errorType))
fErrorCount++;
return toContinueProcess;
}
/* TODO - declared in this file for convenience, prob ought to be moved out to
util/XMLUni.cpp before releasing */
const XMLCh XIncludeUtils::fgXIIncludeQName[] =
{
chLatin_i, chLatin_n, chLatin_c, chLatin_l, chLatin_u, chLatin_d, chLatin_e, chNull
};
const XMLCh XIncludeUtils::fgXIFallbackQName[] =
{
chLatin_f, chLatin_a, chLatin_l, chLatin_l, chLatin_b, chLatin_a, chLatin_c, chLatin_k, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeHREFAttrName[] =
{
chLatin_h, chLatin_r, chLatin_e, chLatin_f, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeParseAttrName[] =
{
chLatin_p, chLatin_a, chLatin_r, chLatin_s, chLatin_e, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeXPointerAttrName[] =
{
chLatin_x, chLatin_p, chLatin_o, chLatin_i, chLatin_n, chLatin_t, chLatin_e, chLatin_r, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeEncodingAttrName[] =
{
chLatin_e, chLatin_n, chLatin_c, chLatin_o, chLatin_d, chLatin_i, chLatin_n, chLatin_g, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeAcceptAttrName[] =
{
chLatin_a, chLatin_c, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeAcceptLanguageAttrName[] =
{
chLatin_a, chLatin_c, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chDash, chLatin_l, chLatin_a,
chLatin_n, chLatin_g, chLatin_u, chLatin_a, chLatin_g, chLatin_e, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeParseAttrXMLValue[] =
{
chLatin_x, chLatin_m, chLatin_l, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeParseAttrTextValue[] =
{
chLatin_t, chLatin_e, chLatin_x, chLatin_t, chNull
};
const XMLCh XIncludeUtils::fgXIIIncludeNamespaceURI[] =
{
/* http://www.w3.org/2001/XInclude */
chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash
, chForwardSlash, chLatin_w, chLatin_w, chLatin_w, chPeriod
, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g
, chForwardSlash, chDigit_2, chDigit_0, chDigit_0, chDigit_1
, chForwardSlash, chLatin_X, chLatin_I, chLatin_n, chLatin_c, chLatin_l
, chLatin_u, chLatin_d, chLatin_e, chNull
};
const XMLCh XIncludeUtils::fgXIBaseAttrName[] =
{
chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
};
XERCES_CPP_NAMESPACE_END