| /************************************************************** |
| * |
| * 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. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_xmlsecurity.hxx" |
| |
| #include "xmldocumentwrapper_xmlsecimpl.hxx" |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| |
| #include <xmloff/attrlist.hxx> |
| #include "xmlelementwrapper_xmlsecimpl.hxx" |
| |
| //#include <malloc.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| /* |
| * Deleted by AF |
| #include <memory.h> |
| */ |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| |
| #ifndef INCLUDED_VECTOR |
| #include <vector> |
| #define INCLUDED_VECTOR |
| #endif |
| |
| #ifdef UNX |
| #define stricmp strcasecmp |
| #endif |
| |
| namespace cssu = com::sun::star::uno; |
| namespace cssl = com::sun::star::lang; |
| namespace cssxc = com::sun::star::xml::crypto; |
| namespace cssxcsax = com::sun::star::xml::csax; |
| namespace cssxs = com::sun::star::xml::sax; |
| namespace cssxw = com::sun::star::xml::wrapper; |
| |
| #define SERVICE_NAME "com.sun.star.xml.wrapper.XMLDocumentWrapper" |
| #define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.XMLDocumentWrapper_XmlSecImpl" |
| |
| #define STRXMLNS "xmlns" |
| |
| #define RTL_ASCII_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_ASCII_US |
| #define RTL_UTF8_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_UTF8 |
| |
| /* used by the recursiveDelete method */ |
| #define NODE_REMOVED 0 |
| #define NODE_NOTREMOVED 1 |
| #define NODE_STOPED 2 |
| |
| XMLDocumentWrapper_XmlSecImpl::XMLDocumentWrapper_XmlSecImpl( ) |
| { |
| saxHelper.startDocument(); |
| m_pDocument = saxHelper.getDocument(); |
| |
| /* |
| * creates the virtual root element |
| */ |
| saxHelper.startElement(rtl::OUString(RTL_UTF8_USTRINGPARAM( "root" )), cssu::Sequence<cssxcsax::XMLAttribute>()); |
| |
| m_pRootElement = saxHelper.getCurrentNode(); |
| m_pCurrentElement = m_pRootElement; |
| } |
| |
| XMLDocumentWrapper_XmlSecImpl::~XMLDocumentWrapper_XmlSecImpl() |
| { |
| saxHelper.endDocument(); |
| xmlFreeDoc(m_pDocument); |
| } |
| |
| void XMLDocumentWrapper_XmlSecImpl::getNextSAXEvent() |
| /****** XMLDocumentWrapper_XmlSecImpl/getNextSAXEvent ************************* |
| * |
| * NAME |
| * getNextSAXEvent -- Prepares the next SAX event to be manipulate |
| * |
| * SYNOPSIS |
| * getNextSAXEvent(); |
| * |
| * FUNCTION |
| * When converting the document into SAX events, this method is used to |
| * decide the next SAX event to be generated. |
| * Two member variables are checked to make the decision, the |
| * m_pCurrentElement and the m_nCurrentPosition. |
| * The m_pCurrentElement represents the node which have been covered, and |
| * the m_nCurrentPosition represents the event which have been sent. |
| * For example, suppose that the m_pCurrentElement |
| * points to element A, and the m_nCurrentPosition equals to |
| * NODEPOSITION_STARTELEMENT, then the next SAX event should be the |
| * endElement for element A if A has no child, or startElement for the |
| * first child element of element A otherwise. |
| * The m_nCurrentPosition can be one of following values: |
| * NODEPOSITION_STARTELEMENT for startElement; |
| * NODEPOSITION_ENDELEMENT for endElement; |
| * NODEPOSITION_NORMAL for other SAX events; |
| * |
| * INPUTS |
| * empty |
| * |
| * RESULT |
| * empty |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| OSL_ASSERT( m_pCurrentElement != NULL ); |
| |
| /* |
| * Get the next event through tree order. |
| * |
| * if the current event is a startElement, then the next |
| * event depends on whether or not the current node has |
| * children. |
| */ |
| if (m_nCurrentPosition == NODEPOSITION_STARTELEMENT) |
| { |
| /* |
| * If the current node has children, then its first child |
| * should be next current node, and the next event will be |
| * startElement or charaters(PI) based on that child's node |
| * type. Otherwise, the endElement of current node is the |
| * next event. |
| */ |
| if (m_pCurrentElement->children != NULL) |
| { |
| m_pCurrentElement = m_pCurrentElement->children; |
| m_nCurrentPosition |
| = (m_pCurrentElement->type == XML_ELEMENT_NODE)? |
| NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL; |
| } |
| else |
| { |
| m_nCurrentPosition = NODEPOSITION_ENDELEMENT; |
| } |
| } |
| /* |
| * if the current event is a not startElement, then the next |
| * event depends on whether or not the current node has |
| * following sibling. |
| */ |
| else if (m_nCurrentPosition == NODEPOSITION_ENDELEMENT || m_nCurrentPosition == NODEPOSITION_NORMAL) |
| { |
| xmlNodePtr pNextSibling = m_pCurrentElement->next; |
| |
| /* |
| * If the current node has following sibling, that sibling |
| * should be next current node, and the next event will be |
| * startElement or charaters(PI) based on that sibling's node |
| * type. Otherwise, the endElement of current node's parent |
| * becomes the next event. |
| */ |
| if (pNextSibling != NULL) |
| { |
| m_pCurrentElement = pNextSibling; |
| m_nCurrentPosition |
| = (m_pCurrentElement->type == XML_ELEMENT_NODE)? |
| NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL; |
| } |
| else |
| { |
| m_pCurrentElement = m_pCurrentElement->parent; |
| m_nCurrentPosition = NODEPOSITION_ENDELEMENT; |
| } |
| } |
| } |
| |
| void XMLDocumentWrapper_XmlSecImpl::sendStartElement( |
| const cssu::Reference< cssxs::XDocumentHandler >& xHandler, |
| const cssu::Reference< cssxs::XDocumentHandler >& xHandler2, |
| const xmlNodePtr pNode) const |
| throw (cssxs::SAXException) |
| /****** XMLDocumentWrapper_XmlSecImpl/sendStartElement ************************ |
| * |
| * NAME |
| * sendStartElement -- Constructs a startElement SAX event |
| * |
| * SYNOPSIS |
| * sendStartElement(xHandler, xHandler2, pNode); |
| * |
| * FUNCTION |
| * Used when converting the document into SAX event stream. |
| * This method constructs a startElement SAX event for a particular |
| * element, then calls the startElement methods of the XDocumentHandlers. |
| * |
| * INPUTS |
| * xHandler - the first XDocumentHandler interface to receive the |
| * startElement SAX event. It can be NULL. |
| * xHandler2 - the second XDocumentHandler interface to receive the |
| * startElement SAX event. It can't be NULL. |
| * pNode - the node on which the startElement should be generated. |
| * This node must be a element type. |
| * |
| * RESULT |
| * empty |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| SvXMLAttributeList* pAttributeList = new SvXMLAttributeList(); |
| cssu::Reference < cssxs::XAttributeList > xAttrList = cssu::Reference< cssxs::XAttributeList > (pAttributeList); |
| |
| xmlNsPtr pNsDef = pNode->nsDef; |
| |
| while (pNsDef != NULL) |
| { |
| const xmlChar* pNsPrefix = pNsDef->prefix; |
| const xmlChar* pNsHref = pNsDef->href; |
| |
| if (pNsDef->prefix == NULL) |
| { |
| pAttributeList->AddAttribute( |
| rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS )), |
| rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref ))); |
| } |
| else |
| { |
| pAttributeList->AddAttribute( |
| rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS )) |
| +rtl::OUString(RTL_UTF8_USTRINGPARAM( ":" )) |
| +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsPrefix )), |
| rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref ))); |
| } |
| |
| pNsDef = pNsDef->next; |
| } |
| |
| xmlAttrPtr pAttr = pNode->properties; |
| |
| while (pAttr != NULL) |
| { |
| const xmlChar* pAttrName = pAttr->name; |
| xmlNsPtr pAttrNs = pAttr->ns; |
| |
| rtl::OUString ouAttrName; |
| if (pAttrNs == NULL) |
| { |
| ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName )); |
| } |
| else |
| { |
| ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrNs->prefix)) |
| +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)":" )) |
| +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName )); |
| } |
| |
| pAttributeList->AddAttribute( |
| ouAttrName, |
| rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)(pAttr->children->content)))); |
| pAttr = pAttr->next; |
| } |
| |
| rtl::OString sNodeName = getNodeQName(pNode); |
| |
| if (xHandler.is()) |
| { |
| xHandler->startElement( |
| rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )), |
| xAttrList); |
| } |
| |
| xHandler2->startElement( |
| rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )), |
| xAttrList); |
| } |
| |
| void XMLDocumentWrapper_XmlSecImpl::sendEndElement( |
| const cssu::Reference< cssxs::XDocumentHandler >& xHandler, |
| const cssu::Reference< cssxs::XDocumentHandler >& xHandler2, |
| const xmlNodePtr pNode) const |
| throw (cssxs::SAXException) |
| /****** XMLDocumentWrapper_XmlSecImpl/sendEndElement ************************** |
| * |
| * NAME |
| * sendEndElement -- Constructs a endElement SAX event |
| * |
| * SYNOPSIS |
| * sendEndElement(xHandler, xHandler2, pNode); |
| * |
| * FUNCTION |
| * Used when converting the document into SAX event stream. |
| * This method constructs a endElement SAX event for a particular |
| * element, then calls the endElement methods of the XDocumentHandlers. |
| * |
| * INPUTS |
| * xHandler - the first XDocumentHandler interface to receive the |
| * endElement SAX event. It can be NULL. |
| * xHandler2 - the second XDocumentHandler interface to receive the |
| * endElement SAX event. It can't be NULL. |
| * pNode - the node on which the endElement should be generated. |
| * This node must be a element type. |
| * |
| * RESULT |
| * empty |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| rtl::OString sNodeName = getNodeQName(pNode); |
| |
| if (xHandler.is()) |
| { |
| xHandler->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) ))); |
| } |
| |
| xHandler2->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) ))); |
| } |
| |
| void XMLDocumentWrapper_XmlSecImpl::sendNode( |
| const cssu::Reference< cssxs::XDocumentHandler >& xHandler, |
| const cssu::Reference< cssxs::XDocumentHandler >& xHandler2, |
| const xmlNodePtr pNode) const |
| throw (cssxs::SAXException) |
| /****** XMLDocumentWrapper_XmlSecImpl/sendNode ******************************** |
| * |
| * NAME |
| * sendNode -- Constructs a characters SAX event or a |
| * processingInstruction SAX event |
| * |
| * SYNOPSIS |
| * sendNode(xHandler, xHandler2, pNode); |
| * |
| * FUNCTION |
| * Used when converting the document into SAX event stream. |
| * This method constructs a characters SAX event or a |
| * processingInstructionfor SAX event based on the type of a particular |
| * element, then calls the corresponding methods of the XDocumentHandlers. |
| * |
| * INPUTS |
| * xHandler - the first XDocumentHandler interface to receive the |
| * SAX event. It can be NULL. |
| * xHandler2 - the second XDocumentHandler interface to receive the |
| * SAX event. It can't be NULL. |
| * pNode - the node on which the endElement should be generated. |
| * If it is a text node, then a characters SAX event is |
| * generated; if it is a PI node, then a |
| * processingInstructionfor SAX event is generated. |
| * |
| * RESULT |
| * empty |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| xmlElementType type = pNode->type; |
| |
| if (type == XML_TEXT_NODE) |
| { |
| if (xHandler.is()) |
| { |
| xHandler->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); |
| } |
| |
| xHandler2->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); |
| } |
| else if (type == XML_PI_NODE) |
| { |
| if (xHandler.is()) |
| { |
| xHandler->processingInstruction( |
| rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )), |
| rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); |
| } |
| |
| xHandler2->processingInstruction( |
| rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )), |
| rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); |
| } |
| } |
| |
| rtl::OString XMLDocumentWrapper_XmlSecImpl::getNodeQName(const xmlNodePtr pNode) const |
| /****** XMLDocumentWrapper_XmlSecImpl/getNodeQName **************************** |
| * |
| * NAME |
| * getNodeQName -- Retrives the qualified name of a node |
| * |
| * SYNOPSIS |
| * name = getNodeQName(pNode); |
| * |
| * FUNCTION |
| * see NAME |
| * |
| * INPUTS |
| * pNode - the node whose name will be retrived |
| * |
| * RESULT |
| * name - the node's qualified name |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| rtl::OString sNodeName((const sal_Char*)pNode->name); |
| if (pNode->ns != NULL) |
| { |
| xmlNsPtr pNs = pNode->ns; |
| |
| if (pNs->prefix != NULL) |
| { |
| rtl::OString sPrefix((const sal_Char*)pNs->prefix); |
| sNodeName = sPrefix+rtl::OString(":")+sNodeName; |
| } |
| } |
| |
| return sNodeName; |
| } |
| |
| xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const cssu::Reference< cssxw::XXMLElementWrapper >& xXMLElement) const |
| /****** XMLDocumentWrapper_XmlSecImpl/checkElement **************************** |
| * |
| * NAME |
| * checkElement -- Retrives the node wrapped by an XXMLElementWrapper |
| * interface |
| * |
| * SYNOPSIS |
| * node = checkElement(xXMLElement); |
| * |
| * FUNCTION |
| * see NAME |
| * |
| * INPUTS |
| * xXMLElement - the XXMLElementWrapper interface wraping a node |
| * |
| * RESULT |
| * node - the node wrapped in the XXMLElementWrapper interface |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| xmlNodePtr rc = NULL; |
| |
| if (xXMLElement.is()) |
| { |
| cssu::Reference< cssl::XUnoTunnel > xNodTunnel( xXMLElement, cssu::UNO_QUERY ) ; |
| if( !xNodTunnel.is() ) |
| { |
| throw cssu::RuntimeException() ; |
| } |
| |
| XMLElementWrapper_XmlSecImpl* pElement |
| = reinterpret_cast<XMLElementWrapper_XmlSecImpl*>( |
| sal::static_int_cast<sal_uIntPtr>( |
| xNodTunnel->getSomething( |
| XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ))) ; |
| |
| if( pElement == NULL ) { |
| throw cssu::RuntimeException() ; |
| } |
| |
| rc = pElement->getNativeElement(); |
| } |
| |
| return rc; |
| } |
| |
| sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete( |
| const xmlNodePtr pNode) |
| /****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete ************************* |
| * |
| * NAME |
| * recursiveDelete -- Deletes a paticular node with its branch. |
| * |
| * SYNOPSIS |
| * result = recursiveDelete(pNode); |
| * |
| * FUNCTION |
| * Deletes a paticular node with its branch, while reserving the nodes |
| * (and their brance) listed in the m_aReservedNodes. |
| * The deletion process is preformed in the tree order, that is, a node |
| * is deleted after its previous sibling node is deleted, a parent node |
| * is deleted after its branch is deleted. |
| * During the deletion process when the m_pStopAtNode is reached, the |
| * progress is interrupted at once. |
| * |
| * INPUTS |
| * pNode - the node to be deleted |
| * |
| * RESULT |
| * result - the result of the deletion process, can be one of following |
| * values: |
| * NODE_STOPED - the process is interrupted by meeting the |
| * m_pStopAtNode |
| * NODE_NOTREMOVED - the pNode is not completely removed |
| * because there is its descendant in the |
| * m_aReservedNodes list |
| * NODE_REMOVED - the pNode and its branch are completely |
| * removed |
| * |
| * NOTES |
| * The node in the m_aReservedNodes list must be in the tree order, otherwise |
| * the result is unpredictable. |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| if (pNode == m_pStopAtNode) |
| { |
| return NODE_STOPED; |
| } |
| |
| if (pNode != m_pCurrentReservedNode) |
| { |
| xmlNodePtr pChild = pNode->children; |
| |
| xmlNodePtr pNextSibling; |
| bool bIsRemoved = true; |
| sal_Int32 nResult; |
| |
| while( pChild != NULL ) |
| { |
| pNextSibling = pChild->next; |
| nResult = recursiveDelete(pChild); |
| |
| switch (nResult) |
| { |
| case NODE_STOPED: |
| return NODE_STOPED; |
| case NODE_NOTREMOVED: |
| bIsRemoved = false; |
| break; |
| case NODE_REMOVED: |
| removeNode(pChild); |
| break; |
| default: |
| throw cssu::RuntimeException(); |
| } |
| |
| pChild = pNextSibling; |
| } |
| |
| if (pNode == m_pCurrentElement) |
| { |
| bIsRemoved = false; |
| } |
| |
| return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED; |
| } |
| else |
| { |
| getNextReservedNode(); |
| return NODE_NOTREMOVED; |
| } |
| } |
| |
| void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode() |
| /****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode ********************* |
| * |
| * NAME |
| * getNextReservedNode -- Highlights the next reserved node in the |
| * reserved node list |
| * |
| * SYNOPSIS |
| * getNextReservedNode(); |
| * |
| * FUNCTION |
| * The m_aReservedNodes array holds a node list, while the |
| * m_pCurrentReservedNode points to the one currently highlighted. |
| * This method is used to highlight the next node in the node list. |
| * This method is called at the time when the current highlighted node |
| * has been already processed, and the next node should be ready. |
| * |
| * INPUTS |
| * empty |
| * |
| * RESULT |
| * empty |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| if (m_nReservedNodeIndex < m_aReservedNodes.getLength()) |
| { |
| m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] ); |
| m_nReservedNodeIndex ++; |
| } |
| else |
| { |
| m_pCurrentReservedNode = NULL; |
| } |
| } |
| |
| void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const |
| /****** XMLDocumentWrapper_XmlSecImpl/removeNode ****************************** |
| * |
| * NAME |
| * removeNode -- Deletes a node with its branch unconditionaly |
| * |
| * SYNOPSIS |
| * removeNode( pNode ); |
| * |
| * FUNCTION |
| * Delete the node along with its branch from the document. |
| * |
| * INPUTS |
| * pNode - the node to be deleted |
| * |
| * RESULT |
| * empty |
| * |
| * HISTORY |
| * 05.01.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| /* you can't remove the current node */ |
| OSL_ASSERT( m_pCurrentElement != pNode ); |
| |
| xmlAttrPtr pAttr = pNode->properties; |
| |
| while (pAttr != NULL) |
| { |
| if (!stricmp((sal_Char*)pAttr->name,"id")) |
| { |
| xmlRemoveID(m_pDocument, pAttr); |
| } |
| |
| pAttr = pAttr->next; |
| } |
| |
| xmlUnlinkNode(pNode); |
| xmlFreeNode(pNode); |
| } |
| |
| void XMLDocumentWrapper_XmlSecImpl::buildIDAttr(xmlNodePtr pNode) const |
| /****** XMLDocumentWrapper_XmlSecImpl/buildIDAttr ***************************** |
| * |
| * NAME |
| * buildIDAttr -- build the ID attribute of a node |
| * |
| * SYNOPSIS |
| * buildIDAttr( pNode ); |
| * |
| * FUNCTION |
| * see NAME |
| * |
| * INPUTS |
| * pNode - the node whose id attribute will be built |
| * |
| * RESULT |
| * empty |
| * |
| * HISTORY |
| * 14.06.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| xmlAttrPtr idAttr = xmlHasProp( pNode, (const unsigned char *)"id" ); |
| if (idAttr == NULL) |
| { |
| idAttr = xmlHasProp( pNode, (const unsigned char *)"Id" ); |
| } |
| |
| if (idAttr != NULL) |
| { |
| xmlChar* idValue = xmlNodeListGetString( m_pDocument, idAttr->children, 1 ) ; |
| xmlAddID( NULL, m_pDocument, idValue, idAttr ); |
| } |
| } |
| |
| void XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(xmlNodePtr pNode) const |
| /****** XMLDocumentWrapper_XmlSecImpl/rebuildIDLink *************************** |
| * |
| * NAME |
| * rebuildIDLink -- rebuild the ID link for the branch |
| * |
| * SYNOPSIS |
| * rebuildIDLink( pNode ); |
| * |
| * FUNCTION |
| * see NAME |
| * |
| * INPUTS |
| * pNode - the node, from which the branch will be rebuilt |
| * |
| * RESULT |
| * empty |
| * |
| * HISTORY |
| * 14.06.2004 - implemented |
| * |
| * AUTHOR |
| * Michael Mi |
| * Email: michael.mi@sun.com |
| ******************************************************************************/ |
| { |
| if (pNode != NULL && pNode->type == XML_ELEMENT_NODE) |
| { |
| buildIDAttr( pNode ); |
| |
| xmlNodePtr child = pNode->children; |
| while (child != NULL) |
| { |
| rebuildIDLink(child); |
| child = child->next; |
| } |
| } |
| } |
| |
| /* XXMLDocumentWrapper */ |
| cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getCurrentElement( ) |
| throw (cssu::RuntimeException) |
| { |
| XMLElementWrapper_XmlSecImpl* pElement = new XMLElementWrapper_XmlSecImpl(m_pCurrentElement); |
| return (cssu::Reference< cssxw::XXMLElementWrapper >)pElement; |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setCurrentElement( const cssu::Reference< cssxw::XXMLElementWrapper >& element ) |
| throw (cssu::RuntimeException) |
| { |
| m_pCurrentElement = checkElement( element ); |
| saxHelper.setCurrentNode( m_pCurrentElement ); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::removeCurrentElement( ) |
| throw (cssu::RuntimeException) |
| { |
| OSL_ASSERT( m_pCurrentElement != NULL ); |
| |
| xmlNodePtr pOldCurrentElement = m_pCurrentElement; |
| |
| /* |
| * pop the top node in the parser context's |
| * nodeTab stack, then the parent of that node will |
| * automatically become the new stack top, and |
| * the current node as well. |
| */ |
| saxHelper.endElement( |
| rtl::OUString( |
| RTL_UTF8_USTRINGPARAM ( |
| (sal_Char*)(pOldCurrentElement->name) |
| ))); |
| m_pCurrentElement = saxHelper.getCurrentNode(); |
| |
| /* |
| * remove the node |
| */ |
| removeNode(pOldCurrentElement); |
| } |
| |
| sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrent( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) |
| throw (cssu::RuntimeException) |
| { |
| xmlNodePtr pNode = checkElement(node); |
| return (pNode == m_pCurrentElement); |
| } |
| |
| sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrentElementEmpty( ) |
| throw (cssu::RuntimeException) |
| { |
| sal_Bool rc = sal_False; |
| |
| if (m_pCurrentElement->children == NULL) |
| { |
| rc = sal_True; |
| } |
| |
| return rc; |
| } |
| |
| rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getNodeName( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) |
| throw (cssu::RuntimeException) |
| { |
| xmlNodePtr pNode = checkElement(node); |
| return rtl::OUString(RTL_UTF8_USTRINGPARAM ( (sal_Char*)pNode->name )); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::clearUselessData( |
| const cssu::Reference< cssxw::XXMLElementWrapper >& node, |
| const cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >& reservedDescendants, |
| const cssu::Reference< cssxw::XXMLElementWrapper >& stopAtNode ) |
| throw (cssu::RuntimeException) |
| { |
| xmlNodePtr pTargetNode = checkElement(node); |
| |
| m_pStopAtNode = checkElement(stopAtNode); |
| m_aReservedNodes = reservedDescendants; |
| m_nReservedNodeIndex = 0; |
| |
| getNextReservedNode(); |
| |
| recursiveDelete(pTargetNode); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::collapse( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) |
| throw (cssu::RuntimeException) |
| { |
| xmlNodePtr pTargetNode = checkElement(node); |
| xmlNodePtr pParent; |
| |
| while (pTargetNode != NULL) |
| { |
| if (pTargetNode->children != NULL || pTargetNode == m_pCurrentElement) |
| { |
| break; |
| } |
| |
| pParent = pTargetNode->parent; |
| removeNode(pTargetNode); |
| pTargetNode = pParent; |
| } |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::getTree( const cssu::Reference< cssxs::XDocumentHandler >& handler ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| if (m_pRootElement != NULL) |
| { |
| xmlNodePtr pTempCurrentElement = m_pCurrentElement; |
| sal_Int32 nTempCurrentPosition = m_nCurrentPosition; |
| |
| m_pCurrentElement = m_pRootElement; |
| |
| m_nCurrentPosition = NODEPOSITION_STARTELEMENT; |
| cssu::Reference< cssxs::XDocumentHandler > xHandler = handler; |
| |
| while(true) |
| { |
| switch (m_nCurrentPosition) |
| { |
| case NODEPOSITION_STARTELEMENT: |
| sendStartElement(NULL, xHandler, m_pCurrentElement); |
| break; |
| case NODEPOSITION_ENDELEMENT: |
| sendEndElement(NULL, xHandler, m_pCurrentElement); |
| break; |
| case NODEPOSITION_NORMAL: |
| sendNode(NULL, xHandler, m_pCurrentElement); |
| break; |
| } |
| |
| if ( (m_pCurrentElement == m_pRootElement) && (m_nCurrentPosition == NODEPOSITION_ENDELEMENT )) |
| { |
| break; |
| } |
| |
| getNextSAXEvent(); |
| } |
| |
| m_pCurrentElement = pTempCurrentElement; |
| m_nCurrentPosition = nTempCurrentPosition; |
| } |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::generateSAXEvents( |
| const cssu::Reference< cssxs::XDocumentHandler >& handler, |
| const cssu::Reference< cssxs::XDocumentHandler >& xEventKeeperHandler, |
| const cssu::Reference< cssxw::XXMLElementWrapper >& startNode, |
| const cssu::Reference< cssxw::XXMLElementWrapper >& endNode ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| /* |
| * The first SAX event is the startElement of the startNode |
| * element. |
| */ |
| bool bHasCurrentElementChild = (m_pCurrentElement->children != NULL); |
| |
| xmlNodePtr pTempCurrentElement = m_pCurrentElement; |
| |
| m_pCurrentElement = checkElement(startNode); |
| |
| if (m_pCurrentElement->type == XML_ELEMENT_NODE) |
| { |
| m_nCurrentPosition = NODEPOSITION_STARTELEMENT; |
| } |
| else |
| { |
| m_nCurrentPosition = NODEPOSITION_NORMAL; |
| } |
| |
| xmlNodePtr pEndNode = checkElement(endNode); |
| |
| cssu::Reference < cssxc::sax::XSAXEventKeeper > xSAXEventKeeper( xEventKeeperHandler, cssu::UNO_QUERY ); |
| |
| cssu::Reference< cssxs::XDocumentHandler > xHandler = handler; |
| |
| while(true) |
| { |
| switch (m_nCurrentPosition) |
| { |
| case NODEPOSITION_STARTELEMENT: |
| sendStartElement(xHandler, xEventKeeperHandler, m_pCurrentElement); |
| break; |
| case NODEPOSITION_ENDELEMENT: |
| sendEndElement(xHandler, xEventKeeperHandler, m_pCurrentElement); |
| break; |
| case NODEPOSITION_NORMAL: |
| sendNode(xHandler, xEventKeeperHandler, m_pCurrentElement); |
| break; |
| default: |
| throw cssu::RuntimeException(); |
| } |
| |
| if (xSAXEventKeeper->isBlocking()) |
| { |
| xHandler = NULL; |
| } |
| |
| if (pEndNode == NULL && |
| ((bHasCurrentElementChild && m_pCurrentElement == xmlGetLastChild(pTempCurrentElement) && m_nCurrentPosition != NODEPOSITION_STARTELEMENT) || |
| (!bHasCurrentElementChild && m_pCurrentElement == pTempCurrentElement && m_nCurrentPosition == NODEPOSITION_STARTELEMENT))) |
| { |
| break; |
| } |
| |
| getNextSAXEvent(); |
| |
| /* |
| * If there is an end point specified, then check whether |
| * the current node equals to the end point. If so, stop |
| * generating. |
| */ |
| if (pEndNode != NULL && m_pCurrentElement == pEndNode) |
| { |
| break; |
| } |
| } |
| |
| m_pCurrentElement = pTempCurrentElement; |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::rebuildIDLink( |
| const com::sun::star::uno::Reference< com::sun::star::xml::wrapper::XXMLElementWrapper >& node ) |
| throw (com::sun::star::uno::RuntimeException) |
| { |
| xmlNodePtr pNode = checkElement( node ); |
| rebuildIDLink(pNode); |
| } |
| |
| |
| /* cssxs::XDocumentHandler */ |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument( ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument( ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startElement( const rtl::OUString& aName, const cssu::Reference< cssxs::XAttributeList >& xAttribs ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| sal_Int32 nLength = xAttribs->getLength(); |
| cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength); |
| |
| for (int i = 0; i < nLength; ++i) |
| { |
| aAttributes[i].sName = xAttribs->getNameByIndex((short)i); |
| aAttributes[i].sValue =xAttribs->getValueByIndex((short)i); |
| } |
| |
| _startElement(aName, aAttributes); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const rtl::OUString& aName ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| saxHelper.endElement(aName); |
| m_pCurrentElement = saxHelper.getCurrentNode(); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const rtl::OUString& aChars ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| saxHelper.characters(aChars); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| saxHelper.ignorableWhitespace(aWhitespaces); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| saxHelper.processingInstruction(aTarget, aData); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| saxHelper.setDocumentLocator(xLocator); |
| } |
| |
| /* XCompressedDocumentHandler */ |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startDocument( ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endDocument( ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startElement( const rtl::OUString& aName, const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| saxHelper.startElement(aName, aAttributes); |
| m_pCurrentElement = saxHelper.getCurrentNode(); |
| |
| buildIDAttr( m_pCurrentElement ); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endElement( const rtl::OUString& aName ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| endElement( aName ); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_characters( const rtl::OUString& aChars ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| characters( aChars ); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_ignorableWhitespace( const rtl::OUString& aWhitespaces ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| ignorableWhitespace( aWhitespaces ); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| processingInstruction( aTarget, aData ); |
| } |
| |
| void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_setDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const rtl::OUString& /*publicId*/, const rtl::OUString& /*systemId*/ ) |
| throw (cssxs::SAXException, cssu::RuntimeException) |
| { |
| } |
| |
| rtl::OUString XMLDocumentWrapper_XmlSecImpl_getImplementationName () |
| throw (cssu::RuntimeException) |
| { |
| return rtl::OUString ( RTL_ASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) ); |
| } |
| |
| sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl_supportsService( const rtl::OUString& ServiceName ) |
| throw (cssu::RuntimeException) |
| { |
| return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME )); |
| } |
| |
| cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames( ) |
| throw (cssu::RuntimeException) |
| { |
| cssu::Sequence < rtl::OUString > aRet(1); |
| rtl::OUString* pArray = aRet.getArray(); |
| pArray[0] = rtl::OUString ( RTL_ASCII_USTRINGPARAM ( SERVICE_NAME ) ); |
| return aRet; |
| } |
| #undef SERVICE_NAME |
| |
| cssu::Reference< cssu::XInterface > SAL_CALL XMLDocumentWrapper_XmlSecImpl_createInstance( |
| const cssu::Reference< cssl::XMultiServiceFactory > &) |
| throw( cssu::Exception ) |
| { |
| return (cppu::OWeakObject*) new XMLDocumentWrapper_XmlSecImpl( ); |
| } |
| |
| /* XServiceInfo */ |
| rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName( ) |
| throw (cssu::RuntimeException) |
| { |
| return XMLDocumentWrapper_XmlSecImpl_getImplementationName(); |
| } |
| sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const rtl::OUString& rServiceName ) |
| throw (cssu::RuntimeException) |
| { |
| return XMLDocumentWrapper_XmlSecImpl_supportsService( rServiceName ); |
| } |
| cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames( ) |
| throw (cssu::RuntimeException) |
| { |
| return XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames(); |
| } |
| |