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