1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmlsecurity.hxx" 30 31 #include "xmldocumentwrapper_xmlsecimpl.hxx" 32 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 33 34 #include <xmloff/attrlist.hxx> 35 #include "xmlelementwrapper_xmlsecimpl.hxx" 36 37 //#include <malloc.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 42 /* 43 * Deleted by AF 44 #include <memory.h> 45 */ 46 47 #include <sys/types.h> 48 #include <sys/stat.h> 49 50 #ifndef INCLUDED_VECTOR 51 #include <vector> 52 #define INCLUDED_VECTOR 53 #endif 54 55 #ifdef UNX 56 #define stricmp strcasecmp 57 #endif 58 59 namespace cssu = com::sun::star::uno; 60 namespace cssl = com::sun::star::lang; 61 namespace cssxc = com::sun::star::xml::crypto; 62 namespace cssxcsax = com::sun::star::xml::csax; 63 namespace cssxs = com::sun::star::xml::sax; 64 namespace cssxw = com::sun::star::xml::wrapper; 65 66 #define SERVICE_NAME "com.sun.star.xml.wrapper.XMLDocumentWrapper" 67 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.XMLDocumentWrapper_XmlSecImpl" 68 69 #define STRXMLNS "xmlns" 70 71 #define RTL_ASCII_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_ASCII_US 72 #define RTL_UTF8_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_UTF8 73 74 /* used by the recursiveDelete method */ 75 #define NODE_REMOVED 0 76 #define NODE_NOTREMOVED 1 77 #define NODE_STOPED 2 78 79 XMLDocumentWrapper_XmlSecImpl::XMLDocumentWrapper_XmlSecImpl( ) 80 { 81 saxHelper.startDocument(); 82 m_pDocument = saxHelper.getDocument(); 83 84 /* 85 * creates the virtual root element 86 */ 87 saxHelper.startElement(rtl::OUString(RTL_UTF8_USTRINGPARAM( "root" )), cssu::Sequence<cssxcsax::XMLAttribute>()); 88 89 m_pRootElement = saxHelper.getCurrentNode(); 90 m_pCurrentElement = m_pRootElement; 91 } 92 93 XMLDocumentWrapper_XmlSecImpl::~XMLDocumentWrapper_XmlSecImpl() 94 { 95 saxHelper.endDocument(); 96 xmlFreeDoc(m_pDocument); 97 } 98 99 void XMLDocumentWrapper_XmlSecImpl::getNextSAXEvent() 100 /****** XMLDocumentWrapper_XmlSecImpl/getNextSAXEvent ************************* 101 * 102 * NAME 103 * getNextSAXEvent -- Prepares the next SAX event to be manipulate 104 * 105 * SYNOPSIS 106 * getNextSAXEvent(); 107 * 108 * FUNCTION 109 * When converting the document into SAX events, this method is used to 110 * decide the next SAX event to be generated. 111 * Two member variables are checked to make the decision, the 112 * m_pCurrentElement and the m_nCurrentPosition. 113 * The m_pCurrentElement represents the node which have been covered, and 114 * the m_nCurrentPosition represents the event which have been sent. 115 * For example, suppose that the m_pCurrentElement 116 * points to element A, and the m_nCurrentPosition equals to 117 * NODEPOSITION_STARTELEMENT, then the next SAX event should be the 118 * endElement for element A if A has no child, or startElement for the 119 * first child element of element A otherwise. 120 * The m_nCurrentPosition can be one of following values: 121 * NODEPOSITION_STARTELEMENT for startElement; 122 * NODEPOSITION_ENDELEMENT for endElement; 123 * NODEPOSITION_NORMAL for other SAX events; 124 * 125 * INPUTS 126 * empty 127 * 128 * RESULT 129 * empty 130 * 131 * HISTORY 132 * 05.01.2004 - implemented 133 * 134 * AUTHOR 135 * Michael Mi 136 * Email: michael.mi@sun.com 137 ******************************************************************************/ 138 { 139 OSL_ASSERT( m_pCurrentElement != NULL ); 140 141 /* 142 * Get the next event through tree order. 143 * 144 * if the current event is a startElement, then the next 145 * event depends on whether or not the current node has 146 * children. 147 */ 148 if (m_nCurrentPosition == NODEPOSITION_STARTELEMENT) 149 { 150 /* 151 * If the current node has children, then its first child 152 * should be next current node, and the next event will be 153 * startElement or charaters(PI) based on that child's node 154 * type. Otherwise, the endElement of current node is the 155 * next event. 156 */ 157 if (m_pCurrentElement->children != NULL) 158 { 159 m_pCurrentElement = m_pCurrentElement->children; 160 m_nCurrentPosition 161 = (m_pCurrentElement->type == XML_ELEMENT_NODE)? 162 NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL; 163 } 164 else 165 { 166 m_nCurrentPosition = NODEPOSITION_ENDELEMENT; 167 } 168 } 169 /* 170 * if the current event is a not startElement, then the next 171 * event depends on whether or not the current node has 172 * following sibling. 173 */ 174 else if (m_nCurrentPosition == NODEPOSITION_ENDELEMENT || m_nCurrentPosition == NODEPOSITION_NORMAL) 175 { 176 xmlNodePtr pNextSibling = m_pCurrentElement->next; 177 178 /* 179 * If the current node has following sibling, that sibling 180 * should be next current node, and the next event will be 181 * startElement or charaters(PI) based on that sibling's node 182 * type. Otherwise, the endElement of current node's parent 183 * becomes the next event. 184 */ 185 if (pNextSibling != NULL) 186 { 187 m_pCurrentElement = pNextSibling; 188 m_nCurrentPosition 189 = (m_pCurrentElement->type == XML_ELEMENT_NODE)? 190 NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL; 191 } 192 else 193 { 194 m_pCurrentElement = m_pCurrentElement->parent; 195 m_nCurrentPosition = NODEPOSITION_ENDELEMENT; 196 } 197 } 198 } 199 200 void XMLDocumentWrapper_XmlSecImpl::sendStartElement( 201 const cssu::Reference< cssxs::XDocumentHandler >& xHandler, 202 const cssu::Reference< cssxs::XDocumentHandler >& xHandler2, 203 const xmlNodePtr pNode) const 204 throw (cssxs::SAXException) 205 /****** XMLDocumentWrapper_XmlSecImpl/sendStartElement ************************ 206 * 207 * NAME 208 * sendStartElement -- Constructs a startElement SAX event 209 * 210 * SYNOPSIS 211 * sendStartElement(xHandler, xHandler2, pNode); 212 * 213 * FUNCTION 214 * Used when converting the document into SAX event stream. 215 * This method constructs a startElement SAX event for a particular 216 * element, then calls the startElement methods of the XDocumentHandlers. 217 * 218 * INPUTS 219 * xHandler - the first XDocumentHandler interface to receive the 220 * startElement SAX event. It can be NULL. 221 * xHandler2 - the second XDocumentHandler interface to receive the 222 * startElement SAX event. It can't be NULL. 223 * pNode - the node on which the startElement should be generated. 224 * This node must be a element type. 225 * 226 * RESULT 227 * empty 228 * 229 * HISTORY 230 * 05.01.2004 - implemented 231 * 232 * AUTHOR 233 * Michael Mi 234 * Email: michael.mi@sun.com 235 ******************************************************************************/ 236 { 237 SvXMLAttributeList* pAttributeList = new SvXMLAttributeList(); 238 cssu::Reference < cssxs::XAttributeList > xAttrList = cssu::Reference< cssxs::XAttributeList > (pAttributeList); 239 240 xmlNsPtr pNsDef = pNode->nsDef; 241 242 while (pNsDef != NULL) 243 { 244 const xmlChar* pNsPrefix = pNsDef->prefix; 245 const xmlChar* pNsHref = pNsDef->href; 246 247 if (pNsDef->prefix == NULL) 248 { 249 pAttributeList->AddAttribute( 250 rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS )), 251 rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref ))); 252 } 253 else 254 { 255 pAttributeList->AddAttribute( 256 rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS )) 257 +rtl::OUString(RTL_UTF8_USTRINGPARAM( ":" )) 258 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsPrefix )), 259 rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref ))); 260 } 261 262 pNsDef = pNsDef->next; 263 } 264 265 xmlAttrPtr pAttr = pNode->properties; 266 267 while (pAttr != NULL) 268 { 269 const xmlChar* pAttrName = pAttr->name; 270 xmlNsPtr pAttrNs = pAttr->ns; 271 272 rtl::OUString ouAttrName; 273 if (pAttrNs == NULL) 274 { 275 ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName )); 276 } 277 else 278 { 279 ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrNs->prefix)) 280 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)":" )) 281 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName )); 282 } 283 284 pAttributeList->AddAttribute( 285 ouAttrName, 286 rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)(pAttr->children->content)))); 287 pAttr = pAttr->next; 288 } 289 290 rtl::OString sNodeName = getNodeQName(pNode); 291 292 if (xHandler.is()) 293 { 294 xHandler->startElement( 295 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )), 296 xAttrList); 297 } 298 299 xHandler2->startElement( 300 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )), 301 xAttrList); 302 } 303 304 void XMLDocumentWrapper_XmlSecImpl::sendEndElement( 305 const cssu::Reference< cssxs::XDocumentHandler >& xHandler, 306 const cssu::Reference< cssxs::XDocumentHandler >& xHandler2, 307 const xmlNodePtr pNode) const 308 throw (cssxs::SAXException) 309 /****** XMLDocumentWrapper_XmlSecImpl/sendEndElement ************************** 310 * 311 * NAME 312 * sendEndElement -- Constructs a endElement SAX event 313 * 314 * SYNOPSIS 315 * sendEndElement(xHandler, xHandler2, pNode); 316 * 317 * FUNCTION 318 * Used when converting the document into SAX event stream. 319 * This method constructs a endElement SAX event for a particular 320 * element, then calls the endElement methods of the XDocumentHandlers. 321 * 322 * INPUTS 323 * xHandler - the first XDocumentHandler interface to receive the 324 * endElement SAX event. It can be NULL. 325 * xHandler2 - the second XDocumentHandler interface to receive the 326 * endElement SAX event. It can't be NULL. 327 * pNode - the node on which the endElement should be generated. 328 * This node must be a element type. 329 * 330 * RESULT 331 * empty 332 * 333 * HISTORY 334 * 05.01.2004 - implemented 335 * 336 * AUTHOR 337 * Michael Mi 338 * Email: michael.mi@sun.com 339 ******************************************************************************/ 340 { 341 rtl::OString sNodeName = getNodeQName(pNode); 342 343 if (xHandler.is()) 344 { 345 xHandler->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) ))); 346 } 347 348 xHandler2->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) ))); 349 } 350 351 void XMLDocumentWrapper_XmlSecImpl::sendNode( 352 const cssu::Reference< cssxs::XDocumentHandler >& xHandler, 353 const cssu::Reference< cssxs::XDocumentHandler >& xHandler2, 354 const xmlNodePtr pNode) const 355 throw (cssxs::SAXException) 356 /****** XMLDocumentWrapper_XmlSecImpl/sendNode ******************************** 357 * 358 * NAME 359 * sendNode -- Constructs a characters SAX event or a 360 * processingInstruction SAX event 361 * 362 * SYNOPSIS 363 * sendNode(xHandler, xHandler2, pNode); 364 * 365 * FUNCTION 366 * Used when converting the document into SAX event stream. 367 * This method constructs a characters SAX event or a 368 * processingInstructionfor SAX event based on the type of a particular 369 * element, then calls the corresponding methods of the XDocumentHandlers. 370 * 371 * INPUTS 372 * xHandler - the first XDocumentHandler interface to receive the 373 * SAX event. It can be NULL. 374 * xHandler2 - the second XDocumentHandler interface to receive the 375 * SAX event. It can't be NULL. 376 * pNode - the node on which the endElement should be generated. 377 * If it is a text node, then a characters SAX event is 378 * generated; if it is a PI node, then a 379 * processingInstructionfor SAX event is generated. 380 * 381 * RESULT 382 * empty 383 * 384 * HISTORY 385 * 05.01.2004 - implemented 386 * 387 * AUTHOR 388 * Michael Mi 389 * Email: michael.mi@sun.com 390 ******************************************************************************/ 391 { 392 xmlElementType type = pNode->type; 393 394 if (type == XML_TEXT_NODE) 395 { 396 if (xHandler.is()) 397 { 398 xHandler->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); 399 } 400 401 xHandler2->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); 402 } 403 else if (type == XML_PI_NODE) 404 { 405 if (xHandler.is()) 406 { 407 xHandler->processingInstruction( 408 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )), 409 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); 410 } 411 412 xHandler2->processingInstruction( 413 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )), 414 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); 415 } 416 } 417 418 rtl::OString XMLDocumentWrapper_XmlSecImpl::getNodeQName(const xmlNodePtr pNode) const 419 /****** XMLDocumentWrapper_XmlSecImpl/getNodeQName **************************** 420 * 421 * NAME 422 * getNodeQName -- Retrives the qualified name of a node 423 * 424 * SYNOPSIS 425 * name = getNodeQName(pNode); 426 * 427 * FUNCTION 428 * see NAME 429 * 430 * INPUTS 431 * pNode - the node whose name will be retrived 432 * 433 * RESULT 434 * name - the node's qualified name 435 * 436 * HISTORY 437 * 05.01.2004 - implemented 438 * 439 * AUTHOR 440 * Michael Mi 441 * Email: michael.mi@sun.com 442 ******************************************************************************/ 443 { 444 rtl::OString sNodeName((const sal_Char*)pNode->name); 445 if (pNode->ns != NULL) 446 { 447 xmlNsPtr pNs = pNode->ns; 448 449 if (pNs->prefix != NULL) 450 { 451 rtl::OString sPrefix((const sal_Char*)pNs->prefix); 452 sNodeName = sPrefix+rtl::OString(":")+sNodeName; 453 } 454 } 455 456 return sNodeName; 457 } 458 459 xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const cssu::Reference< cssxw::XXMLElementWrapper >& xXMLElement) const 460 /****** XMLDocumentWrapper_XmlSecImpl/checkElement **************************** 461 * 462 * NAME 463 * checkElement -- Retrives the node wrapped by an XXMLElementWrapper 464 * interface 465 * 466 * SYNOPSIS 467 * node = checkElement(xXMLElement); 468 * 469 * FUNCTION 470 * see NAME 471 * 472 * INPUTS 473 * xXMLElement - the XXMLElementWrapper interface wraping a node 474 * 475 * RESULT 476 * node - the node wrapped in the XXMLElementWrapper interface 477 * 478 * HISTORY 479 * 05.01.2004 - implemented 480 * 481 * AUTHOR 482 * Michael Mi 483 * Email: michael.mi@sun.com 484 ******************************************************************************/ 485 { 486 xmlNodePtr rc = NULL; 487 488 if (xXMLElement.is()) 489 { 490 cssu::Reference< cssl::XUnoTunnel > xNodTunnel( xXMLElement, cssu::UNO_QUERY ) ; 491 if( !xNodTunnel.is() ) 492 { 493 throw cssu::RuntimeException() ; 494 } 495 496 XMLElementWrapper_XmlSecImpl* pElement 497 = reinterpret_cast<XMLElementWrapper_XmlSecImpl*>( 498 sal::static_int_cast<sal_uIntPtr>( 499 xNodTunnel->getSomething( 500 XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ))) ; 501 502 if( pElement == NULL ) { 503 throw cssu::RuntimeException() ; 504 } 505 506 rc = pElement->getNativeElement(); 507 } 508 509 return rc; 510 } 511 512 sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete( 513 const xmlNodePtr pNode) 514 /****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete ************************* 515 * 516 * NAME 517 * recursiveDelete -- Deletes a paticular node with its branch. 518 * 519 * SYNOPSIS 520 * result = recursiveDelete(pNode); 521 * 522 * FUNCTION 523 * Deletes a paticular node with its branch, while reserving the nodes 524 * (and their brance) listed in the m_aReservedNodes. 525 * The deletion process is preformed in the tree order, that is, a node 526 * is deleted after its previous sibling node is deleted, a parent node 527 * is deleted after its branch is deleted. 528 * During the deletion process when the m_pStopAtNode is reached, the 529 * progress is interrupted at once. 530 * 531 * INPUTS 532 * pNode - the node to be deleted 533 * 534 * RESULT 535 * result - the result of the deletion process, can be one of following 536 * values: 537 * NODE_STOPED - the process is interrupted by meeting the 538 * m_pStopAtNode 539 * NODE_NOTREMOVED - the pNode is not completely removed 540 * because there is its descendant in the 541 * m_aReservedNodes list 542 * NODE_REMOVED - the pNode and its branch are completely 543 * removed 544 * 545 * NOTES 546 * The node in the m_aReservedNodes list must be in the tree order, otherwise 547 * the result is unpredictable. 548 * 549 * HISTORY 550 * 05.01.2004 - implemented 551 * 552 * AUTHOR 553 * Michael Mi 554 * Email: michael.mi@sun.com 555 ******************************************************************************/ 556 { 557 if (pNode == m_pStopAtNode) 558 { 559 return NODE_STOPED; 560 } 561 562 if (pNode != m_pCurrentReservedNode) 563 { 564 xmlNodePtr pChild = pNode->children; 565 566 xmlNodePtr pNextSibling; 567 bool bIsRemoved = true; 568 sal_Int32 nResult; 569 570 while( pChild != NULL ) 571 { 572 pNextSibling = pChild->next; 573 nResult = recursiveDelete(pChild); 574 575 switch (nResult) 576 { 577 case NODE_STOPED: 578 return NODE_STOPED; 579 case NODE_NOTREMOVED: 580 bIsRemoved = false; 581 break; 582 case NODE_REMOVED: 583 removeNode(pChild); 584 break; 585 default: 586 throw cssu::RuntimeException(); 587 } 588 589 pChild = pNextSibling; 590 } 591 592 if (pNode == m_pCurrentElement) 593 { 594 bIsRemoved = false; 595 } 596 597 return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED; 598 } 599 else 600 { 601 getNextReservedNode(); 602 return NODE_NOTREMOVED; 603 } 604 } 605 606 void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode() 607 /****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode ********************* 608 * 609 * NAME 610 * getNextReservedNode -- Highlights the next reserved node in the 611 * reserved node list 612 * 613 * SYNOPSIS 614 * getNextReservedNode(); 615 * 616 * FUNCTION 617 * The m_aReservedNodes array holds a node list, while the 618 * m_pCurrentReservedNode points to the one currently highlighted. 619 * This method is used to highlight the next node in the node list. 620 * This method is called at the time when the current highlighted node 621 * has been already processed, and the next node should be ready. 622 * 623 * INPUTS 624 * empty 625 * 626 * RESULT 627 * empty 628 * 629 * HISTORY 630 * 05.01.2004 - implemented 631 * 632 * AUTHOR 633 * Michael Mi 634 * Email: michael.mi@sun.com 635 ******************************************************************************/ 636 { 637 if (m_nReservedNodeIndex < m_aReservedNodes.getLength()) 638 { 639 m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] ); 640 m_nReservedNodeIndex ++; 641 } 642 else 643 { 644 m_pCurrentReservedNode = NULL; 645 } 646 } 647 648 void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const 649 /****** XMLDocumentWrapper_XmlSecImpl/removeNode ****************************** 650 * 651 * NAME 652 * removeNode -- Deletes a node with its branch unconditionaly 653 * 654 * SYNOPSIS 655 * removeNode( pNode ); 656 * 657 * FUNCTION 658 * Delete the node along with its branch from the document. 659 * 660 * INPUTS 661 * pNode - the node to be deleted 662 * 663 * RESULT 664 * empty 665 * 666 * HISTORY 667 * 05.01.2004 - implemented 668 * 669 * AUTHOR 670 * Michael Mi 671 * Email: michael.mi@sun.com 672 ******************************************************************************/ 673 { 674 /* you can't remove the current node */ 675 OSL_ASSERT( m_pCurrentElement != pNode ); 676 677 xmlAttrPtr pAttr = pNode->properties; 678 679 while (pAttr != NULL) 680 { 681 if (!stricmp((sal_Char*)pAttr->name,"id")) 682 { 683 xmlRemoveID(m_pDocument, pAttr); 684 } 685 686 pAttr = pAttr->next; 687 } 688 689 xmlUnlinkNode(pNode); 690 xmlFreeNode(pNode); 691 } 692 693 void XMLDocumentWrapper_XmlSecImpl::buildIDAttr(xmlNodePtr pNode) const 694 /****** XMLDocumentWrapper_XmlSecImpl/buildIDAttr ***************************** 695 * 696 * NAME 697 * buildIDAttr -- build the ID attribute of a node 698 * 699 * SYNOPSIS 700 * buildIDAttr( pNode ); 701 * 702 * FUNCTION 703 * see NAME 704 * 705 * INPUTS 706 * pNode - the node whose id attribute will be built 707 * 708 * RESULT 709 * empty 710 * 711 * HISTORY 712 * 14.06.2004 - implemented 713 * 714 * AUTHOR 715 * Michael Mi 716 * Email: michael.mi@sun.com 717 ******************************************************************************/ 718 { 719 xmlAttrPtr idAttr = xmlHasProp( pNode, (const unsigned char *)"id" ); 720 if (idAttr == NULL) 721 { 722 idAttr = xmlHasProp( pNode, (const unsigned char *)"Id" ); 723 } 724 725 if (idAttr != NULL) 726 { 727 xmlChar* idValue = xmlNodeListGetString( m_pDocument, idAttr->children, 1 ) ; 728 xmlAddID( NULL, m_pDocument, idValue, idAttr ); 729 } 730 } 731 732 void XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(xmlNodePtr pNode) const 733 /****** XMLDocumentWrapper_XmlSecImpl/rebuildIDLink *************************** 734 * 735 * NAME 736 * rebuildIDLink -- rebuild the ID link for the branch 737 * 738 * SYNOPSIS 739 * rebuildIDLink( pNode ); 740 * 741 * FUNCTION 742 * see NAME 743 * 744 * INPUTS 745 * pNode - the node, from which the branch will be rebuilt 746 * 747 * RESULT 748 * empty 749 * 750 * HISTORY 751 * 14.06.2004 - implemented 752 * 753 * AUTHOR 754 * Michael Mi 755 * Email: michael.mi@sun.com 756 ******************************************************************************/ 757 { 758 if (pNode != NULL && pNode->type == XML_ELEMENT_NODE) 759 { 760 buildIDAttr( pNode ); 761 762 xmlNodePtr child = pNode->children; 763 while (child != NULL) 764 { 765 rebuildIDLink(child); 766 child = child->next; 767 } 768 } 769 } 770 771 /* XXMLDocumentWrapper */ 772 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getCurrentElement( ) 773 throw (cssu::RuntimeException) 774 { 775 XMLElementWrapper_XmlSecImpl* pElement = new XMLElementWrapper_XmlSecImpl(m_pCurrentElement); 776 return (cssu::Reference< cssxw::XXMLElementWrapper >)pElement; 777 } 778 779 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setCurrentElement( const cssu::Reference< cssxw::XXMLElementWrapper >& element ) 780 throw (cssu::RuntimeException) 781 { 782 m_pCurrentElement = checkElement( element ); 783 saxHelper.setCurrentNode( m_pCurrentElement ); 784 } 785 786 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::removeCurrentElement( ) 787 throw (cssu::RuntimeException) 788 { 789 OSL_ASSERT( m_pCurrentElement != NULL ); 790 791 xmlNodePtr pOldCurrentElement = m_pCurrentElement; 792 793 /* 794 * pop the top node in the parser context's 795 * nodeTab stack, then the parent of that node will 796 * automatically become the new stack top, and 797 * the current node as well. 798 */ 799 saxHelper.endElement( 800 rtl::OUString( 801 RTL_UTF8_USTRINGPARAM ( 802 (sal_Char*)(pOldCurrentElement->name) 803 ))); 804 m_pCurrentElement = saxHelper.getCurrentNode(); 805 806 /* 807 * remove the node 808 */ 809 removeNode(pOldCurrentElement); 810 } 811 812 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrent( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) 813 throw (cssu::RuntimeException) 814 { 815 xmlNodePtr pNode = checkElement(node); 816 return (pNode == m_pCurrentElement); 817 } 818 819 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrentElementEmpty( ) 820 throw (cssu::RuntimeException) 821 { 822 sal_Bool rc = sal_False; 823 824 if (m_pCurrentElement->children == NULL) 825 { 826 rc = sal_True; 827 } 828 829 return rc; 830 } 831 832 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getNodeName( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) 833 throw (cssu::RuntimeException) 834 { 835 xmlNodePtr pNode = checkElement(node); 836 return rtl::OUString(RTL_UTF8_USTRINGPARAM ( (sal_Char*)pNode->name )); 837 } 838 839 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::clearUselessData( 840 const cssu::Reference< cssxw::XXMLElementWrapper >& node, 841 const cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >& reservedDescendants, 842 const cssu::Reference< cssxw::XXMLElementWrapper >& stopAtNode ) 843 throw (cssu::RuntimeException) 844 { 845 xmlNodePtr pTargetNode = checkElement(node); 846 847 m_pStopAtNode = checkElement(stopAtNode); 848 m_aReservedNodes = reservedDescendants; 849 m_nReservedNodeIndex = 0; 850 851 getNextReservedNode(); 852 853 recursiveDelete(pTargetNode); 854 } 855 856 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::collapse( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) 857 throw (cssu::RuntimeException) 858 { 859 xmlNodePtr pTargetNode = checkElement(node); 860 xmlNodePtr pParent; 861 862 while (pTargetNode != NULL) 863 { 864 if (pTargetNode->children != NULL || pTargetNode == m_pCurrentElement) 865 { 866 break; 867 } 868 869 pParent = pTargetNode->parent; 870 removeNode(pTargetNode); 871 pTargetNode = pParent; 872 } 873 } 874 875 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::getTree( const cssu::Reference< cssxs::XDocumentHandler >& handler ) 876 throw (cssxs::SAXException, cssu::RuntimeException) 877 { 878 if (m_pRootElement != NULL) 879 { 880 xmlNodePtr pTempCurrentElement = m_pCurrentElement; 881 sal_Int32 nTempCurrentPosition = m_nCurrentPosition; 882 883 m_pCurrentElement = m_pRootElement; 884 885 m_nCurrentPosition = NODEPOSITION_STARTELEMENT; 886 cssu::Reference< cssxs::XDocumentHandler > xHandler = handler; 887 888 while(true) 889 { 890 switch (m_nCurrentPosition) 891 { 892 case NODEPOSITION_STARTELEMENT: 893 sendStartElement(NULL, xHandler, m_pCurrentElement); 894 break; 895 case NODEPOSITION_ENDELEMENT: 896 sendEndElement(NULL, xHandler, m_pCurrentElement); 897 break; 898 case NODEPOSITION_NORMAL: 899 sendNode(NULL, xHandler, m_pCurrentElement); 900 break; 901 } 902 903 if ( (m_pCurrentElement == m_pRootElement) && (m_nCurrentPosition == NODEPOSITION_ENDELEMENT )) 904 { 905 break; 906 } 907 908 getNextSAXEvent(); 909 } 910 911 m_pCurrentElement = pTempCurrentElement; 912 m_nCurrentPosition = nTempCurrentPosition; 913 } 914 } 915 916 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::generateSAXEvents( 917 const cssu::Reference< cssxs::XDocumentHandler >& handler, 918 const cssu::Reference< cssxs::XDocumentHandler >& xEventKeeperHandler, 919 const cssu::Reference< cssxw::XXMLElementWrapper >& startNode, 920 const cssu::Reference< cssxw::XXMLElementWrapper >& endNode ) 921 throw (cssxs::SAXException, cssu::RuntimeException) 922 { 923 /* 924 * The first SAX event is the startElement of the startNode 925 * element. 926 */ 927 bool bHasCurrentElementChild = (m_pCurrentElement->children != NULL); 928 929 xmlNodePtr pTempCurrentElement = m_pCurrentElement; 930 931 m_pCurrentElement = checkElement(startNode); 932 933 if (m_pCurrentElement->type == XML_ELEMENT_NODE) 934 { 935 m_nCurrentPosition = NODEPOSITION_STARTELEMENT; 936 } 937 else 938 { 939 m_nCurrentPosition = NODEPOSITION_NORMAL; 940 } 941 942 xmlNodePtr pEndNode = checkElement(endNode); 943 944 cssu::Reference < cssxc::sax::XSAXEventKeeper > xSAXEventKeeper( xEventKeeperHandler, cssu::UNO_QUERY ); 945 946 cssu::Reference< cssxs::XDocumentHandler > xHandler = handler; 947 948 while(true) 949 { 950 switch (m_nCurrentPosition) 951 { 952 case NODEPOSITION_STARTELEMENT: 953 sendStartElement(xHandler, xEventKeeperHandler, m_pCurrentElement); 954 break; 955 case NODEPOSITION_ENDELEMENT: 956 sendEndElement(xHandler, xEventKeeperHandler, m_pCurrentElement); 957 break; 958 case NODEPOSITION_NORMAL: 959 sendNode(xHandler, xEventKeeperHandler, m_pCurrentElement); 960 break; 961 default: 962 throw cssu::RuntimeException(); 963 } 964 965 if (xSAXEventKeeper->isBlocking()) 966 { 967 xHandler = NULL; 968 } 969 970 if (pEndNode == NULL && 971 ((bHasCurrentElementChild && m_pCurrentElement == xmlGetLastChild(pTempCurrentElement) && m_nCurrentPosition != NODEPOSITION_STARTELEMENT) || 972 (!bHasCurrentElementChild && m_pCurrentElement == pTempCurrentElement && m_nCurrentPosition == NODEPOSITION_STARTELEMENT))) 973 { 974 break; 975 } 976 977 getNextSAXEvent(); 978 979 /* 980 * If there is an end point specified, then check whether 981 * the current node equals to the end point. If so, stop 982 * generating. 983 */ 984 if (pEndNode != NULL && m_pCurrentElement == pEndNode) 985 { 986 break; 987 } 988 } 989 990 m_pCurrentElement = pTempCurrentElement; 991 } 992 993 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::rebuildIDLink( 994 const com::sun::star::uno::Reference< com::sun::star::xml::wrapper::XXMLElementWrapper >& node ) 995 throw (com::sun::star::uno::RuntimeException) 996 { 997 xmlNodePtr pNode = checkElement( node ); 998 rebuildIDLink(pNode); 999 } 1000 1001 1002 /* cssxs::XDocumentHandler */ 1003 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument( ) 1004 throw (cssxs::SAXException, cssu::RuntimeException) 1005 { 1006 } 1007 1008 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument( ) 1009 throw (cssxs::SAXException, cssu::RuntimeException) 1010 { 1011 } 1012 1013 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startElement( const rtl::OUString& aName, const cssu::Reference< cssxs::XAttributeList >& xAttribs ) 1014 throw (cssxs::SAXException, cssu::RuntimeException) 1015 { 1016 sal_Int32 nLength = xAttribs->getLength(); 1017 cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength); 1018 1019 for (int i = 0; i < nLength; ++i) 1020 { 1021 aAttributes[i].sName = xAttribs->getNameByIndex((short)i); 1022 aAttributes[i].sValue =xAttribs->getValueByIndex((short)i); 1023 } 1024 1025 _startElement(aName, aAttributes); 1026 } 1027 1028 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const rtl::OUString& aName ) 1029 throw (cssxs::SAXException, cssu::RuntimeException) 1030 { 1031 saxHelper.endElement(aName); 1032 m_pCurrentElement = saxHelper.getCurrentNode(); 1033 } 1034 1035 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const rtl::OUString& aChars ) 1036 throw (cssxs::SAXException, cssu::RuntimeException) 1037 { 1038 saxHelper.characters(aChars); 1039 } 1040 1041 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces ) 1042 throw (cssxs::SAXException, cssu::RuntimeException) 1043 { 1044 saxHelper.ignorableWhitespace(aWhitespaces); 1045 } 1046 1047 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) 1048 throw (cssxs::SAXException, cssu::RuntimeException) 1049 { 1050 saxHelper.processingInstruction(aTarget, aData); 1051 } 1052 1053 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator ) 1054 throw (cssxs::SAXException, cssu::RuntimeException) 1055 { 1056 saxHelper.setDocumentLocator(xLocator); 1057 } 1058 1059 /* XCompressedDocumentHandler */ 1060 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startDocument( ) 1061 throw (cssxs::SAXException, cssu::RuntimeException) 1062 { 1063 } 1064 1065 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endDocument( ) 1066 throw (cssxs::SAXException, cssu::RuntimeException) 1067 { 1068 } 1069 1070 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startElement( const rtl::OUString& aName, const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes ) 1071 throw (cssxs::SAXException, cssu::RuntimeException) 1072 { 1073 saxHelper.startElement(aName, aAttributes); 1074 m_pCurrentElement = saxHelper.getCurrentNode(); 1075 1076 buildIDAttr( m_pCurrentElement ); 1077 } 1078 1079 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endElement( const rtl::OUString& aName ) 1080 throw (cssxs::SAXException, cssu::RuntimeException) 1081 { 1082 endElement( aName ); 1083 } 1084 1085 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_characters( const rtl::OUString& aChars ) 1086 throw (cssxs::SAXException, cssu::RuntimeException) 1087 { 1088 characters( aChars ); 1089 } 1090 1091 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_ignorableWhitespace( const rtl::OUString& aWhitespaces ) 1092 throw (cssxs::SAXException, cssu::RuntimeException) 1093 { 1094 ignorableWhitespace( aWhitespaces ); 1095 } 1096 1097 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) 1098 throw (cssxs::SAXException, cssu::RuntimeException) 1099 { 1100 processingInstruction( aTarget, aData ); 1101 } 1102 1103 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_setDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const rtl::OUString& /*publicId*/, const rtl::OUString& /*systemId*/ ) 1104 throw (cssxs::SAXException, cssu::RuntimeException) 1105 { 1106 } 1107 1108 rtl::OUString XMLDocumentWrapper_XmlSecImpl_getImplementationName () 1109 throw (cssu::RuntimeException) 1110 { 1111 return rtl::OUString ( RTL_ASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) ); 1112 } 1113 1114 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl_supportsService( const rtl::OUString& ServiceName ) 1115 throw (cssu::RuntimeException) 1116 { 1117 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME )); 1118 } 1119 1120 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames( ) 1121 throw (cssu::RuntimeException) 1122 { 1123 cssu::Sequence < rtl::OUString > aRet(1); 1124 rtl::OUString* pArray = aRet.getArray(); 1125 pArray[0] = rtl::OUString ( RTL_ASCII_USTRINGPARAM ( SERVICE_NAME ) ); 1126 return aRet; 1127 } 1128 #undef SERVICE_NAME 1129 1130 cssu::Reference< cssu::XInterface > SAL_CALL XMLDocumentWrapper_XmlSecImpl_createInstance( 1131 const cssu::Reference< cssl::XMultiServiceFactory > &) 1132 throw( cssu::Exception ) 1133 { 1134 return (cppu::OWeakObject*) new XMLDocumentWrapper_XmlSecImpl( ); 1135 } 1136 1137 /* XServiceInfo */ 1138 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName( ) 1139 throw (cssu::RuntimeException) 1140 { 1141 return XMLDocumentWrapper_XmlSecImpl_getImplementationName(); 1142 } 1143 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const rtl::OUString& rServiceName ) 1144 throw (cssu::RuntimeException) 1145 { 1146 return XMLDocumentWrapper_XmlSecImpl_supportsService( rServiceName ); 1147 } 1148 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames( ) 1149 throw (cssu::RuntimeException) 1150 { 1151 return XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames(); 1152 } 1153 1154