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 throw (cssxs::SAXException) 201 /****** XMLDocumentWrapper_XmlSecImpl/sendStartElement ************************ 202 * 203 * NAME 204 * sendStartElement -- Constructs a startElement SAX event 205 * 206 * SYNOPSIS 207 * sendStartElement(xHandler, xHandler2, pNode); 208 * 209 * FUNCTION 210 * Used when converting the document into SAX event stream. 211 * This method constructs a startElement SAX event for a particular 212 * element, then calls the startElement methods of the XDocumentHandlers. 213 * 214 * INPUTS 215 * xHandler - the first XDocumentHandler interface to receive the 216 * startElement SAX event. It can be NULL. 217 * xHandler2 - the second XDocumentHandler interface to receive the 218 * startElement SAX event. It can't be NULL. 219 * pNode - the node on which the startElement should be generated. 220 * This node must be a element type. 221 * 222 * RESULT 223 * empty 224 * 225 * HISTORY 226 * 05.01.2004 - implemented 227 * 228 * AUTHOR 229 * Michael Mi 230 * Email: michael.mi@sun.com 231 ******************************************************************************/ 232 { 233 SvXMLAttributeList* pAttributeList = new SvXMLAttributeList(); 234 cssu::Reference < cssxs::XAttributeList > xAttrList = cssu::Reference< cssxs::XAttributeList > (pAttributeList); 235 236 xmlNsPtr pNsDef = pNode->nsDef; 237 238 while (pNsDef != NULL) 239 { 240 const xmlChar* pNsPrefix = pNsDef->prefix; 241 const xmlChar* pNsHref = pNsDef->href; 242 243 if (pNsDef->prefix == NULL) 244 { 245 pAttributeList->AddAttribute( 246 rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS )), 247 rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref ))); 248 } 249 else 250 { 251 pAttributeList->AddAttribute( 252 rtl::OUString(RTL_UTF8_USTRINGPARAM( STRXMLNS )) 253 +rtl::OUString(RTL_UTF8_USTRINGPARAM( ":" )) 254 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsPrefix )), 255 rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pNsHref ))); 256 } 257 258 pNsDef = pNsDef->next; 259 } 260 261 xmlAttrPtr pAttr = pNode->properties; 262 263 while (pAttr != NULL) 264 { 265 const xmlChar* pAttrName = pAttr->name; 266 xmlNsPtr pAttrNs = pAttr->ns; 267 268 rtl::OUString ouAttrName; 269 if (pAttrNs == NULL) 270 { 271 ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName )); 272 } 273 else 274 { 275 ouAttrName = rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrNs->prefix)) 276 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)":" )) 277 +rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)pAttrName )); 278 } 279 280 pAttributeList->AddAttribute( 281 ouAttrName, 282 rtl::OUString(RTL_UTF8_USTRINGPARAM( (sal_Char*)(pAttr->children->content)))); 283 pAttr = pAttr->next; 284 } 285 286 rtl::OString sNodeName = getNodeQName(pNode); 287 288 if (xHandler.is()) 289 { 290 xHandler->startElement( 291 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )), 292 xAttrList); 293 } 294 295 xHandler2->startElement( 296 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) )), 297 xAttrList); 298 } 299 300 void XMLDocumentWrapper_XmlSecImpl::sendEndElement( 301 const cssu::Reference< cssxs::XDocumentHandler >& xHandler, 302 const cssu::Reference< cssxs::XDocumentHandler >& xHandler2, 303 const xmlNodePtr pNode) const 304 throw (cssxs::SAXException) 305 /****** XMLDocumentWrapper_XmlSecImpl/sendEndElement ************************** 306 * 307 * NAME 308 * sendEndElement -- Constructs a endElement SAX event 309 * 310 * SYNOPSIS 311 * sendEndElement(xHandler, xHandler2, pNode); 312 * 313 * FUNCTION 314 * Used when converting the document into SAX event stream. 315 * This method constructs a endElement SAX event for a particular 316 * element, then calls the endElement methods of the XDocumentHandlers. 317 * 318 * INPUTS 319 * xHandler - the first XDocumentHandler interface to receive the 320 * endElement SAX event. It can be NULL. 321 * xHandler2 - the second XDocumentHandler interface to receive the 322 * endElement SAX event. It can't be NULL. 323 * pNode - the node on which the endElement should be generated. 324 * This node must be a element type. 325 * 326 * RESULT 327 * empty 328 * 329 * HISTORY 330 * 05.01.2004 - implemented 331 * 332 * AUTHOR 333 * Michael Mi 334 * Email: michael.mi@sun.com 335 ******************************************************************************/ 336 { 337 rtl::OString sNodeName = getNodeQName(pNode); 338 339 if (xHandler.is()) 340 { 341 xHandler->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) ))); 342 } 343 344 xHandler2->endElement(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(sNodeName.getStr())) ))); 345 } 346 347 void XMLDocumentWrapper_XmlSecImpl::sendNode( 348 const cssu::Reference< cssxs::XDocumentHandler >& xHandler, 349 const cssu::Reference< cssxs::XDocumentHandler >& xHandler2, 350 const xmlNodePtr pNode) const 351 throw (cssxs::SAXException) 352 /****** XMLDocumentWrapper_XmlSecImpl/sendNode ******************************** 353 * 354 * NAME 355 * sendNode -- Constructs a characters SAX event or a 356 * processingInstruction SAX event 357 * 358 * SYNOPSIS 359 * sendNode(xHandler, xHandler2, pNode); 360 * 361 * FUNCTION 362 * Used when converting the document into SAX event stream. 363 * This method constructs a characters SAX event or a 364 * processingInstructionfor SAX event based on the type of a particular 365 * element, then calls the corresponding methods of the XDocumentHandlers. 366 * 367 * INPUTS 368 * xHandler - the first XDocumentHandler interface to receive the 369 * SAX event. It can be NULL. 370 * xHandler2 - the second XDocumentHandler interface to receive the 371 * SAX event. It can't be NULL. 372 * pNode - the node on which the endElement should be generated. 373 * If it is a text node, then a characters SAX event is 374 * generated; if it is a PI node, then a 375 * processingInstructionfor SAX event is generated. 376 * 377 * RESULT 378 * empty 379 * 380 * HISTORY 381 * 05.01.2004 - implemented 382 * 383 * AUTHOR 384 * Michael Mi 385 * Email: michael.mi@sun.com 386 ******************************************************************************/ 387 { 388 xmlElementType type = pNode->type; 389 390 if (type == XML_TEXT_NODE) 391 { 392 if (xHandler.is()) 393 { 394 xHandler->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); 395 } 396 397 xHandler2->characters(rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); 398 } 399 else if (type == XML_PI_NODE) 400 { 401 if (xHandler.is()) 402 { 403 xHandler->processingInstruction( 404 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )), 405 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); 406 } 407 408 xHandler2->processingInstruction( 409 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->name)) )), 410 rtl::OUString(RTL_UTF8_USTRINGPARAM ( ((sal_Char*)(pNode->content)) ))); 411 } 412 } 413 414 rtl::OString XMLDocumentWrapper_XmlSecImpl::getNodeQName(const xmlNodePtr pNode) const 415 /****** XMLDocumentWrapper_XmlSecImpl/getNodeQName **************************** 416 * 417 * NAME 418 * getNodeQName -- Retrives the qualified name of a node 419 * 420 * SYNOPSIS 421 * name = getNodeQName(pNode); 422 * 423 * FUNCTION 424 * see NAME 425 * 426 * INPUTS 427 * pNode - the node whose name will be retrived 428 * 429 * RESULT 430 * name - the node's qualified name 431 * 432 * HISTORY 433 * 05.01.2004 - implemented 434 * 435 * AUTHOR 436 * Michael Mi 437 * Email: michael.mi@sun.com 438 ******************************************************************************/ 439 { 440 rtl::OString sNodeName((const sal_Char*)pNode->name); 441 if (pNode->ns != NULL) 442 { 443 xmlNsPtr pNs = pNode->ns; 444 445 if (pNs->prefix != NULL) 446 { 447 rtl::OString sPrefix((const sal_Char*)pNs->prefix); 448 sNodeName = sPrefix+rtl::OString(":")+sNodeName; 449 } 450 } 451 452 return sNodeName; 453 } 454 455 xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const cssu::Reference< cssxw::XXMLElementWrapper >& xXMLElement) const 456 /****** XMLDocumentWrapper_XmlSecImpl/checkElement **************************** 457 * 458 * NAME 459 * checkElement -- Retrives the node wrapped by an XXMLElementWrapper 460 * interface 461 * 462 * SYNOPSIS 463 * node = checkElement(xXMLElement); 464 * 465 * FUNCTION 466 * see NAME 467 * 468 * INPUTS 469 * xXMLElement - the XXMLElementWrapper interface wraping a node 470 * 471 * RESULT 472 * node - the node wrapped in the XXMLElementWrapper interface 473 * 474 * HISTORY 475 * 05.01.2004 - implemented 476 * 477 * AUTHOR 478 * Michael Mi 479 * Email: michael.mi@sun.com 480 ******************************************************************************/ 481 { 482 xmlNodePtr rc = NULL; 483 484 if (xXMLElement.is()) 485 { 486 cssu::Reference< cssl::XUnoTunnel > xNodTunnel( xXMLElement, cssu::UNO_QUERY ) ; 487 if( !xNodTunnel.is() ) 488 { 489 throw cssu::RuntimeException() ; 490 } 491 492 XMLElementWrapper_XmlSecImpl* pElement 493 = reinterpret_cast<XMLElementWrapper_XmlSecImpl*>( 494 sal::static_int_cast<sal_uIntPtr>( 495 xNodTunnel->getSomething( 496 XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ))) ; 497 498 if( pElement == NULL ) { 499 throw cssu::RuntimeException() ; 500 } 501 502 rc = pElement->getNativeElement(); 503 } 504 505 return rc; 506 } 507 508 sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete( 509 const xmlNodePtr pNode) 510 /****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete ************************* 511 * 512 * NAME 513 * recursiveDelete -- Deletes a paticular node with its branch. 514 * 515 * SYNOPSIS 516 * result = recursiveDelete(pNode); 517 * 518 * FUNCTION 519 * Deletes a paticular node with its branch, while reserving the nodes 520 * (and their brance) listed in the m_aReservedNodes. 521 * The deletion process is preformed in the tree order, that is, a node 522 * is deleted after its previous sibling node is deleted, a parent node 523 * is deleted after its branch is deleted. 524 * During the deletion process when the m_pStopAtNode is reached, the 525 * progress is interrupted at once. 526 * 527 * INPUTS 528 * pNode - the node to be deleted 529 * 530 * RESULT 531 * result - the result of the deletion process, can be one of following 532 * values: 533 * NODE_STOPED - the process is interrupted by meeting the 534 * m_pStopAtNode 535 * NODE_NOTREMOVED - the pNode is not completely removed 536 * because there is its descendant in the 537 * m_aReservedNodes list 538 * NODE_REMOVED - the pNode and its branch are completely 539 * removed 540 * 541 * NOTES 542 * The node in the m_aReservedNodes list must be in the tree order, otherwise 543 * the result is unpredictable. 544 * 545 * HISTORY 546 * 05.01.2004 - implemented 547 * 548 * AUTHOR 549 * Michael Mi 550 * Email: michael.mi@sun.com 551 ******************************************************************************/ 552 { 553 if (pNode == m_pStopAtNode) 554 { 555 return NODE_STOPED; 556 } 557 558 if (pNode != m_pCurrentReservedNode) 559 { 560 xmlNodePtr pChild = pNode->children; 561 562 xmlNodePtr pNextSibling; 563 bool bIsRemoved = true; 564 sal_Int32 nResult; 565 566 while( pChild != NULL ) 567 { 568 pNextSibling = pChild->next; 569 nResult = recursiveDelete(pChild); 570 571 switch (nResult) 572 { 573 case NODE_STOPED: 574 return NODE_STOPED; 575 case NODE_NOTREMOVED: 576 bIsRemoved = false; 577 break; 578 case NODE_REMOVED: 579 removeNode(pChild); 580 break; 581 default: 582 throw cssu::RuntimeException(); 583 } 584 585 pChild = pNextSibling; 586 } 587 588 if (pNode == m_pCurrentElement) 589 { 590 bIsRemoved = false; 591 } 592 593 return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED; 594 } 595 else 596 { 597 getNextReservedNode(); 598 return NODE_NOTREMOVED; 599 } 600 } 601 602 void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode() 603 /****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode ********************* 604 * 605 * NAME 606 * getNextReservedNode -- Highlights the next reserved node in the 607 * reserved node list 608 * 609 * SYNOPSIS 610 * getNextReservedNode(); 611 * 612 * FUNCTION 613 * The m_aReservedNodes array holds a node list, while the 614 * m_pCurrentReservedNode points to the one currently highlighted. 615 * This method is used to highlight the next node in the node list. 616 * This method is called at the time when the current highlighted node 617 * has been already processed, and the next node should be ready. 618 * 619 * INPUTS 620 * empty 621 * 622 * RESULT 623 * empty 624 * 625 * HISTORY 626 * 05.01.2004 - implemented 627 * 628 * AUTHOR 629 * Michael Mi 630 * Email: michael.mi@sun.com 631 ******************************************************************************/ 632 { 633 if (m_nReservedNodeIndex < m_aReservedNodes.getLength()) 634 { 635 m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] ); 636 m_nReservedNodeIndex ++; 637 } 638 else 639 { 640 m_pCurrentReservedNode = NULL; 641 } 642 } 643 644 void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const 645 /****** XMLDocumentWrapper_XmlSecImpl/removeNode ****************************** 646 * 647 * NAME 648 * removeNode -- Deletes a node with its branch unconditionaly 649 * 650 * SYNOPSIS 651 * removeNode( pNode ); 652 * 653 * FUNCTION 654 * Delete the node along with its branch from the document. 655 * 656 * INPUTS 657 * pNode - the node to be deleted 658 * 659 * RESULT 660 * empty 661 * 662 * HISTORY 663 * 05.01.2004 - implemented 664 * 665 * AUTHOR 666 * Michael Mi 667 * Email: michael.mi@sun.com 668 ******************************************************************************/ 669 { 670 /* you can't remove the current node */ 671 OSL_ASSERT( m_pCurrentElement != pNode ); 672 673 xmlAttrPtr pAttr = pNode->properties; 674 675 while (pAttr != NULL) 676 { 677 if (!stricmp((sal_Char*)pAttr->name,"id")) 678 { 679 xmlRemoveID(m_pDocument, pAttr); 680 } 681 682 pAttr = pAttr->next; 683 } 684 685 xmlUnlinkNode(pNode); 686 xmlFreeNode(pNode); 687 } 688 689 void XMLDocumentWrapper_XmlSecImpl::buildIDAttr(xmlNodePtr pNode) const 690 /****** XMLDocumentWrapper_XmlSecImpl/buildIDAttr ***************************** 691 * 692 * NAME 693 * buildIDAttr -- build the ID attribute of a node 694 * 695 * SYNOPSIS 696 * buildIDAttr( pNode ); 697 * 698 * FUNCTION 699 * see NAME 700 * 701 * INPUTS 702 * pNode - the node whose id attribute will be built 703 * 704 * RESULT 705 * empty 706 * 707 * HISTORY 708 * 14.06.2004 - implemented 709 * 710 * AUTHOR 711 * Michael Mi 712 * Email: michael.mi@sun.com 713 ******************************************************************************/ 714 { 715 xmlAttrPtr idAttr = xmlHasProp( pNode, (const unsigned char *)"id" ); 716 if (idAttr == NULL) 717 { 718 idAttr = xmlHasProp( pNode, (const unsigned char *)"Id" ); 719 } 720 721 if (idAttr != NULL) 722 { 723 xmlChar* idValue = xmlNodeListGetString( m_pDocument, idAttr->children, 1 ) ; 724 xmlAddID( NULL, m_pDocument, idValue, idAttr ); 725 } 726 } 727 728 void XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(xmlNodePtr pNode) const 729 /****** XMLDocumentWrapper_XmlSecImpl/rebuildIDLink *************************** 730 * 731 * NAME 732 * rebuildIDLink -- rebuild the ID link for the branch 733 * 734 * SYNOPSIS 735 * rebuildIDLink( pNode ); 736 * 737 * FUNCTION 738 * see NAME 739 * 740 * INPUTS 741 * pNode - the node, from which the branch will be rebuilt 742 * 743 * RESULT 744 * empty 745 * 746 * HISTORY 747 * 14.06.2004 - implemented 748 * 749 * AUTHOR 750 * Michael Mi 751 * Email: michael.mi@sun.com 752 ******************************************************************************/ 753 { 754 if (pNode != NULL && pNode->type == XML_ELEMENT_NODE) 755 { 756 buildIDAttr( pNode ); 757 758 xmlNodePtr child = pNode->children; 759 while (child != NULL) 760 { 761 rebuildIDLink(child); 762 child = child->next; 763 } 764 } 765 } 766 767 /* XXMLDocumentWrapper */ 768 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getCurrentElement( ) 769 throw (cssu::RuntimeException) 770 { 771 XMLElementWrapper_XmlSecImpl* pElement = new XMLElementWrapper_XmlSecImpl(m_pCurrentElement); 772 return (cssu::Reference< cssxw::XXMLElementWrapper >)pElement; 773 } 774 775 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setCurrentElement( const cssu::Reference< cssxw::XXMLElementWrapper >& element ) 776 throw (cssu::RuntimeException) 777 { 778 m_pCurrentElement = checkElement( element ); 779 saxHelper.setCurrentNode( m_pCurrentElement ); 780 } 781 782 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::removeCurrentElement( ) 783 throw (cssu::RuntimeException) 784 { 785 OSL_ASSERT( m_pCurrentElement != NULL ); 786 787 xmlNodePtr pOldCurrentElement = m_pCurrentElement; 788 789 /* 790 * pop the top node in the parser context's 791 * nodeTab stack, then the parent of that node will 792 * automatically become the new stack top, and 793 * the current node as well. 794 */ 795 saxHelper.endElement( 796 rtl::OUString( 797 RTL_UTF8_USTRINGPARAM ( 798 (sal_Char*)(pOldCurrentElement->name) 799 ))); 800 m_pCurrentElement = saxHelper.getCurrentNode(); 801 802 /* 803 * remove the node 804 */ 805 removeNode(pOldCurrentElement); 806 } 807 808 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrent( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) 809 throw (cssu::RuntimeException) 810 { 811 xmlNodePtr pNode = checkElement(node); 812 return (pNode == m_pCurrentElement); 813 } 814 815 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrentElementEmpty( ) 816 throw (cssu::RuntimeException) 817 { 818 sal_Bool rc = sal_False; 819 820 if (m_pCurrentElement->children == NULL) 821 { 822 rc = sal_True; 823 } 824 825 return rc; 826 } 827 828 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getNodeName( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) 829 throw (cssu::RuntimeException) 830 { 831 xmlNodePtr pNode = checkElement(node); 832 return rtl::OUString(RTL_UTF8_USTRINGPARAM ( (sal_Char*)pNode->name )); 833 } 834 835 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::clearUselessData( 836 const cssu::Reference< cssxw::XXMLElementWrapper >& node, 837 const cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >& reservedDescendants, 838 const cssu::Reference< cssxw::XXMLElementWrapper >& stopAtNode ) 839 throw (cssu::RuntimeException) 840 { 841 xmlNodePtr pTargetNode = checkElement(node); 842 843 m_pStopAtNode = checkElement(stopAtNode); 844 m_aReservedNodes = reservedDescendants; 845 m_nReservedNodeIndex = 0; 846 847 getNextReservedNode(); 848 849 recursiveDelete(pTargetNode); 850 } 851 852 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::collapse( const cssu::Reference< cssxw::XXMLElementWrapper >& node ) 853 throw (cssu::RuntimeException) 854 { 855 xmlNodePtr pTargetNode = checkElement(node); 856 xmlNodePtr pParent; 857 858 while (pTargetNode != NULL) 859 { 860 if (pTargetNode->children != NULL || pTargetNode == m_pCurrentElement) 861 { 862 break; 863 } 864 865 pParent = pTargetNode->parent; 866 removeNode(pTargetNode); 867 pTargetNode = pParent; 868 } 869 } 870 871 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::getTree( const cssu::Reference< cssxs::XDocumentHandler >& handler ) 872 throw (cssxs::SAXException, cssu::RuntimeException) 873 { 874 if (m_pRootElement != NULL) 875 { 876 xmlNodePtr pTempCurrentElement = m_pCurrentElement; 877 sal_Int32 nTempCurrentPosition = m_nCurrentPosition; 878 879 m_pCurrentElement = m_pRootElement; 880 881 m_nCurrentPosition = NODEPOSITION_STARTELEMENT; 882 cssu::Reference< cssxs::XDocumentHandler > xHandler = handler; 883 884 while(true) 885 { 886 switch (m_nCurrentPosition) 887 { 888 case NODEPOSITION_STARTELEMENT: 889 sendStartElement(NULL, xHandler, m_pCurrentElement); 890 break; 891 case NODEPOSITION_ENDELEMENT: 892 sendEndElement(NULL, xHandler, m_pCurrentElement); 893 break; 894 case NODEPOSITION_NORMAL: 895 sendNode(NULL, xHandler, m_pCurrentElement); 896 break; 897 } 898 899 if ( (m_pCurrentElement == m_pRootElement) && (m_nCurrentPosition == NODEPOSITION_ENDELEMENT )) 900 { 901 break; 902 } 903 904 getNextSAXEvent(); 905 } 906 907 m_pCurrentElement = pTempCurrentElement; 908 m_nCurrentPosition = nTempCurrentPosition; 909 } 910 } 911 912 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::generateSAXEvents( 913 const cssu::Reference< cssxs::XDocumentHandler >& handler, 914 const cssu::Reference< cssxs::XDocumentHandler >& xEventKeeperHandler, 915 const cssu::Reference< cssxw::XXMLElementWrapper >& startNode, 916 const cssu::Reference< cssxw::XXMLElementWrapper >& endNode ) 917 throw (cssxs::SAXException, cssu::RuntimeException) 918 { 919 /* 920 * The first SAX event is the startElement of the startNode 921 * element. 922 */ 923 bool bHasCurrentElementChild = (m_pCurrentElement->children != NULL); 924 925 xmlNodePtr pTempCurrentElement = m_pCurrentElement; 926 927 m_pCurrentElement = checkElement(startNode); 928 929 if (m_pCurrentElement->type == XML_ELEMENT_NODE) 930 { 931 m_nCurrentPosition = NODEPOSITION_STARTELEMENT; 932 } 933 else 934 { 935 m_nCurrentPosition = NODEPOSITION_NORMAL; 936 } 937 938 xmlNodePtr pEndNode = checkElement(endNode); 939 940 cssu::Reference < cssxc::sax::XSAXEventKeeper > xSAXEventKeeper( xEventKeeperHandler, cssu::UNO_QUERY ); 941 942 cssu::Reference< cssxs::XDocumentHandler > xHandler = handler; 943 944 while(true) 945 { 946 switch (m_nCurrentPosition) 947 { 948 case NODEPOSITION_STARTELEMENT: 949 sendStartElement(xHandler, xEventKeeperHandler, m_pCurrentElement); 950 break; 951 case NODEPOSITION_ENDELEMENT: 952 sendEndElement(xHandler, xEventKeeperHandler, m_pCurrentElement); 953 break; 954 case NODEPOSITION_NORMAL: 955 sendNode(xHandler, xEventKeeperHandler, m_pCurrentElement); 956 break; 957 default: 958 throw cssu::RuntimeException(); 959 } 960 961 if (xSAXEventKeeper->isBlocking()) 962 { 963 xHandler = NULL; 964 } 965 966 if (pEndNode == NULL && 967 ((bHasCurrentElementChild && m_pCurrentElement == xmlGetLastChild(pTempCurrentElement) && m_nCurrentPosition != NODEPOSITION_STARTELEMENT) || 968 (!bHasCurrentElementChild && m_pCurrentElement == pTempCurrentElement && m_nCurrentPosition == NODEPOSITION_STARTELEMENT))) 969 { 970 break; 971 } 972 973 getNextSAXEvent(); 974 975 /* 976 * If there is an end point specified, then check whether 977 * the current node equals to the end point. If so, stop 978 * generating. 979 */ 980 if (pEndNode != NULL && m_pCurrentElement == pEndNode) 981 { 982 break; 983 } 984 } 985 986 m_pCurrentElement = pTempCurrentElement; 987 } 988 989 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::rebuildIDLink( 990 const com::sun::star::uno::Reference< com::sun::star::xml::wrapper::XXMLElementWrapper >& node ) 991 throw (com::sun::star::uno::RuntimeException) 992 { 993 xmlNodePtr pNode = checkElement( node ); 994 rebuildIDLink(pNode); 995 } 996 997 998 /* cssxs::XDocumentHandler */ 999 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument( ) 1000 throw (cssxs::SAXException, cssu::RuntimeException) 1001 { 1002 } 1003 1004 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument( ) 1005 throw (cssxs::SAXException, cssu::RuntimeException) 1006 { 1007 } 1008 1009 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startElement( const rtl::OUString& aName, const cssu::Reference< cssxs::XAttributeList >& xAttribs ) 1010 throw (cssxs::SAXException, cssu::RuntimeException) 1011 { 1012 sal_Int32 nLength = xAttribs->getLength(); 1013 cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength); 1014 1015 for (int i = 0; i < nLength; ++i) 1016 { 1017 aAttributes[i].sName = xAttribs->getNameByIndex((short)i); 1018 aAttributes[i].sValue =xAttribs->getValueByIndex((short)i); 1019 } 1020 1021 _startElement(aName, aAttributes); 1022 } 1023 1024 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const rtl::OUString& aName ) 1025 throw (cssxs::SAXException, cssu::RuntimeException) 1026 { 1027 saxHelper.endElement(aName); 1028 m_pCurrentElement = saxHelper.getCurrentNode(); 1029 } 1030 1031 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const rtl::OUString& aChars ) 1032 throw (cssxs::SAXException, cssu::RuntimeException) 1033 { 1034 saxHelper.characters(aChars); 1035 } 1036 1037 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces ) 1038 throw (cssxs::SAXException, cssu::RuntimeException) 1039 { 1040 saxHelper.ignorableWhitespace(aWhitespaces); 1041 } 1042 1043 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) 1044 throw (cssxs::SAXException, cssu::RuntimeException) 1045 { 1046 saxHelper.processingInstruction(aTarget, aData); 1047 } 1048 1049 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator ) 1050 throw (cssxs::SAXException, cssu::RuntimeException) 1051 { 1052 saxHelper.setDocumentLocator(xLocator); 1053 } 1054 1055 /* XCompressedDocumentHandler */ 1056 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startDocument( ) 1057 throw (cssxs::SAXException, cssu::RuntimeException) 1058 { 1059 } 1060 1061 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endDocument( ) 1062 throw (cssxs::SAXException, cssu::RuntimeException) 1063 { 1064 } 1065 1066 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startElement( const rtl::OUString& aName, const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes ) 1067 throw (cssxs::SAXException, cssu::RuntimeException) 1068 { 1069 saxHelper.startElement(aName, aAttributes); 1070 m_pCurrentElement = saxHelper.getCurrentNode(); 1071 1072 buildIDAttr( m_pCurrentElement ); 1073 } 1074 1075 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endElement( const rtl::OUString& aName ) 1076 throw (cssxs::SAXException, cssu::RuntimeException) 1077 { 1078 endElement( aName ); 1079 } 1080 1081 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_characters( const rtl::OUString& aChars ) 1082 throw (cssxs::SAXException, cssu::RuntimeException) 1083 { 1084 characters( aChars ); 1085 } 1086 1087 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_ignorableWhitespace( const rtl::OUString& aWhitespaces ) 1088 throw (cssxs::SAXException, cssu::RuntimeException) 1089 { 1090 ignorableWhitespace( aWhitespaces ); 1091 } 1092 1093 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) 1094 throw (cssxs::SAXException, cssu::RuntimeException) 1095 { 1096 processingInstruction( aTarget, aData ); 1097 } 1098 1099 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_setDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const rtl::OUString& /*publicId*/, const rtl::OUString& /*systemId*/ ) 1100 throw (cssxs::SAXException, cssu::RuntimeException) 1101 { 1102 } 1103 1104 rtl::OUString XMLDocumentWrapper_XmlSecImpl_getImplementationName () 1105 throw (cssu::RuntimeException) 1106 { 1107 return rtl::OUString ( RTL_ASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) ); 1108 } 1109 1110 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl_supportsService( const rtl::OUString& ServiceName ) 1111 throw (cssu::RuntimeException) 1112 { 1113 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME )); 1114 } 1115 1116 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames( ) 1117 throw (cssu::RuntimeException) 1118 { 1119 cssu::Sequence < rtl::OUString > aRet(1); 1120 rtl::OUString* pArray = aRet.getArray(); 1121 pArray[0] = rtl::OUString ( RTL_ASCII_USTRINGPARAM ( SERVICE_NAME ) ); 1122 return aRet; 1123 } 1124 #undef SERVICE_NAME 1125 1126 cssu::Reference< cssu::XInterface > SAL_CALL XMLDocumentWrapper_XmlSecImpl_createInstance( 1127 const cssu::Reference< cssl::XMultiServiceFactory > &) 1128 throw( cssu::Exception ) 1129 { 1130 return (cppu::OWeakObject*) new XMLDocumentWrapper_XmlSecImpl( ); 1131 } 1132 1133 /* XServiceInfo */ 1134 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName( ) 1135 throw (cssu::RuntimeException) 1136 { 1137 return XMLDocumentWrapper_XmlSecImpl_getImplementationName(); 1138 } 1139 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const rtl::OUString& rServiceName ) 1140 throw (cssu::RuntimeException) 1141 { 1142 return XMLDocumentWrapper_XmlSecImpl_supportsService( rServiceName ); 1143 } 1144 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames( ) 1145 throw (cssu::RuntimeException) 1146 { 1147 return XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames(); 1148 } 1149 1150