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