xmlfix3: unoxml: prevent invalid child-parent relationships:
new method CNode::IsChildTypeAllowed(NodeType). use it in appendChild(), insertBefore(), replaceChild().
This commit is contained in:
@@ -70,6 +70,17 @@ namespace DOM
|
||||
return pNs;
|
||||
}
|
||||
|
||||
bool CAttr::IsChildTypeAllowed(NodeType const nodeType)
|
||||
{
|
||||
switch (nodeType) {
|
||||
case NodeType_TEXT_NODE:
|
||||
case NodeType_ENTITY_REFERENCE_NODE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
OUString SAL_CALL CAttr::getNodeName()
|
||||
throw (RuntimeException)
|
||||
{
|
||||
|
||||
@@ -68,6 +68,8 @@ namespace DOM
|
||||
/// return the libxml namespace corresponding to m_pNamespace on pNode
|
||||
xmlNsPtr GetNamespace(xmlNodePtr const pNode);
|
||||
|
||||
virtual bool IsChildTypeAllowed(NodeType const nodeType);
|
||||
|
||||
/**
|
||||
Returns the name of this attribute.
|
||||
*/
|
||||
|
||||
@@ -56,6 +56,20 @@
|
||||
|
||||
namespace DOM
|
||||
{
|
||||
static xmlNodePtr lcl_getDocumentType(xmlDocPtr const i_pDocument)
|
||||
{
|
||||
// find the doc type
|
||||
xmlNodePtr cur = i_pDocument->children;
|
||||
while (cur != NULL)
|
||||
{
|
||||
if ((cur->type == XML_DOCUMENT_TYPE_NODE) ||
|
||||
(cur->type == XML_DTD_NODE)) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// get the pointer to the root element node of the document
|
||||
static xmlNodePtr lcl_getDocumentRootPtr(xmlDocPtr const i_pDocument)
|
||||
{
|
||||
@@ -292,6 +306,24 @@ namespace DOM
|
||||
rContext.mxDocHandler->endDocument();
|
||||
}
|
||||
|
||||
bool CDocument::IsChildTypeAllowed(NodeType const nodeType)
|
||||
{
|
||||
switch (nodeType) {
|
||||
case NodeType_PROCESSING_INSTRUCTION_NODE:
|
||||
case NodeType_COMMENT_NODE:
|
||||
return true;
|
||||
case NodeType_ELEMENT_NODE:
|
||||
// there may be only one!
|
||||
return 0 == lcl_getDocumentRootPtr(m_aDocPtr);
|
||||
case NodeType_DOCUMENT_TYPE_NODE:
|
||||
// there may be only one!
|
||||
return 0 == lcl_getDocumentType(m_aDocPtr);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SAL_CALL CDocument::addListener(const Reference< XStreamListener >& aListener )
|
||||
throw (RuntimeException)
|
||||
{
|
||||
@@ -601,15 +633,9 @@ namespace DOM
|
||||
{
|
||||
::osl::MutexGuard const g(m_Mutex);
|
||||
|
||||
// find the doc type
|
||||
xmlNodePtr cur = m_aDocPtr->children;
|
||||
while (cur != NULL)
|
||||
{
|
||||
if (cur->type == XML_DOCUMENT_TYPE_NODE || cur->type == XML_DTD_NODE)
|
||||
break;
|
||||
}
|
||||
xmlNodePtr const pDocType(lcl_getDocumentType(m_aDocPtr));
|
||||
Reference< XDocumentType > const xRet(
|
||||
static_cast< XNode* >(GetCNode(cur).get()),
|
||||
static_cast< XNode* >(GetCNode(pDocType).get()),
|
||||
UNO_QUERY);
|
||||
return xRet;
|
||||
}
|
||||
|
||||
@@ -131,6 +131,8 @@ namespace DOM
|
||||
|
||||
virtual void fastSaxify( Context& rContext );
|
||||
|
||||
virtual bool IsChildTypeAllowed(NodeType const nodeType);
|
||||
|
||||
/**
|
||||
Creates an Attr of the given name.
|
||||
*/
|
||||
|
||||
@@ -37,6 +37,21 @@ namespace DOM
|
||||
{
|
||||
}
|
||||
|
||||
bool CDocumentFragment::IsChildTypeAllowed(NodeType const nodeType)
|
||||
{
|
||||
switch (nodeType) {
|
||||
case NodeType_ELEMENT_NODE:
|
||||
case NodeType_PROCESSING_INSTRUCTION_NODE:
|
||||
case NodeType_COMMENT_NODE:
|
||||
case NodeType_TEXT_NODE:
|
||||
case NodeType_CDATA_SECTION_NODE:
|
||||
case NodeType_ENTITY_REFERENCE_NODE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
OUString SAL_CALL CDocumentFragment::getNodeName()throw (RuntimeException)
|
||||
{
|
||||
return OUString::createFromAscii("#document-fragment");
|
||||
|
||||
@@ -55,6 +55,8 @@ namespace DOM
|
||||
xmlNodePtr const pNode);
|
||||
|
||||
public:
|
||||
virtual bool IsChildTypeAllowed(NodeType const nodeType);
|
||||
|
||||
// ---- resolve uno inheritance problems...
|
||||
// overrides for XNode base
|
||||
virtual OUString SAL_CALL getNodeName()
|
||||
|
||||
@@ -206,6 +206,28 @@ namespace DOM
|
||||
popContext(i_rContext);
|
||||
}
|
||||
|
||||
bool CElement::IsChildTypeAllowed(NodeType const nodeType)
|
||||
{
|
||||
switch (nodeType) {
|
||||
case NodeType_ELEMENT_NODE:
|
||||
case NodeType_TEXT_NODE:
|
||||
case NodeType_COMMENT_NODE:
|
||||
case NodeType_PROCESSING_INSTRUCTION_NODE:
|
||||
case NodeType_CDATA_SECTION_NODE:
|
||||
case NodeType_ENTITY_REFERENCE_NODE:
|
||||
return true;
|
||||
case NodeType_ATTRIBUTE_NODE:
|
||||
/* this is not relly allowed by the DOM spec, but this
|
||||
implementation has evidently supported it (by special case
|
||||
handling, so the attribute does not actually become a child)
|
||||
so allow it for backward compatiblity */
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Retrieves an attribute value by name.
|
||||
return empty string if attribute is not set
|
||||
|
||||
@@ -66,6 +66,8 @@ namespace DOM
|
||||
|
||||
virtual void fastSaxify( Context& i_rContext );
|
||||
|
||||
virtual bool IsChildTypeAllowed(NodeType const nodeType);
|
||||
|
||||
/**
|
||||
Retrieves an attribute value by name.
|
||||
*/
|
||||
|
||||
@@ -41,6 +41,21 @@ namespace DOM
|
||||
{
|
||||
}
|
||||
|
||||
bool CEntity::IsChildTypeAllowed(NodeType const nodeType)
|
||||
{
|
||||
switch (nodeType) {
|
||||
case NodeType_ELEMENT_NODE:
|
||||
case NodeType_PROCESSING_INSTRUCTION_NODE:
|
||||
case NodeType_COMMENT_NODE:
|
||||
case NodeType_TEXT_NODE:
|
||||
case NodeType_CDATA_SECTION_NODE:
|
||||
case NodeType_ENTITY_REFERENCE_NODE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
For unparsed entities, the name of the notation for the entity.
|
||||
*/
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace DOM
|
||||
xmlEntityPtr const pEntity);
|
||||
|
||||
public:
|
||||
virtual bool IsChildTypeAllowed(NodeType const nodeType);
|
||||
|
||||
/**
|
||||
For unparsed entities, the name of the notation for the entity.
|
||||
|
||||
@@ -39,6 +39,21 @@ namespace DOM
|
||||
{
|
||||
}
|
||||
|
||||
bool CEntityReference::IsChildTypeAllowed(NodeType const nodeType)
|
||||
{
|
||||
switch (nodeType) {
|
||||
case NodeType_ELEMENT_NODE:
|
||||
case NodeType_PROCESSING_INSTRUCTION_NODE:
|
||||
case NodeType_COMMENT_NODE:
|
||||
case NodeType_TEXT_NODE:
|
||||
case NodeType_CDATA_SECTION_NODE:
|
||||
case NodeType_ENTITY_REFERENCE_NODE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
OUString SAL_CALL CEntityReference::getNodeName()throw (RuntimeException)
|
||||
{
|
||||
::osl::MutexGuard const g(m_rMutex);
|
||||
|
||||
@@ -57,6 +57,8 @@ namespace DOM
|
||||
xmlNodePtr const pNode);
|
||||
|
||||
public:
|
||||
virtual bool IsChildTypeAllowed(NodeType const nodeType);
|
||||
|
||||
// ---- resolve uno inheritance problems...
|
||||
// overrides for XNode base
|
||||
virtual OUString SAL_CALL getNodeName()
|
||||
|
||||
@@ -289,6 +289,12 @@ namespace DOM
|
||||
// default: do nothing
|
||||
}
|
||||
|
||||
bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/)
|
||||
{
|
||||
// default: no children allowed
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Adds the node newChild to the end of the list of children of this node.
|
||||
*/
|
||||
@@ -323,6 +329,11 @@ namespace DOM
|
||||
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
|
||||
throw e;
|
||||
}
|
||||
if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) {
|
||||
DOMException e;
|
||||
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
|
||||
throw e;
|
||||
}
|
||||
|
||||
// check whether this is an attribute node; it needs special handling
|
||||
xmlNodePtr res = NULL;
|
||||
@@ -691,6 +702,11 @@ namespace DOM
|
||||
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
|
||||
throw e;
|
||||
}
|
||||
if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
|
||||
DOMException e;
|
||||
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
|
||||
throw e;
|
||||
}
|
||||
|
||||
// attributes are unordered anyway, so just do appendChild
|
||||
if (XML_ATTRIBUTE_NODE == pNewChild->type) {
|
||||
@@ -828,7 +844,6 @@ namespace DOM
|
||||
if (!xOldChild.is() || !xNewChild.is()) {
|
||||
throw RuntimeException();
|
||||
}
|
||||
// XXX check node types
|
||||
|
||||
if (xNewChild->getOwnerDocument() != getOwnerDocument()) {
|
||||
DOMException e;
|
||||
@@ -867,6 +882,11 @@ namespace DOM
|
||||
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
|
||||
throw e;
|
||||
}
|
||||
if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
|
||||
DOMException e;
|
||||
e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
|
||||
throw e;
|
||||
}
|
||||
|
||||
if( pOld->type == XML_ATTRIBUTE_NODE )
|
||||
{
|
||||
|
||||
@@ -154,6 +154,9 @@ namespace DOM
|
||||
// recursively create SAX events
|
||||
virtual void fastSaxify( Context& io_rContext );
|
||||
|
||||
// constrains child relationship between nodes based on type
|
||||
virtual bool IsChildTypeAllowed(NodeType const nodeType);
|
||||
|
||||
// ---- DOM interfaces
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user