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
XMLDocumentWrapper_XmlSecImpl()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
~XMLDocumentWrapper_XmlSecImpl()89 XMLDocumentWrapper_XmlSecImpl::~XMLDocumentWrapper_XmlSecImpl()
90 {
91 saxHelper.endDocument();
92 xmlFreeDoc(m_pDocument);
93 }
94
getNextSAXEvent()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
sendStartElement(const cssu::Reference<cssxs::XDocumentHandler> & xHandler,const cssu::Reference<cssxs::XDocumentHandler> & xHandler2,const xmlNodePtr pNode) const196 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
sendEndElement(const cssu::Reference<cssxs::XDocumentHandler> & xHandler,const cssu::Reference<cssxs::XDocumentHandler> & xHandler2,const xmlNodePtr pNode) const299 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
sendNode(const cssu::Reference<cssxs::XDocumentHandler> & xHandler,const cssu::Reference<cssxs::XDocumentHandler> & xHandler2,const xmlNodePtr pNode) const345 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
getNodeQName(const xmlNodePtr pNode) const411 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
checkElement(const cssu::Reference<cssxw::XXMLElementWrapper> & xXMLElement) const452 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
recursiveDelete(const xmlNodePtr pNode)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
getNextReservedNode()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
removeNode(const xmlNodePtr pNode) const641 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
buildIDAttr(xmlNodePtr pNode) const686 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
rebuildIDLink(xmlNodePtr pNode) const725 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 */
getCurrentElement()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
setCurrentElement(const cssu::Reference<cssxw::XXMLElementWrapper> & element)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
removeCurrentElement()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
isCurrent(const cssu::Reference<cssxw::XXMLElementWrapper> & node)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
isCurrentElementEmpty()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
getNodeName(const cssu::Reference<cssxw::XXMLElementWrapper> & node)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
clearUselessData(const cssu::Reference<cssxw::XXMLElementWrapper> & node,const cssu::Sequence<cssu::Reference<cssxw::XXMLElementWrapper>> & reservedDescendants,const cssu::Reference<cssxw::XXMLElementWrapper> & stopAtNode)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
collapse(const cssu::Reference<cssxw::XXMLElementWrapper> & node)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
getTree(const cssu::Reference<cssxs::XDocumentHandler> & handler)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
generateSAXEvents(const cssu::Reference<cssxs::XDocumentHandler> & handler,const cssu::Reference<cssxs::XDocumentHandler> & xEventKeeperHandler,const cssu::Reference<cssxw::XXMLElementWrapper> & startNode,const cssu::Reference<cssxw::XXMLElementWrapper> & endNode)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
rebuildIDLink(const com::sun::star::uno::Reference<com::sun::star::xml::wrapper::XXMLElementWrapper> & node)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 */
startDocument()985 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument( )
986 {
987 }
988
endDocument()989 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument( )
990 {
991 }
992
startElement(const rtl::OUString & aName,const cssu::Reference<cssxs::XAttributeList> & xAttribs)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
endElement(const rtl::OUString & aName)1007 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const rtl::OUString& aName )
1008 {
1009 saxHelper.endElement(aName);
1010 m_pCurrentElement = saxHelper.getCurrentNode();
1011 }
1012
characters(const rtl::OUString & aChars)1013 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const rtl::OUString& aChars )
1014 {
1015 saxHelper.characters(aChars);
1016 }
1017
ignorableWhitespace(const rtl::OUString & aWhitespaces)1018 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1019 {
1020 saxHelper.ignorableWhitespace(aWhitespaces);
1021 }
1022
processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)1023 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData )
1024 {
1025 saxHelper.processingInstruction(aTarget, aData);
1026 }
1027
setDocumentLocator(const cssu::Reference<cssxs::XLocator> & xLocator)1028 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator )
1029 {
1030 saxHelper.setDocumentLocator(xLocator);
1031 }
1032
1033 /* XCompressedDocumentHandler */
_startDocument()1034 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startDocument( )
1035 {
1036 }
1037
_endDocument()1038 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endDocument( )
1039 {
1040 }
1041
_startElement(const rtl::OUString & aName,const cssu::Sequence<cssxcsax::XMLAttribute> & aAttributes)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
_endElement(const rtl::OUString & aName)1050 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endElement( const rtl::OUString& aName )
1051 {
1052 endElement( aName );
1053 }
1054
_characters(const rtl::OUString & aChars)1055 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_characters( const rtl::OUString& aChars )
1056 {
1057 characters( aChars );
1058 }
1059
_ignorableWhitespace(const rtl::OUString & aWhitespaces)1060 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_ignorableWhitespace( const rtl::OUString& aWhitespaces )
1061 {
1062 ignorableWhitespace( aWhitespaces );
1063 }
1064
_processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)1065 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData )
1066 {
1067 processingInstruction( aTarget, aData );
1068 }
1069
_setDocumentLocator(sal_Int32,sal_Int32,const rtl::OUString &,const rtl::OUString &)1070 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_setDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const rtl::OUString& /*publicId*/, const rtl::OUString& /*systemId*/ )
1071 {
1072 }
1073
XMLDocumentWrapper_XmlSecImpl_getImplementationName()1074 rtl::OUString XMLDocumentWrapper_XmlSecImpl_getImplementationName ()
1075 {
1076 return rtl::OUString ( RTL_ASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1077 }
1078
XMLDocumentWrapper_XmlSecImpl_supportsService(const rtl::OUString & ServiceName)1079 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl_supportsService( const rtl::OUString& ServiceName )
1080 {
1081 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
1082 }
1083
XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames()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
XMLDocumentWrapper_XmlSecImpl_createInstance(const cssu::Reference<cssl::XMultiServiceFactory> &)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 */
getImplementationName()1100 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName( )
1101 {
1102 return XMLDocumentWrapper_XmlSecImpl_getImplementationName();
1103 }
supportsService(const rtl::OUString & rServiceName)1104 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const rtl::OUString& rServiceName )
1105 {
1106 return XMLDocumentWrapper_XmlSecImpl_supportsService( rServiceName );
1107 }
getSupportedServiceNames()1108 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames( )
1109 {
1110 return XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames();
1111 }
1112