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 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
sendEndElement(const cssu::Reference<cssxs::XDocumentHandler> & xHandler,const cssu::Reference<cssxs::XDocumentHandler> & xHandler2,const xmlNodePtr pNode) const300 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
sendNode(const cssu::Reference<cssxs::XDocumentHandler> & xHandler,const cssu::Reference<cssxs::XDocumentHandler> & xHandler2,const xmlNodePtr pNode) const347 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
getNodeQName(const xmlNodePtr pNode) const414 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
checkElement(const cssu::Reference<cssxw::XXMLElementWrapper> & xXMLElement) const455 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
recursiveDelete(const xmlNodePtr pNode)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
getNextReservedNode()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
removeNode(const xmlNodePtr pNode) const644 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
buildIDAttr(xmlNodePtr pNode) const689 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
rebuildIDLink(xmlNodePtr pNode) const728 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 */
getCurrentElement()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
setCurrentElement(const cssu::Reference<cssxw::XXMLElementWrapper> & element)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
removeCurrentElement()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
isCurrent(const cssu::Reference<cssxw::XXMLElementWrapper> & node)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
isCurrentElementEmpty()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
getNodeName(const cssu::Reference<cssxw::XXMLElementWrapper> & node)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
clearUselessData(const cssu::Reference<cssxw::XXMLElementWrapper> & node,const cssu::Sequence<cssu::Reference<cssxw::XXMLElementWrapper>> & reservedDescendants,const cssu::Reference<cssxw::XXMLElementWrapper> & stopAtNode)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
collapse(const cssu::Reference<cssxw::XXMLElementWrapper> & node)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
getTree(const cssu::Reference<cssxs::XDocumentHandler> & handler)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
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)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
rebuildIDLink(const com::sun::star::uno::Reference<com::sun::star::xml::wrapper::XXMLElementWrapper> & node)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 */
startDocument()999 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument( )
1000 throw (cssxs::SAXException, cssu::RuntimeException)
1001 {
1002 }
1003
endDocument()1004 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument( )
1005 throw (cssxs::SAXException, cssu::RuntimeException)
1006 {
1007 }
1008
startElement(const rtl::OUString & aName,const cssu::Reference<cssxs::XAttributeList> & xAttribs)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
endElement(const rtl::OUString & aName)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
characters(const rtl::OUString & aChars)1031 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const rtl::OUString& aChars )
1032 throw (cssxs::SAXException, cssu::RuntimeException)
1033 {
1034 saxHelper.characters(aChars);
1035 }
1036
ignorableWhitespace(const rtl::OUString & aWhitespaces)1037 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1038 throw (cssxs::SAXException, cssu::RuntimeException)
1039 {
1040 saxHelper.ignorableWhitespace(aWhitespaces);
1041 }
1042
processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)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
setDocumentLocator(const cssu::Reference<cssxs::XLocator> & xLocator)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 */
_startDocument()1056 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_startDocument( )
1057 throw (cssxs::SAXException, cssu::RuntimeException)
1058 {
1059 }
1060
_endDocument()1061 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endDocument( )
1062 throw (cssxs::SAXException, cssu::RuntimeException)
1063 {
1064 }
1065
_startElement(const rtl::OUString & aName,const cssu::Sequence<cssxcsax::XMLAttribute> & aAttributes)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
_endElement(const rtl::OUString & aName)1075 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_endElement( const rtl::OUString& aName )
1076 throw (cssxs::SAXException, cssu::RuntimeException)
1077 {
1078 endElement( aName );
1079 }
1080
_characters(const rtl::OUString & aChars)1081 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_characters( const rtl::OUString& aChars )
1082 throw (cssxs::SAXException, cssu::RuntimeException)
1083 {
1084 characters( aChars );
1085 }
1086
_ignorableWhitespace(const rtl::OUString & aWhitespaces)1087 void SAL_CALL XMLDocumentWrapper_XmlSecImpl::_ignorableWhitespace( const rtl::OUString& aWhitespaces )
1088 throw (cssxs::SAXException, cssu::RuntimeException)
1089 {
1090 ignorableWhitespace( aWhitespaces );
1091 }
1092
_processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)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
_setDocumentLocator(sal_Int32,sal_Int32,const rtl::OUString &,const rtl::OUString &)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
XMLDocumentWrapper_XmlSecImpl_getImplementationName()1104 rtl::OUString XMLDocumentWrapper_XmlSecImpl_getImplementationName ()
1105 throw (cssu::RuntimeException)
1106 {
1107 return rtl::OUString ( RTL_ASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1108 }
1109
XMLDocumentWrapper_XmlSecImpl_supportsService(const rtl::OUString & ServiceName)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
XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames()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
XMLDocumentWrapper_XmlSecImpl_createInstance(const cssu::Reference<cssl::XMultiServiceFactory> &)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 */
getImplementationName()1134 rtl::OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName( )
1135 throw (cssu::RuntimeException)
1136 {
1137 return XMLDocumentWrapper_XmlSecImpl_getImplementationName();
1138 }
supportsService(const rtl::OUString & rServiceName)1139 sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const rtl::OUString& rServiceName )
1140 throw (cssu::RuntimeException)
1141 {
1142 return XMLDocumentWrapper_XmlSecImpl_supportsService( rServiceName );
1143 }
getSupportedServiceNames()1144 cssu::Sequence< rtl::OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames( )
1145 throw (cssu::RuntimeException)
1146 {
1147 return XMLDocumentWrapper_XmlSecImpl_getSupportedServiceNames();
1148 }
1149
1150