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){
Alberto Massari
committed
fErrorReporter = errorReporter;
fIncludeHistoryHead = NULL;
}
XIncludeUtils::~XIncludeUtils(){
Alberto Massari
committed
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){
if (sourceNode) {
Alberto Massari
committed
/* 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);
}
Alberto Massari
committed
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;
}
}
Alberto Massari
committed
/* 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 (XMLSize_t i = 0; i < children.size(); i++){
Alberto Massari
committed
parseDOMNodeDoingXInclude(children.elementAt(i), parsedDocument, entityResolver);
}
}
}
// ---------------------------------------------------------------------------
// utility func to extract a DOMNodes Base attr value if present
// ---------------------------------------------------------------------------
static const XMLCh *
getBaseAttrValue(DOMNode *node){
Alberto Massari
committed
if (node->getNodeType() == DOMNode::ELEMENT_NODE){
DOMElement *elem = (DOMElement *)node;
if(elem->hasAttributes()) {
/* get all the attributes of the node */
DOMNamedNodeMap *pAttributes = elem->getAttributes();
XMLSize_t nSize = pAttributes->getLength();
for(XMLSize_t i=0;i<nSize;++i) {
DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->item(i);
/* get attribute name */
Alberto Massari
committed
if (XMLString::equals(pAttributeNode->getName(), XIncludeUtils::fgXIBaseAttrName)){
/*if (namespace == XMLUni::fgXMLString){
Alberto Massari
committed
}*/
return pAttributeNode->getValue();
}
Alberto Massari
committed
}
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){
Alberto Massari
committed
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();
Alberto Massari
committed
if(xincludeNode->hasAttributes()) {
/* get all the attributes of the node */
DOMNamedNodeMap *pAttributes = xincludeNode->getAttributes();
XMLSize_t nSize = pAttributes->getLength();
for(XMLSize_t i=0;i<nSize;++i) {
Alberto Massari
committed
139
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
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.
Alberto Massari
committed
DOMNode *child;
Alberto Massari
committed
DOMElement *fallback = NULL;
Alberto Massari
committed
for (child = xincludeNode->getFirstChild(); child != 0; child=child->getNextSibling()){
Alberto Massari
committed
if(child->getNodeType()!=DOMNode::ELEMENT_NODE)
continue;
Alberto Massari
committed
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;
}
Alberto Massari
committed
else if(isXIIncludeDOMNode(child) || XMLString::equals(child->getNamespaceURI(), XIncludeUtils::fgXIIIncludeNamespaceURI)) {
Alberto Massari
committed
/* 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;
Alberto Massari
committed
}
Alberto Massari
committed
}
if (href == NULL){
/* this is an unrecoverable error until we have xpointer support -
if there is an xpointer, the current document is assumed
Alberto Massari
committed
however, there is no xpointer support yet */
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeNoHref,
NULL, parsedDocument->getDocumentURI());
return false;
}
Alberto Massari
committed
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/* 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 */
XIncludeLocation hrefLoc(href);
XIncludeLocation relativeLocation(href);
const XMLCh *includeBase = xincludeNode->getBaseURI();
if (includeBase != NULL){
hrefLoc.prependPath(includeBase);
}
if (getBaseAttrValue(xincludeNode) != NULL){
relativeLocation.prependPath(getBaseAttrValue(xincludeNode));
Alberto Massari
committed
}
/* 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
Alberto Massari
committed
let's see if there is a fallback */
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeIncludeFailedResourceError,
hrefLoc.getLocation(), parsedDocument->getDocumentURI());
Alberto Massari
committed
if (includeParent == NULL){
Alberto Massari
committed
includeParent = parsedDocument;
}
Alberto Massari
committed
// we could be getting errors trying to insert elements at the root of the document, so we should use replaceChild;
// in order to handle multiple nodes, add them to a document fragment and use that to replace the original node
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());
Alberto Massari
committed
if (fallback->hasChildNodes()){
DOMDocumentFragment* frag = parsedDocument->createDocumentFragment();
DOMNode *child = fallback->getFirstChild();
/* add the content of the fallback element, and remove the fallback elem itself */
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());
}
}
Alberto Massari
committed
DOMNode *newChild = frag->appendChild(newNode);
parseDOMNodeDoingXInclude(newChild, parsedDocument, entityResolver);
}
includeParent->replaceChild(frag, xincludeNode);
frag->release();
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());
Alberto Massari
committed
DOMDocumentFragment* frag = parsedDocument->createDocumentFragment();
Alberto Massari
committed
/* 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) {
Alberto Massari
committed
DOMNamedNodeMap *pAttributes = child->getAttributes();
XMLSize_t nSize = pAttributes->getLength();
for(XMLSize_t i=0;i<nSize;++i) {
Alberto Massari
committed
DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->item(i);
Alberto Massari
committed
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
{
// it's duplicate, ignore it
}
else
{
// it's a conflict, report it
Alberto Massari
committed
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeConflictingNotation,
notationName, parsedDocument->getDocumentURI());
Alberto Massari
committed
}
}
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()) &&
Alberto Massari
committed
XMLString::equals(myEnt->getBaseURI(), ent->getBaseURI()))
{
// it's duplicate, ignore it
}
else
{
// it's a conflict, report it
Alberto Massari
committed
XIncludeUtils::reportError(xincludeNode, XMLErrs::XIncludeConflictingEntity,
entityName, parsedDocument->getDocumentURI());
Alberto Massari
committed
}
}
}
}
}
DOMNode *newNode = parsedDocument->importNode(child, true);
Alberto Massari
committed
DOMNode *newChild = frag->appendChild(newNode);
parseDOMNodeDoingXInclude(newChild, parsedDocument, entityResolver);
Alberto Massari
committed
}
Alberto Massari
committed
includeParent->replaceChild(frag, xincludeNode);
frag->release();
Alberto Massari
committed
popFromCurrentInclusionHistoryStack(NULL);
modifiedNode = true;
} else if (includedText){
includeParent->replaceChild(includedText, xincludeNode);
modifiedNode = true;
}
Alberto Massari
committed
}
Alberto Massari
committed
if (includedDoc)
includedDoc->release();
Alberto Massari
committed
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,
Alberto Massari
committed
DOMNode *includeNode,
DOMDocument *parsedDocument,
XMLEntityHandler* entityResolver){
Alberto Massari
committed
if (encoding == NULL)
/* "UTF-8" is stipulated default by spec */
encoding = XMLUni::fgUTF8EncodingString;
Alberto Massari
committed
Alberto Massari
committed
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;
Alberto Massari
committed
}
Alberto Massari
committed
//addDocumentURIToCurrentInclusionHistoryStack(href);
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) {
Alberto Massari
committed
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCannotOpenFile,
href, href);
return NULL;
}
BinInputStream* stream=janIS.get()->makeStream();
if(stream==NULL) {
Alberto Massari
committed
XIncludeUtils::reportError(parsedDocument, XMLErrs::XIncludeCannotOpenFile,
href, href);
return NULL;
}
Janitor<BinInputStream> janStream(stream);
const XMLSize_t 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;
Alberto Massari
committed
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());
/*static*/ bool
XIncludeUtils::isXIIncludeDOMNode(DOMNode *node){
Alberto Massari
committed
const XMLCh *nodeName = node->getLocalName();
const XMLCh *namespaceURI = node->getNamespaceURI();
Alberto Massari
committed
return isXIIncludeElement(nodeName, namespaceURI);
Alberto Massari
committed
/*static*/ bool
XIncludeUtils::isXIFallbackDOMNode(DOMNode *node){
Alberto Massari
committed
const XMLCh *nodeName = node->getLocalName();
const XMLCh *namespaceURI = node->getNamespaceURI();
Alberto Massari
committed
return isXIFallbackElement(nodeName, namespaceURI);
/*static*/ bool
XIncludeUtils::isXIIncludeElement(const XMLCh *name, const XMLCh *namespaceURI){
Alberto Massari
committed
if (namespaceURI == NULL || name == NULL){
/* no namespaces not supported */
return false;
}
if (XMLString::equals(name, fgXIIncludeQName)
Alberto Massari
committed
&& XMLString::equals(namespaceURI, fgXIIIncludeNamespaceURI)){
return true;
}
return false;
/*static*/ bool
XIncludeUtils::isXIFallbackElement(const XMLCh *name, const XMLCh *namespaceURI){
Alberto Massari
committed
if (namespaceURI == NULL || name == NULL){
/* no namespaces not supported */
return false;
}
if (XMLString::equals(name, fgXIFallbackQName)
Alberto Massari
committed
&& XMLString::equals(namespaceURI, fgXIIIncludeNamespaceURI)){
return true;
}
return false;
}
/* 4.1.1 */
const XMLCh *
XIncludeUtils::getEscapedHRefAttrValue(const XMLCh * /*hrefAttrValue*/, bool & /*needsDeallocating*/){
Alberto Massari
committed
XMLCh *escapedAttr = NULL;
return escapedAttr;
}
/* 4.1.2 */
bool
XIncludeUtils::setContentNegotiation(const XMLCh * /*acceptAttrValue*/, const XMLCh * /*acceptLangAttrValue*/){
Alberto Massari
committed
return false;
XIncludeUtils::checkTextIsValidForInclude(XMLCh * /*includeChars*/){
Alberto Massari
committed
return false;
}
// ========================================================
// the stack utilities are slightly convoluted debug versions, they
// will be pared down for the release code
// ========================================================
static XIncludeHistoryNode *
getTopOfCurrentInclusionHistoryStack(XIncludeHistoryNode *head){
Alberto Massari
committed
XIncludeHistoryNode *historyCursor = head;
if (historyCursor == NULL){
return NULL;
}
while (historyCursor->next != NULL){
historyCursor = historyCursor->next;
}
return historyCursor;
bool
XIncludeUtils::addDocumentURIToCurrentInclusionHistoryStack(const XMLCh *URItoAdd){
Alberto Massari
committed
XIncludeHistoryNode *newNode = (XIncludeHistoryNode *)XMLPlatformUtils::fgMemoryManager->allocate(sizeof(XIncludeHistoryNode));
if (newNode == NULL){
return false;
}
newNode->URI = XMLString::replicate(URItoAdd);
newNode->next = NULL;
Alberto Massari
committed
if (fIncludeHistoryHead == NULL){
fIncludeHistoryHead = newNode;
return true;
Alberto Massari
committed
}
XIncludeHistoryNode *topNode = getTopOfCurrentInclusionHistoryStack(fIncludeHistoryHead);
topNode->next = newNode;
return true;
bool
XIncludeUtils::isInCurrentInclusionHistoryStack(const XMLCh *toFind){
Alberto Massari
committed
XIncludeHistoryNode *historyCursor = fIncludeHistoryHead;
/* walk the list */
while (historyCursor != NULL){
Alberto Massari
committed
if (XMLString::equals(toFind, historyCursor->URI)){
return true;
}
historyCursor = historyCursor->next;
}
return false;
}
XIncludeHistoryNode *
XIncludeUtils::popFromCurrentInclusionHistoryStack(const XMLCh * /*toPop*/){
Alberto Massari
committed
XIncludeHistoryNode *historyCursor = fIncludeHistoryHead;
XIncludeHistoryNode *penultimateCursor = historyCursor;
if (fIncludeHistoryHead == NULL){
return NULL;
Alberto Massari
committed
}
while (historyCursor->next != NULL){
penultimateCursor = historyCursor;
historyCursor = historyCursor->next;
}
Alberto Massari
committed
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(){
Alberto Massari
committed
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
Alberto Massari
committed
, const XMLCh * const href)
{
bool toContinueProcess = true; /* default value for no error handler */
Alberto Massari
committed
const XMLCh* const systemId = href;
const XMLCh* const publicId = href;
/* TODO - look these up somehow? */
const XMLFileLoc lineNum = 0;
const XMLFileLoc colNum = 0;
if (fErrorReporter)
{
Alberto Massari
committed
// Load the message into a local for display
XMLCh errText[msgSize + 1];
Alberto Massari
committed
/* 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
Alberto Massari
committed
, 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[] =
{
Alberto Massari
committed
chLatin_i, chLatin_n, chLatin_c, chLatin_l, chLatin_u, chLatin_d, chLatin_e, chNull
};
const XMLCh XIncludeUtils::fgXIFallbackQName[] =
{
Alberto Massari
committed
chLatin_f, chLatin_a, chLatin_l, chLatin_l, chLatin_b, chLatin_a, chLatin_c, chLatin_k, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeHREFAttrName[] =
{
Alberto Massari
committed
chLatin_h, chLatin_r, chLatin_e, chLatin_f, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeParseAttrName[] =
{
Alberto Massari
committed
chLatin_p, chLatin_a, chLatin_r, chLatin_s, chLatin_e, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeXPointerAttrName[] =
{
Alberto Massari
committed
chLatin_x, chLatin_p, chLatin_o, chLatin_i, chLatin_n, chLatin_t, chLatin_e, chLatin_r, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeEncodingAttrName[] =
{
Alberto Massari
committed
chLatin_e, chLatin_n, chLatin_c, chLatin_o, chLatin_d, chLatin_i, chLatin_n, chLatin_g, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeAcceptAttrName[] =
{
Alberto Massari
committed
chLatin_a, chLatin_c, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chNull
};
const XMLCh XIncludeUtils::fgXIIncludeAcceptLanguageAttrName[] =
{
Alberto Massari
committed
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[] =
{
Alberto Massari
committed
chLatin_t, chLatin_e, chLatin_x, chLatin_t, chNull
};
const XMLCh XIncludeUtils::fgXIIIncludeNamespaceURI[] =
{
Alberto Massari
committed
/* 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
Alberto Massari
committed
, chForwardSlash, chLatin_X, chLatin_I, chLatin_n, chLatin_c, chLatin_l
, chLatin_u, chLatin_d, chLatin_e, chNull
};
const XMLCh XIncludeUtils::fgXIBaseAttrName[] =
{
Alberto Massari
committed
chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
};
XERCES_CPP_NAMESPACE_END