LibreOffice Module xmlsecurity (master) 1
saxeventkeeperimpl.cxx
Go to the documentation of this file.
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
22#include "buffernode.hxx"
23#include "elementmark.hxx"
24#include "elementcollector.hxx"
25#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
26#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
27#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
28#include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp>
30#include <osl/diagnose.h>
31#include <rtl/ustrbuf.hxx>
32
33#include <algorithm>
34
36 :m_pCurrentBufferNode(nullptr),
37 m_nNextElementMarkId(1),
38 m_pNewBlocker(nullptr),
39 m_pCurrentBlockingBufferNode(nullptr),
40 m_bIsReleasing(false),
41 m_bIsForwarding(false)
42{
43 m_vElementMarkBuffers.reserve(2);
44 m_vNewElementCollectors.reserve(2);
46}
47
49{
50 /*
51 * delete the BufferNode tree
52 */
53 m_pRootBufferNode.reset();
54
56
57 /*
58 * delete all unfreed ElementMarks
59 */
61 m_pNewBlocker = nullptr;
62}
63
65/****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
66 *
67 * NAME
68 * setCurrentBufferNode -- set a new active BufferNode.
69 *
70 * SYNOPSIS
71 * setCurrentBufferNode( pBufferNode );
72 *
73 * FUNCTION
74 * connects this BufferNode into the BufferNode tree as a child of the
75 * current active BufferNode. Then makes this BufferNode as the current
76 * active BufferNode.
77 * If the previous active BufferNode points to the root
78 * BufferNode, which means that no buffering operation was proceeding,
79 * then notifies the status change listener that buffering operation
80 * will begin at once.
81 *
82 * INPUTS
83 * pBufferNode - a BufferNode which will be the new active BufferNode
84 ******************************************************************************/
85{
86 if (pBufferNode == m_pCurrentBufferNode)
87 return;
88
91 {
92 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(true);
93 }
94
95 if (pBufferNode->getParent() == nullptr)
96 {
97 m_pCurrentBufferNode->addChild(std::unique_ptr<BufferNode>(pBufferNode));
98 pBufferNode->setParent(m_pCurrentBufferNode);
99 }
100
101 m_pCurrentBufferNode = pBufferNode;
102}
103
105/****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
106 *
107 * NAME
108 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
109 *
110 * SYNOPSIS
111 * pBufferNode = addNewElementMarkBuffers( );
112 *
113 * FUNCTION
114 * if there are new ElementCollector or new Blocker to be added, then
115 * connect all of them with the current BufferNode. In case of the
116 * current BufferNode doesn't exist, creates one.
117 * Clears up the new ElementCollector list and the new Blocker pointer.
118 *
119 * RESULT
120 * pBufferNode - the BufferNode that has been connected with both new
121 * ElementCollectors and new Blocker.
122 ******************************************************************************/
123{
124 BufferNode* pBufferNode = nullptr;
125
126 if (m_pNewBlocker || !m_vNewElementCollectors.empty() )
127 {
128 /*
129 * When the current BufferNode is right pointing to the current
130 * working element in the XMLDocumentWrapper component, then
131 * no new BufferNode is needed to create.
132 * This situation can only happen in the "Forwarding" mode.
133 */
134 if ( (m_pCurrentBufferNode != nullptr) &&
136 {
137 pBufferNode = m_pCurrentBufferNode;
138 }
139 else
140 {
141 pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
142 }
143
144 if (m_pNewBlocker != nullptr)
145 {
146 pBufferNode->setBlocker(m_pNewBlocker);
147
148 /*
149 * If no blocking before, then notify the status change listener that
150 * the SAXEventKeeper has entered "blocking" status, during which, no
151 * SAX events will be forwarded to the next document handler.
152 */
153 if (m_pCurrentBlockingBufferNode == nullptr)
154 {
155 m_pCurrentBlockingBufferNode = pBufferNode;
156
158 {
159 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(true);
160 }
161 }
162
163 m_pNewBlocker = nullptr;
164 }
165
166 for( const auto& i : m_vNewElementCollectors )
167 {
168 pBufferNode->addElementCollector(i);
169 }
171 }
172
173 return pBufferNode;
174}
175
177/****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
178 *
179 * NAME
180 * findElementMarkBuffer -- finds an ElementMark.
181 *
182 * SYNOPSIS
183 * pElementMark = findElementMarkBuffer( nId );
184 *
185 * FUNCTION
186 * searches an ElementMark with the particular Id in the ElementMark
187 * list.
188 *
189 * INPUTS
190 * nId - the Id of the ElementMark to be searched.
191 *
192 * RESULT
193 * pElementMark - the ElementMark with the particular Id, or NULL when
194 * no such Id exists.
195 ******************************************************************************/
196{
197 ElementMark* pElementMark = nullptr;
198
199 for( auto&& ii : m_vElementMarkBuffers )
200 {
201 if ( nId == ii->getBufferId())
202 {
203 pElementMark = const_cast<ElementMark*>(ii.get());
204 break;
205 }
206 }
207
208 return pElementMark;
209}
210
212/****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
213 *
214 * NAME
215 * removeElementMarkBuffer -- removes an ElementMark
216 *
217 * SYNOPSIS
218 * removeElementMarkBuffer( nId );
219 *
220 * FUNCTION
221 * removes an ElementMark with the particular Id in the ElementMark list.
222 *
223 * INPUTS
224 * nId - the Id of the ElementMark to be removed.
225 ******************************************************************************/
226{
227 auto ii = std::find_if(m_vElementMarkBuffers.begin(), m_vElementMarkBuffers.end(),
228 [nId](std::unique_ptr<const ElementMark>& rElementMark) { return nId == rElementMark->getBufferId(); }
229 );
230 if (ii == m_vElementMarkBuffers.end())
231 return;
232
233 /*
234 * checks whether this ElementMark still in the new ElementCollect array
235 */
236 auto jj = std::find_if(m_vNewElementCollectors.begin(), m_vNewElementCollectors.end(),
237 [&ii](const ElementCollector* pElementCollector) { return ii->get() == pElementCollector; }
238 );
239 if (jj != m_vNewElementCollectors.end())
240 m_vNewElementCollectors.erase(jj);
241
242 /*
243 * checks whether this ElementMark is the new Blocker
244 */
245 if (ii->get() == m_pNewBlocker)
246 {
247 m_pNewBlocker = nullptr;
248 }
249
250 m_vElementMarkBuffers.erase( ii );
251}
252
254 BufferNode const * pBufferNode, sal_Int32 nIndent) const
255/****** SAXEventKeeperImpl/printBufferNode ***********************************
256 *
257 * NAME
258 * printBufferNode -- retrieves the information of a BufferNode and its
259 * branch.
260 *
261 * SYNOPSIS
262 * info = printBufferNode( pBufferNode, nIndent );
263 *
264 * FUNCTION
265 * all retrieved information includes:
266 * 1. whether it is the current BufferNode;
267 * 2. whether it is the current blocking BufferNode;
268 * 3. the name of the parent element;
269 * 4. the name of this element;
270 * 5. all ElementCollectors working on this BufferNode;
271 * 6. the Blocker working on this BufferNode;
272 * 7. all child BufferNodes' information.
273 *
274 * INPUTS
275 * pBufferNode - the BufferNode from where information will be retrieved.
276 * nIndent - how many space characters prefixed before the output
277 * message.
278 *
279 * RESULT
280 * info - the information string
281 ******************************************************************************/
282{
283 OUStringBuffer rc;
284
285 for ( int i=0; i<nIndent; ++i )
286 {
287 rc.append(" ");
288 }
289
290 if (pBufferNode == m_pCurrentBufferNode)
291 {
292 rc.append("[%]");
293 }
294
295 if (pBufferNode == m_pCurrentBlockingBufferNode)
296 {
297 rc.append("[B]");
298 }
299
300 rc.append(" " + m_xXMLDocument->getNodeName(pBufferNode->getXMLElement()));
301
302 BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
303 if (pParent != nullptr)
304 {
305 rc.append("[" + m_xXMLDocument->getNodeName(pParent->getXMLElement()) + "]");
306 }
307
308 rc.append(":EC=" + pBufferNode->printChildren() + " BR=");
309
310 ElementMark * pBlocker = pBufferNode->getBlocker();
311 if (pBlocker != nullptr)
312 {
313 rc.append( OUString::number(pBlocker->getBufferId()) +
314 "(SecId=" + OUString::number( pBlocker->getSecurityId() ) + ") ");
315 }
316 rc.append("\n");
317
318 std::vector< std::unique_ptr<BufferNode> > const & vChildren = pBufferNode->getChildren();
319 for( const auto& jj : vChildren )
320 {
321 rc.append(printBufferNode(jj.get(), nIndent+4));
322 }
323
324 return rc.makeStringAndClear();
325}
326
327css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
329/****** SAXEventKeeperImpl/collectChildWorkingElement ************************
330 *
331 * NAME
332 * collectChildWorkingElement -- collects a BufferNode's all child
333 * Elements.
334 *
335 * SYNOPSIS
336 * list = collectChildWorkingElement( pBufferNode );
337 *
338 * INPUTS
339 * pBufferNode - the BufferNode whose child Elements will be collected.
340 *
341 * RESULT
342 * list - the child Elements list.
343 ******************************************************************************/
344{
345 std::vector< std::unique_ptr<BufferNode> > const & vChildren = pBufferNode->getChildren();
346
347 css::uno::Sequence < css::uno::Reference<
348 css::xml::wrapper::XXMLElementWrapper > > aChildrenCollection ( vChildren.size());
349
350 std::transform(vChildren.begin(), vChildren.end(), aChildrenCollection.getArray(),
351 [](const auto& i) { return i->getXMLElement(); });
352
353 return aChildrenCollection;
354}
355
357 BufferNode* pBufferNode, bool bClearRoot) const
358/****** SAXEventKeeperImpl/smashBufferNode ***********************************
359 *
360 * NAME
361 * smashBufferNode -- removes a BufferNode along with its working
362 * element.
363 *
364 * SYNOPSIS
365 * smashBufferNode( pBufferNode, bClearRoot );
366 *
367 * FUNCTION
368 * removes the BufferNode's working element from the DOM document, while
369 * reserves all ancestor paths for its child BufferNodes.
370 * when any of the BufferNode's ancestor element is useless, removes it
371 * too.
372 * removes the BufferNode from the BufferNode tree.
373 *
374 * INPUTS
375 * pBufferNode - the BufferNode to be removed
376 * bClearRoot - whether the root element also needs to be cleared up.
377 *
378 * NOTES
379 * when removing a Blocker's BufferNode, the bClearRoot flag should be
380 * true. Because a Blocker can buffer many SAX events which are not used
381 * by any other ElementCollector or Blocker.
382 * When the bClearRoot is set to true, the root BufferNode will be first
383 * cleared, with a stop flag setting at the next Blocking BufferNode. This
384 * operation can delete all useless buffered SAX events which are only
385 * needed by the Blocker to be deleted.
386 ******************************************************************************/
387{
388 if (pBufferNode->hasAnything())
389 return;
390
391 BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
392
393 /*
394 * delete the XML data
395 */
396 if (pParent == m_pRootBufferNode.get())
397 {
398 bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == nullptr);
399 bool bIsBlockInside = false;
400 bool bIsBlockingAfterward = false;
401
402 /*
403 * If this is a blocker, then remove any out-element data
404 * which caused by blocking. The removal process will stop
405 * at the next blocker to avoid removing any useful data.
406 */
407 if (bClearRoot)
408 {
409 css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
410 aChildElements = collectChildWorkingElement(m_pRootBufferNode.get());
411
412 /*
413 * the clearUselessData only clearup the content in the
414 * node, not the node itself.
415 */
416 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
417 aChildElements,
418 bIsNotBlocking?nullptr:
419 (m_pCurrentBlockingBufferNode->getXMLElement()));
420
421 /*
422 * remove the node if it is empty, then if its parent is also
423 * empty, remove it, then if the next parent is also empty,
424 * remove it,..., until parent become null.
425 */
426 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
427 }
428
429 /*
430 * if blocking, check the relationship between this BufferNode and
431 * the current blocking BufferNode.
432 */
433 if ( !bIsNotBlocking )
434 {
435 /*
436 * the current blocking BufferNode is a descendant of this BufferNode.
437 */
438 bIsBlockInside = (nullptr != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
439
440 /*
441 * the current blocking BufferNode locates behind this BufferNode in tree
442 * order.
443 */
444 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
445 }
446
447 /*
448 * this BufferNode's working element needs to be deleted only when
449 * 1. there is no blocking, or
450 * 2. the current blocking BufferNode is a descendant of this BufferNode,
451 * (then in the BufferNode's working element, the useless data before the blocking
452 * element should be deleted.) or
453 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
454 * (then the useless data between the blocking element and the working element
455 * should be deleted.).
456 * Otherwise, this working element should not be deleted.
457 */
458 if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
459 {
460 css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
461 aChildElements = collectChildWorkingElement(pBufferNode);
462
463 /*
464 * the clearUselessData only clearup the content in the
465 * node, not the node itself.
466 */
467 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
468 aChildElements,
469 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
470 nullptr);
471
472 /*
473 * remove the node if it is empty, then if its parent is also
474 * empty, remove it, then if the next parent is also empty,
475 * remove it,..., until parent become null.
476 */
477 m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
478 }
479 }
480
481 sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
482
483 std::vector< std::unique_ptr<BufferNode> > vChildren = pBufferNode->releaseChildren();
484 pParent->removeChild(pBufferNode); // delete buffernode
485
486 for( auto& i : vChildren )
487 {
488 i->setParent(pParent);
489 pParent->addChild(std::move(i), nIndex);
490 nIndex++;
491 }
492}
493
495 BufferNode* pStartBufferNode)
496/****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
497 *
498 * NAME
499 * findNextBlockingBufferNode -- finds the next blocking BufferNode
500 * behind the particular BufferNode.
501 *
502 * SYNOPSIS
503 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
504 *
505 * INPUTS
506 * pStartBufferNode - the BufferNode from where to search the next
507 * blocking BufferNode.
508 *
509 * RESULT
510 * pBufferNode - the next blocking BufferNode, or NULL if no such
511 * BufferNode exists.
512 ******************************************************************************/
513{
514 BufferNode* pNext = nullptr;
515
516 if (pStartBufferNode != nullptr)
517 {
518 pNext = pStartBufferNode;
519
520 while (nullptr != (pNext = const_cast<BufferNode*>(pNext->getNextNodeByTreeOrder())))
521 {
522 if (pNext->getBlocker() != nullptr)
523 {
524 break;
525 }
526 }
527 }
528
529 return pNext;
530}
531
533/****** SAXEventKeeperImpl/diffuse *******************************************
534 *
535 * NAME
536 * diffuse -- diffuse the notification.
537 *
538 * SYNOPSIS
539 * diffuse( pBufferNode );
540 *
541 * FUNCTION
542 * diffuse the collecting completion notification from the specific
543 * BufferNode along its parent link, until an ancestor which is not
544 * completely received is met.
545 *
546 * INPUTS
547 * pBufferNode - the BufferNode from which the notification will be
548 * diffused.
549 ******************************************************************************/
550{
551 BufferNode* pParent = pBufferNode;
552
553 while(pParent->isAllReceived())
554 {
555 pParent->elementCollectorNotify();
556 pParent = const_cast<BufferNode*>(pParent->getParent());
557 }
558}
559
561/****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
562 *
563 * NAME
564 * releaseElementMarkBuffer -- releases useless ElementMarks
565 *
566 * SYNOPSIS
567 * releaseElementMarkBuffer( );
568 *
569 * FUNCTION
570 * releases each ElementMark in the releasing list
571 * m_vReleasedElementMarkBuffers.
572 * The operation differs between an ElementCollector and a Blocker.
573 ******************************************************************************/
574{
575 m_bIsReleasing = true;
576 while (!m_vReleasedElementMarkBuffers.empty())
577 {
578 auto pId = m_vReleasedElementMarkBuffers.begin();
579 sal_Int32 nId = *pId;
581
582 ElementMark* pElementMark = findElementMarkBuffer(nId);
583
584 if (pElementMark != nullptr)
585 {
586 if (css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR
587 == pElementMark->getType())
588 /*
589 * it is a EC
590 */
591 {
592 ElementCollector* pElementCollector = static_cast<ElementCollector*>(pElementMark);
593
594 css::xml::crypto::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
595 /*
596 * Delete the EC from the buffer node.
597 */
598 BufferNode* pBufferNode = pElementCollector->getBufferNode();
599 pBufferNode->removeElementCollector(pElementCollector);
600
601 if ( nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY)
602 {
603 pBufferNode->notifyBranch();
604 }
605
606 /*
607 * delete the ElementMark
608 */
609 pElementCollector = nullptr;
610 pElementMark = nullptr;
612
613 /*
614 * delete the BufferNode
615 */
616 diffuse(pBufferNode);
617 smashBufferNode(pBufferNode, false);
618 }
619 else
620 /*
621 * it is a Blocker
622 */
623 {
624 /*
625 * Delete the TH from the buffer node.
626 */
627 BufferNode *pBufferNode = pElementMark->getBufferNode();
628 pBufferNode->setBlocker(nullptr);
629
630 /*
631 * If there is a following handler and no blocking now, then
632 * forward this event
633 */
634 if (m_pCurrentBlockingBufferNode == pBufferNode)
635 {
636 /*
637 * Before forwarding, the next blocking point needs to be
638 * found.
639 */
641
642 /*
643 * Forward the blocked events between these two STHs.
644 */
645 if (m_xNextHandler.is())
646 {
647 BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
648 BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
649
650 m_pCurrentBufferNode = pBufferNode;
652
653 m_bIsForwarding = true;
654
655 m_xXMLDocument->generateSAXEvents(
657 this,
658 pBufferNode->getXMLElement(),
659 (pTempCurrentBlockingBufferNode == nullptr)?nullptr:(pTempCurrentBlockingBufferNode->getXMLElement()));
660
661 m_bIsForwarding = false;
662
663 m_pCurrentBufferNode = pTempCurrentBufferNode;
664 if (m_pCurrentBlockingBufferNode == nullptr)
665 {
666 m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
667 }
668 }
669
670 if (m_pCurrentBlockingBufferNode == nullptr &&
672 {
673 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(false);
674 }
675 }
676
677 /*
678 * delete the ElementMark
679 */
680 pElementMark = nullptr;
682
683 /*
684 * delete the BufferNode
685 */
686 diffuse(pBufferNode);
687 smashBufferNode(pBufferNode, true);
688 }
689 }
690 }
691
692 m_bIsReleasing = false;
693
694 if (!m_pRootBufferNode->hasAnything() &&
695 !m_pRootBufferNode->hasChildren() &&
697 {
698 m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(true);
699 }
700}
701
703/****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
704 *
705 * NAME
706 * markElementMarkBuffer -- marks an ElementMark to be released
707 *
708 * SYNOPSIS
709 * markElementMarkBuffer( nId );
710 *
711 * FUNCTION
712 * puts the ElementMark with the particular Id into the releasing list,
713 * checks whether the releasing process is running, if not then launch
714 * this process.
715 *
716 * INPUTS
717 * nId - the Id of the ElementMark which will be released
718 ******************************************************************************/
719{
721 if ( !m_bIsReleasing )
722 {
724 }
725}
726
728 css::xml::crypto::sax::ElementMarkPriority nPriority,
729 bool bModifyElement,
730 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
731/****** SAXEventKeeperImpl/createElementCollector ****************************
732 *
733 * NAME
734 * createElementCollector -- creates a new ElementCollector on the
735 * incoming element.
736 *
737 * SYNOPSIS
738 * nId = createElementCollector( nSecurityId, nPriority,
739 * bModifyElement,
740 * xReferenceResolvedListener );
741 *
742 * FUNCTION
743 * allocs a new Id, then create an ElementCollector with this Id value.
744 * Add the new created ElementCollector to the new ElementCollecotor list.
745 *
746 * INPUTS
747 * nPriority - the priority of the new ElementCollector
748 * bModifyElement -whether this BufferNode will modify the content of
749 * the corresponding element it works on
750 * xReferenceResolvedListener - the listener for the new ElementCollector.
751 *
752 * RESULT
753 * nId - the Id of the new ElementCollector
754 ******************************************************************************/
755{
756 sal_Int32 nId = m_nNextElementMarkId;
758
759 ElementCollector* pElementCollector
760 = new ElementCollector(
761 nId,
762 nPriority,
763 bModifyElement,
764 xReferenceResolvedListener);
765
766 m_vElementMarkBuffers.push_back(
767 std::unique_ptr<const ElementMark>(pElementCollector));
768
769 /*
770 * All the new EC to initial EC array.
771 */
772 m_vNewElementCollectors.push_back( pElementCollector );
773
774 return nId;
775}
776
777
779/****** SAXEventKeeperImpl/createBlocker *************************************
780 *
781 * NAME
782 * createBlocker -- creates a new Blocker on the incoming element.
783 *
784 * SYNOPSIS
785 * nId = createBlocker( nSecurityId );
786 *
787 * RESULT
788 * nId - the Id of the new Blocker
789 ******************************************************************************/
790{
791 sal_Int32 nId = m_nNextElementMarkId;
793
794 OSL_ASSERT(m_pNewBlocker == nullptr);
795
796 m_pNewBlocker = new ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nId);
797 m_vElementMarkBuffers.push_back(
798 std::unique_ptr<const ElementMark>(m_pNewBlocker));
799
800 return nId;
801}
802
803/* XSAXEventKeeper */
805{
807 css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY,
808 false,
809 nullptr);
810}
811
813{
815}
816
818{
819 return createBlocker();
820}
821
822void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
823{
825}
826
828{
829 return (m_pCurrentBlockingBufferNode != nullptr);
830}
831
832css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL
834{
835 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc;
836
837 ElementMark* pElementMark = findElementMarkBuffer(id);
838 if (pElementMark != nullptr)
839 {
840 rc = pElementMark->getBufferNode()->getXMLElement();
841 }
842
843 return rc;
844}
845
847 sal_Int32 id,
848 const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement )
849{
850 if (aElement.is())
851 {
852 m_xXMLDocument->rebuildIDLink(aElement);
853
854 ElementMark* pElementMark = findElementMarkBuffer(id);
855
856 if (pElementMark != nullptr)
857 {
858 BufferNode* pBufferNode = pElementMark->getBufferNode();
859 if (pBufferNode != nullptr)
860 {
861 const bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
862 pBufferNode->setXMLElement(aElement);
863
864 if (bIsCurrent)
865 {
866 m_xXMLDocument->setCurrentElement(aElement);
867 }
868 }
869 }
870 }
871 else
872 {
874 }
875}
876
877css::uno::Reference< css::xml::sax::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
878 const css::uno::Reference< css::xml::sax::XDocumentHandler >& xNewHandler )
879{
880 css::uno::Reference< css::xml::sax::XDocumentHandler > xOldHandler = m_xNextHandler;
881
882 m_xNextHandler = xNewHandler;
883 return xOldHandler;
884}
885
887{
888 OUString rc = "ElementMarkBuffers: size = "
889 + OUString::number(m_vElementMarkBuffers.size())
890 + "\nCurrentBufferNode: "
892 + "\n" + printBufferNode(m_pRootBufferNode.get(), 0);
893
894 return rc;
895}
896
897css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
898{
899 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc;
900
901 if (m_pCurrentBlockingBufferNode != nullptr)
902 {
904 }
905
906 return rc;
907}
908
909/* XSecuritySAXEventKeeper */
911 css::xml::crypto::sax::ElementMarkPriority priority,
912 sal_Bool modifyElement )
913{
915 priority,
916 modifyElement,
917 nullptr);
918}
919
920void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
921{
922 ElementMark* pElementMark = findElementMarkBuffer(id);
923 if (pElementMark != nullptr)
924 {
925 pElementMark->setSecurityId(securityId);
926 }
927}
928
929
930/* XReferenceResolvedBroadcaster */
932 sal_Int32 referenceId,
933 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener )
934{
935 ElementCollector* pElementCollector = static_cast<ElementCollector*>(findElementMarkBuffer(referenceId));
936 if (pElementCollector != nullptr)
937 {
938 pElementCollector->setReferenceResolvedListener(listener);
939 }
940}
941
943 sal_Int32 /*referenceId*/,
944 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >&)
945{
946}
947
948/* XSAXEventKeeperStatusChangeBroadcaster */
950 const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener )
951{
953}
954
956 const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >&)
957{
958}
959
960/* XDocumentHandler */
962{
963 if ( m_xNextHandler.is())
964 {
965 m_xNextHandler->startDocument();
966 }
967}
968
970{
971 if ( m_xNextHandler.is())
972 {
973 m_xNextHandler->endDocument();
974 }
975}
976
978 const OUString& aName,
979 const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
980{
981 /*
982 * If there is a following handler and no blocking now, then
983 * forward this event
984 */
985 if ((m_pCurrentBlockingBufferNode == nullptr) &&
986 (m_xNextHandler.is()) &&
987 (!m_bIsForwarding) &&
988 (m_pNewBlocker == nullptr))
989 {
990 m_xNextHandler->startElement(aName, xAttribs);
991 }
992 /*
993 * If not forwarding, buffer this startElement.
994 */
995 if (!m_bIsForwarding)
996 {
997 sal_Int32 nLength = xAttribs->getLength();
998 css::uno::Sequence< css::xml::csax::XMLAttribute > aAttributes (nLength);
999 auto aAttributesRange = asNonConstRange(aAttributes);
1000
1001 for ( int i = 0; i<nLength; ++i )
1002 {
1003 aAttributesRange[i].sName = xAttribs->getNameByIndex(static_cast<short>(i));
1004 aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast<short>(i));
1005 }
1006
1007 m_xCompressedDocumentHandler->compressedStartElement(aName, aAttributes);
1008 }
1009
1010 BufferNode* pBufferNode = addNewElementMarkBuffers();
1011 if (pBufferNode != nullptr)
1012 {
1013 setCurrentBufferNode(pBufferNode);
1014 }
1015}
1016
1017void SAL_CALL SAXEventKeeperImpl::endElement( const OUString& aName )
1018{
1019 const bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1020
1021 /*
1022 * If there is a following handler and no blocking now, then
1023 * forward this event
1024 */
1025 if ((m_pCurrentBlockingBufferNode == nullptr) &&
1026 (m_xNextHandler.is()) &&
1027 (!m_bIsForwarding))
1028 {
1029 m_xNextHandler->endElement(aName);
1030 }
1031
1032 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1034 (!m_xXMLDocument->isCurrentElementEmpty()))
1035 {
1036 if (!m_bIsForwarding)
1037 {
1038 m_xCompressedDocumentHandler->compressedEndElement(aName);
1039 }
1040
1041 /*
1042 * If the current buffer node has not notified yet, and
1043 * the current buffer node is waiting for the current element,
1044 * then let it notify.
1045 */
1046 if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode.get()))
1047 {
1048 BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1050
1051 pOldCurrentBufferNode->setReceivedAll();
1052
1053 if ((m_pCurrentBufferNode == m_pRootBufferNode.get()) &&
1055 {
1056 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(false);
1057 }
1058 }
1059 }
1060 else
1061 {
1062 if (!m_bIsForwarding)
1063 {
1064 m_xXMLDocument->removeCurrentElement();
1065 }
1066 }
1067}
1068
1069void SAL_CALL SAXEventKeeperImpl::characters( const OUString& aChars )
1070{
1071 if (m_bIsForwarding)
1072 return;
1073
1074 if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is())
1075 {
1076 m_xNextHandler->characters(aChars);
1077 }
1078
1079 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1081 {
1082 m_xCompressedDocumentHandler->compressedCharacters(aChars);
1083 }
1084}
1085
1086void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const OUString& aWhitespaces )
1087{
1088 characters( aWhitespaces );
1089}
1090
1092 const OUString& aTarget, const OUString& aData )
1093{
1094 if (m_bIsForwarding)
1095 return;
1096
1097 if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is())
1098 {
1099 m_xNextHandler->processingInstruction(aTarget, aData);
1100 }
1101
1102 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1104 {
1105 m_xCompressedDocumentHandler->compressedProcessingInstruction(aTarget, aData);
1106 }
1107}
1108
1109void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >&)
1110{
1111}
1112
1113/* XInitialization */
1114void SAL_CALL SAXEventKeeperImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
1115{
1116 OSL_ASSERT(aArguments.getLength() == 1);
1117
1119 m_xDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY );
1120 m_xCompressedDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY );
1121
1122 m_pRootBufferNode.reset( new BufferNode(m_xXMLDocument->getCurrentElement()) );
1124}
1125
1127{
1128 return "com.sun.star.xml.security.framework.SAXEventKeeperImpl";
1129}
1130
1131css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( )
1132{
1133 return { "com.sun.star.xml.crypto.sax.SAXEventKeeper" };
1134}
1135
1136/* XServiceInfo */
1138{
1140}
1141
1142sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName )
1143{
1144 return cppu::supportsService(this, rServiceName);
1145}
1146
1147css::uno::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
1148{
1150}
1151
1152/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void notifyBranch()
Definition: buffernode.cxx:623
void removeChild(const BufferNode *pChild)
Definition: buffernode.cxx:377
void setParent(const BufferNode *pParent)
Definition: buffernode.cxx:433
void elementCollectorNotify()
Definition: buffernode.cxx:650
const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > & getXMLElement() const
Definition: buffernode.hxx:108
void setBlocker(const ElementMark *pBlocker)
Definition: buffernode.cxx:149
const BufferNode * getNextNodeByTreeOrder() const
Definition: buffernode.cxx:542
void setXMLElement(const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > &xXMLElement)
Definition: buffernode.cxx:618
void removeElementCollector(const ElementCollector *pElementCollector)
Definition: buffernode.cxx:120
bool isAllReceived() const
Definition: buffernode.hxx:87
ElementMark * getBlocker() const
Definition: buffernode.hxx:90
const BufferNode * getParent() const
Definition: buffernode.hxx:102
void addElementCollector(const ElementCollector *pElementCollector)
Definition: buffernode.cxx:97
void setReceivedAll()
Definition: buffernode.cxx:71
void addChild(std::unique_ptr< BufferNode > pChild, sal_Int32 nPosition)
Definition: buffernode.cxx:318
std::vector< std::unique_ptr< BufferNode > > const & getChildren() const
Definition: buffernode.cxx:278
sal_Int32 indexOfChild(const BufferNode *pChild) const
Definition: buffernode.cxx:403
css::xml::crypto::sax::ElementMarkPriority getPriority() const
void setReferenceResolvedListener(const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > &referenceResolvedListener)
css::xml::crypto::sax::ElementMarkType getType() const
Definition: elementmark.hxx:63
void setSecurityId(sal_Int32 nSecurityId)
Definition: elementmark.cxx:58
sal_Int32 getBufferId() const
Definition: elementmark.hxx:64
BufferNode * getBufferNode() const
Definition: elementmark.hxx:59
sal_Int32 getSecurityId() const
Definition: elementmark.hxx:61
OUString printBufferNode(BufferNode const *pBufferNode, sal_Int32 nIndent) const
std::vector< const ElementCollector * > m_vNewElementCollectors
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual void SAL_CALL removeSAXEventKeeperStatusChangeListener(const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener > &listener) override
virtual void SAL_CALL addSAXEventKeeperStatusChangeListener(const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener > &listener) override
virtual void SAL_CALL setElement(sal_Int32 id, const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > &aElement) override
virtual void SAL_CALL setSecurityId(sal_Int32 id, sal_Int32 securityId) override
virtual void SAL_CALL removeBlocker(sal_Int32 id) override
virtual void SAL_CALL endDocument() override
virtual void SAL_CALL removeElementCollector(sal_Int32 id) override
virtual OUString SAL_CALL getImplementationName() override
css::uno::Reference< css::xml::sax::XDocumentHandler > m_xDocumentHandler
BufferNode * m_pCurrentBufferNode
virtual void SAL_CALL processingInstruction(const OUString &aTarget, const OUString &aData) override
virtual sal_Int32 SAL_CALL addBlocker() override
virtual void SAL_CALL startElement(const OUString &aName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttribs) override
virtual void SAL_CALL addReferenceResolvedListener(sal_Int32 referenceId, const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > &listener) override
virtual css::uno::Reference< css::xml::sax::XDocumentHandler > SAL_CALL setNextHandler(const css::uno::Reference< css::xml::sax::XDocumentHandler > &xNewHandler) override
css::uno::Reference< css::xml::wrapper::XXMLDocumentWrapper > m_xXMLDocument
virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL getCurrentBlockingNode() override
void setCurrentBufferNode(BufferNode *pBufferNode)
sal_Int32 createElementCollector(css::xml::crypto::sax::ElementMarkPriority nPriority, bool bModifyElement, const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > &xReferenceResolvedListener)
virtual sal_Int32 SAL_CALL addElementCollector() override
virtual void SAL_CALL startDocument() override
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
ElementMark * findElementMarkBuffer(sal_Int32 nId) const
static css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > collectChildWorkingElement(BufferNode const *pBufferNode)
virtual void SAL_CALL ignorableWhitespace(const OUString &aWhitespaces) override
std::vector< sal_Int32 > m_vReleasedElementMarkBuffers
BufferNode * addNewElementMarkBuffers()
css::uno::Reference< css::xml::sax::XDocumentHandler > m_xNextHandler
void smashBufferNode(BufferNode *pBufferNode, bool bClearRoot) const
virtual void SAL_CALL removeReferenceResolvedListener(sal_Int32 referenceId, const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > &listener) override
virtual sal_Int32 SAL_CALL addSecurityElementCollector(css::xml::crypto::sax::ElementMarkPriority priority, sal_Bool modifyElement) override
css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener > m_xSAXEventKeeperStatusChangeListener
void removeElementMarkBuffer(sal_Int32 nId)
virtual OUString SAL_CALL printBufferNodeTree() override
std::unique_ptr< BufferNode > m_pRootBufferNode
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL setDocumentLocator(const css::uno::Reference< css::xml::sax::XLocator > &xLocator) override
static BufferNode * findNextBlockingBufferNode(BufferNode *pStartBufferNode)
virtual void SAL_CALL endElement(const OUString &aName) override
virtual ~SAXEventKeeperImpl() override
virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL getElement(sal_Int32 id) override
css::uno::Reference< css::xml::csax::XCompressedDocumentHandler > m_xCompressedDocumentHandler
virtual void SAL_CALL characters(const OUString &aChars) override
BufferNode * m_pCurrentBlockingBufferNode
virtual sal_Bool SAL_CALL isBlocking() override
static void diffuse(BufferNode *pBufferNode)
void markElementMarkBuffer(sal_Int32 nId)
std::vector< std::unique_ptr< const ElementMark > > m_vElementMarkBuffers
Sequence< PropertyValue > aArguments
sal_Int32 nIndex
OUString aName
constexpr OUStringLiteral aData
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
sal_Int16 nId
css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames()
OUString SAXEventKeeperImpl_getImplementationName()
unsigned char sal_Bool
sal_Int32 nLength