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