diff options
Diffstat (limited to '')
-rw-r--r-- | forms/source/xforms/submission.cxx | 609 | ||||
-rw-r--r-- | forms/source/xforms/submission.hxx | 232 | ||||
-rw-r--r-- | forms/source/xforms/submission/replace.cxx | 131 | ||||
-rw-r--r-- | forms/source/xforms/submission/serialization.hxx | 60 | ||||
-rw-r--r-- | forms/source/xforms/submission/serialization_app_xml.cxx | 126 | ||||
-rw-r--r-- | forms/source/xforms/submission/serialization_app_xml.hxx | 40 | ||||
-rw-r--r-- | forms/source/xforms/submission/serialization_urlencoded.cxx | 181 | ||||
-rw-r--r-- | forms/source/xforms/submission/serialization_urlencoded.hxx | 47 | ||||
-rw-r--r-- | forms/source/xforms/submission/submission.hxx | 137 | ||||
-rw-r--r-- | forms/source/xforms/submission/submission_get.cxx | 103 | ||||
-rw-r--r-- | forms/source/xforms/submission/submission_get.hxx | 33 | ||||
-rw-r--r-- | forms/source/xforms/submission/submission_post.cxx | 78 | ||||
-rw-r--r-- | forms/source/xforms/submission/submission_post.hxx | 32 | ||||
-rw-r--r-- | forms/source/xforms/submission/submission_put.cxx | 67 | ||||
-rw-r--r-- | forms/source/xforms/submission/submission_put.hxx | 33 |
15 files changed, 1909 insertions, 0 deletions
diff --git a/forms/source/xforms/submission.cxx b/forms/source/xforms/submission.cxx new file mode 100644 index 000000000..d8d81abd5 --- /dev/null +++ b/forms/source/xforms/submission.cxx @@ -0,0 +1,609 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "submission.hxx" + +#include "model.hxx" +#include "binding.hxx" +#include "mip.hxx" +#include "evaluationcontext.hxx" +#include "submission/submission_put.hxx" +#include "submission/submission_post.hxx" +#include "submission/submission_get.hxx" + +#include <rtl/ustring.hxx> +#include <com/sun/star/lang/NoSupportException.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/xforms/XModel.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/DocumentBuilder.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/task/XInteractionContinuation.hpp> +#include <com/sun/star/xforms/InvalidDataOnSubmitException.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <cppuhelper/exc_hlp.hxx> +#include <comphelper/interaction.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/servicehelper.hxx> +#include <memory> +#include <string_view> + +using com::sun::star::util::VetoException; +using com::sun::star::form::submission::XSubmissionVetoListener; +using com::sun::star::lang::WrappedTargetException; +using com::sun::star::lang::NoSupportException; +using com::sun::star::task::XInteractionHandler; +using com::sun::star::task::XInteractionRequest; +using com::sun::star::task::XInteractionContinuation; +using com::sun::star::xforms::XModel; +using com::sun::star::xforms::InvalidDataOnSubmitException; +using com::sun::star::xml::xpath::XXPathObject; +using com::sun::star::frame::XFrame; +using xforms::Submission; +using xforms::Model; +using xforms::MIP; + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::xml::dom; + +Submission::Submission() : + mbIndent(), + mbOmitXmlDeclaration(), + mbStandalone(), + msReplace( "none" ) +{ + initializePropertySet(); +} + +Submission::~Submission() noexcept +{ +} + + +void Submission::setModel( const Reference<XModel>& xModel ) +{ + mxModel = xModel; +} + + +void Submission::setID( const OUString& sID ) +{ + msID = sID; +} + + +void Submission::setBind( const OUString& sBind ) +{ + msBind = sBind; +} + +OUString Submission::getRef() const +{ + return maRef.getExpression(); +} + +void Submission::setRef( const OUString& sRef ) +{ + maRef.setExpression( sRef ); +} + + +void Submission::setAction( const OUString& sAction ) +{ + msAction = sAction; +} + + +void Submission::setMethod( const OUString& sMethod ) +{ + msMethod = sMethod; +} + + +void Submission::setVersion( const OUString& sVersion ) +{ + msVersion = sVersion; +} + + +void Submission::setIndent( bool bIndent ) +{ + mbIndent = bIndent; +} + + +void Submission::setMediaType( const OUString& sMediaType ) +{ + msMediaType = sMediaType; +} + + +void Submission::setEncoding( const OUString& sEncoding ) +{ + msEncoding = sEncoding; +} + + +void Submission::setOmitXmlDeclaration( bool bOmitXmlDeclaration ) +{ + mbOmitXmlDeclaration = bOmitXmlDeclaration; +} + + +void Submission::setStandalone( bool bStandalone ) +{ + mbStandalone = bStandalone; +} + + +void Submission::setCDataSectionElement( const OUString& sCDataSectionElement ) +{ + msCDataSectionElement = sCDataSectionElement; +} + + +void Submission::setReplace( const OUString& sReplace ) +{ + msReplace = sReplace; +} + + +void Submission::setSeparator( const OUString& sSeparator ) +{ + msSeparator = sSeparator; +} + + +void Submission::setIncludeNamespacePrefixes( const Sequence< OUString >& rIncludeNamespacePrefixes ) +{ + msIncludeNamespacePrefixes = rIncludeNamespacePrefixes; +} + +bool Submission::doSubmit( const Reference< XInteractionHandler >& xHandler ) +{ + liveCheck(); + + // construct XXPathObject for submission doc; use bind in preference of ref + EvaluationContext aEvalContext; + ComputedExpression aExpression; + if( !msBind.isEmpty() ) + { + Binding* pBinding = comphelper::getFromUnoTunnel<Binding>( mxModel->getBinding(msBind) ); + if( pBinding != nullptr ) + { + aExpression.setExpression( pBinding->getBindingExpression() ); + aEvalContext = pBinding->getEvaluationContext(); + } + // TODO: else: illegal binding name -> raise error + } + else if( !maRef.getExpression().isEmpty() ) + { + aExpression.setExpression( maRef.getExpression() ); + aEvalContext = comphelper::getFromUnoTunnel<Model>( mxModel )->getEvaluationContext(); + } + else + { + aExpression.setExpression( "/" ); + aEvalContext = comphelper::getFromUnoTunnel<Model>( mxModel )->getEvaluationContext(); + } + aExpression.evaluate( aEvalContext ); + Reference<XXPathObject> xResult = aExpression.getXPath(); + OSL_ENSURE( xResult.is(), "no result?" ); + + // early out if we have not obtained any result + if( ! xResult.is() ) + return false; + + + // Reference< XNodeList > aList = xResult->getNodeList(); + OUString aMethod = getMethod(); + + // strip whitespace-only text node for get submission + Reference< XDocumentFragment > aFragment = createSubmissionDocument( + xResult, aMethod.equalsIgnoreAsciiCase("get")); + + // submit result; set encoding, etc. + std::unique_ptr<CSubmission> xSubmission; + if (aMethod.equalsIgnoreAsciiCase("PUT")) + xSubmission.reset(new CSubmissionPut( getAction(), aFragment)); + else if (aMethod.equalsIgnoreAsciiCase("post")) + xSubmission.reset(new CSubmissionPost( getAction(), aFragment)); + else if (aMethod.equalsIgnoreAsciiCase("get")) + xSubmission.reset(new CSubmissionGet( getAction(), aFragment)); + else + { + OSL_FAIL("Unsupported xforms submission method"); + return false; + } + + if (!xSubmission->IsWebProtocol()) + return false; + + CSubmission::SubmissionResult aResult = xSubmission->submit( xHandler ); + + if (aResult == CSubmission::SUCCESS) + { + Reference< XDocument > aInstanceDoc = getInstanceDocument(xResult); + aResult = xSubmission->replace(getReplace(), aInstanceDoc, Reference< XFrame >()); + } + + return ( aResult == CSubmission::SUCCESS ); +} + +Sequence<sal_Int8> Submission::getUnoTunnelId() +{ + static const comphelper::UnoIdInit aImplementationId; + return aImplementationId.getSeq(); +} + + +void Submission::liveCheck() +{ + bool bValid = mxModel.is(); + + if( ! bValid ) + throw RuntimeException(); +} + +Model* Submission::getModelImpl() const +{ + Model* pModel = nullptr; + if( mxModel.is() ) + pModel = comphelper::getFromUnoTunnel<Model>( mxModel ); + return pModel; +} + + +// Property-Set implementation + + +#define HANDLE_ID 0 +#define HANDLE_Bind 1 +#define HANDLE_Ref 2 +#define HANDLE_Action 3 +#define HANDLE_Method 4 +#define HANDLE_Version 5 +#define HANDLE_Indent 6 +#define HANDLE_MediaType 7 +#define HANDLE_Encoding 8 +#define HANDLE_OmitXmlDeclaration 9 +#define HANDLE_Standalone 10 +#define HANDLE_CDataSectionElement 11 +#define HANDLE_Replace 12 +#define HANDLE_Separator 13 +#define HANDLE_IncludeNamespacePrefixes 14 +#define HANDLE_Model 15 + +void Submission::initializePropertySet() +{ + registerProperty( css::beans::Property("ID", HANDLE_ID, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setID, &Submission::getID) ); + + registerProperty( css::beans::Property("Bind", HANDLE_Bind, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setBind, &Submission::getBind) ); + + registerProperty( css::beans::Property("Ref", HANDLE_Ref, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setRef, &Submission::getRef) ); + + registerProperty( css::beans::Property("Action", HANDLE_Action, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setAction, &Submission::getAction) ); + + registerProperty( css::beans::Property("Method", HANDLE_Method, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setMethod, &Submission::getMethod) ); + + registerProperty( css::beans::Property("Version", HANDLE_Version, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setVersion, &Submission::getVersion) ); + + registerProperty( css::beans::Property("Indent", HANDLE_Indent, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND ), + new BooleanPropertyAccessor< Submission >(this, &Submission::setIndent, &Submission::getIndent)); + + registerProperty( css::beans::Property("MediaType", HANDLE_MediaType, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setMediaType, &Submission::getMediaType) ); + + registerProperty( css::beans::Property("Encoding", HANDLE_Encoding, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setEncoding, &Submission::getEncoding) ); + + registerProperty( css::beans::Property("OmitXmlDeclaration", HANDLE_OmitXmlDeclaration, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND ), + new BooleanPropertyAccessor< Submission >(this, &Submission::setOmitXmlDeclaration, &Submission::getOmitXmlDeclaration)); + + registerProperty( css::beans::Property("Standalone", HANDLE_Standalone, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND ), + new BooleanPropertyAccessor< Submission >(this, &Submission::setStandalone, &Submission::getStandalone)); + + registerProperty( css::beans::Property("CDataSectionElement", HANDLE_CDataSectionElement, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setCDataSectionElement, &Submission::getCDataSectionElement) ); + + registerProperty( css::beans::Property("Replace", HANDLE_Replace, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setReplace, &Submission::getReplace) ); + + registerProperty( css::beans::Property("Separator", HANDLE_Separator, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, OUString >(this, &Submission::setSeparator, &Submission::getSeparator) ); + + registerProperty( css::beans::Property("IncludeNamespacePrefixes", HANDLE_IncludeNamespacePrefixes, cppu::UnoType<Sequence<OUString>>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, Sequence<OUString> >(this, &Submission::setIncludeNamespacePrefixes, &Submission::getIncludeNamespacePrefixes) ); + + registerProperty( css::beans::Property("Model", HANDLE_Model, cppu::UnoType<Reference<XModel>>::get(), css::beans::PropertyAttribute::BOUND ), + new DirectPropertyAccessor< Submission, Reference<XModel> >(this, &Submission::setModel, &Submission::getModel) ); + + initializePropertyValueCache( HANDLE_Indent ); + initializePropertyValueCache( HANDLE_OmitXmlDeclaration ); + initializePropertyValueCache( HANDLE_Standalone ); +} + +sal_Bool SAL_CALL Submission::convertFastPropertyValue( + Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue ) +{ + if ( nHandle == HANDLE_IncludeNamespacePrefixes ) + { + // for convenience reasons (????), we accept a string which contains + // a comma-separated list of namespace prefixes + OUString sTokenList; + if ( rValue >>= sTokenList ) + { + std::vector< OUString > aPrefixes; + sal_Int32 p = 0; + while ( p >= 0 ) + aPrefixes.push_back( sTokenList.getToken( 0, ',', p ) ); + + Sequence< OUString > aConvertedPrefixes( aPrefixes.data(), aPrefixes.size() ); + return PropertySetBase::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, Any( aConvertedPrefixes ) ); + } + } + + return PropertySetBase::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); +} + +OUString SAL_CALL Submission::getName() +{ + return getID(); +} + +void SAL_CALL Submission::setName( const OUString& sID ) +{ + setID( sID ); +} + + +sal_Int64 SAL_CALL Submission::getSomething( + const Sequence<sal_Int8>& aId ) +{ + return comphelper::getSomethingImpl(aId, this); +} + + +static OUString lcl_message( std::u16string_view rID, std::u16string_view rText ) +{ + OUString aMessage = OUString::Concat("XForms submission '") + rID + "' failed" + rText + "."; + return aMessage; +} + +void SAL_CALL Submission::submitWithInteraction( + const Reference<XInteractionHandler>& _rxHandler ) +{ + // as long as this class is not really threadsafe, we need to copy + // the members we're interested in + Reference< XModel > xModel( mxModel ); + OUString sID( msID ); + + if ( !xModel.is() || msID.isEmpty() ) + throw RuntimeException( + "This is not a valid submission object.", + *this + ); + + Model* pModel = comphelper::getFromUnoTunnel<Model>( xModel ); + OSL_ENSURE( pModel != nullptr, "illegal model?" ); + + // #i36765# #i47248# warning on submission of illegal data + // check for validity (and query user if invalid) + bool bValid = pModel->isValid(); + if( ! bValid ) + { + InvalidDataOnSubmitException aInvalidDataException( + lcl_message(sID, u" due to invalid data" ), *this ); + + if( _rxHandler.is() ) + { + // laboriously create interaction request + rtl::Reference<comphelper::OInteractionRequest> pRequest + = new comphelper::OInteractionRequest( + Any( aInvalidDataException ) ); + + rtl::Reference<comphelper::OInteractionApprove> pContinue + = new comphelper::OInteractionApprove(); + pRequest->addContinuation( pContinue ); + + rtl::Reference<comphelper::OInteractionDisapprove> pCancel + = new comphelper::OInteractionDisapprove(); + pRequest->addContinuation( pCancel ); + + // ask the handler... + _rxHandler->handle( pRequest ); + OSL_ENSURE( pContinue->wasSelected() || pCancel->wasSelected(), + "handler didn't select" ); + + // and continue, if user chose 'continue' + if( pContinue->wasSelected() ) + bValid = true; + } + + // abort if invalid (and user didn't tell us to continue) + if( ! bValid ) + throw aInvalidDataException; + } + + // attempt submission + bool bResult = false; + try + { + bResult = doSubmit( _rxHandler ); + } + catch( const VetoException& ) + { + OSL_FAIL( "Model::submit: Hmm. How can a single submission have a veto right?" ); + // allowed to leave + throw; + } + catch( const Exception& ) + { + css::uno::Any anyEx = cppu::getCaughtException(); + // exception caught: re-throw as wrapped target exception + throw WrappedTargetException( + lcl_message( sID, u" due to exception being thrown" ), + *this, anyEx ); + } + + if( !bResult ) + { + // other failure: throw wrapped target exception, too. + throw WrappedTargetException( + lcl_message( sID, std::u16string_view() ), *this, Any() ); + } + mxModel->rebuild(); +} + +void SAL_CALL Submission::submit( ) +{ + submitWithInteraction( nullptr ); +} + +void SAL_CALL Submission::addSubmissionVetoListener( const Reference< XSubmissionVetoListener >& /*listener*/ ) +{ + // TODO + throw NoSupportException(); +} + +void SAL_CALL Submission::removeSubmissionVetoListener( const Reference< XSubmissionVetoListener >& /*listener*/ ) +{ + // TODO + throw NoSupportException(); +} + +static bool isIgnorable(const Reference< XNode >& aNode) +{ + // ignore whitespace-only textnodes + if (aNode->getNodeType() == NodeType_TEXT_NODE) + { + OUString aTrimmedValue = aNode->getNodeValue().trim(); + if (aTrimmedValue.isEmpty()) return true; + } + + return false; +} + +// recursively copy relevant nodes from A to B +static void cloneNodes(Model& aModel, const Reference< XNode >& dstParent, const Reference< XNode >& source, bool bRemoveWSNodes) +{ + if (!source.is()) return; + + Reference< XNode > cur = source; + Reference< XDocument > dstDoc = dstParent->getOwnerDocument(); + Reference< XNode > imported; + + if (!cur.is()) + return; + + // is this node relevant? + MIP mip = aModel.queryMIP(cur); + if(mip.isRelevant() && !(bRemoveWSNodes && isIgnorable(cur))) + { + imported = dstDoc->importNode(cur, false); + imported = dstParent->appendChild(imported); + // append source children to new imported parent + for( cur = cur->getFirstChild(); cur.is(); cur = cur->getNextSibling() ) + cloneNodes(aModel, imported, cur, bRemoveWSNodes); + } +} +Reference< XDocument > Submission::getInstanceDocument(const Reference< XXPathObject >& aObj) +{ + using namespace css::xml::xpath; + // result + Reference< XDocument > aDocument; + + if (aObj->getObjectType() == XPathObjectType_XPATH_NODESET) + { + Reference< XNodeList > aList = aObj->getNodeList(); + if (aList->getLength() > 0) + aDocument = aList->item(0)->getOwnerDocument(); + } + return aDocument; +} + +Reference< XDocumentFragment > Submission::createSubmissionDocument(const Reference< XXPathObject >& aObj, bool bRemoveWSNodes) +{ + using namespace css::xml::xpath; + Reference< XDocumentBuilder > aDocBuilder = DocumentBuilder::create(comphelper::getProcessComponentContext()); + Reference< XDocument > aDocument = aDocBuilder->newDocument(); + Reference< XDocumentFragment > aFragment = aDocument->createDocumentFragment(); + + + if (aObj->getObjectType() == XPathObjectType_XPATH_NODESET) + { + Reference< XNodeList > aList = aObj->getNodeList(); + Reference< XNode > aListItem; + for (sal_Int32 i=0; i < aList->getLength(); i++) + { + aListItem = aList->item(i); + if (aListItem->getNodeType()==NodeType_DOCUMENT_NODE) + aListItem = (Reference< XDocument >(aListItem, UNO_QUERY))->getDocumentElement(); + // copy relevant nodes from instance into fragment + cloneNodes(*getModelImpl(), aFragment, aListItem, bRemoveWSNodes); + } + } + return aFragment; +} + +// some forwarding: XPropertySet is implemented in our base class, +// but also available as base of XSubmission +Reference< css::beans::XPropertySetInfo > SAL_CALL Submission::getPropertySetInfo( ) +{ + return PropertySetBase::getPropertySetInfo(); +} +void SAL_CALL Submission::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) +{ + PropertySetBase::setPropertyValue( aPropertyName, aValue ); +} +Any SAL_CALL Submission::getPropertyValue( const OUString& PropertyName ) +{ + return PropertySetBase::getPropertyValue( PropertyName ); +} +void SAL_CALL Submission::addPropertyChangeListener( const OUString& aPropertyName, const Reference< css::beans::XPropertyChangeListener >& xListener ) +{ + PropertySetBase::addPropertyChangeListener( aPropertyName, xListener ); +} +void SAL_CALL Submission::removePropertyChangeListener( const OUString& aPropertyName, const Reference< css::beans::XPropertyChangeListener >& aListener ) +{ + PropertySetBase::removePropertyChangeListener( aPropertyName, aListener ); +} +void SAL_CALL Submission::addVetoableChangeListener( const OUString& PropertyName, const Reference< css::beans::XVetoableChangeListener >& aListener ) +{ + PropertySetBase::addVetoableChangeListener( PropertyName, aListener ); +} +void SAL_CALL Submission::removeVetoableChangeListener( const OUString& PropertyName, const Reference< css::beans::XVetoableChangeListener >& aListener ) +{ + PropertySetBase::removeVetoableChangeListener( PropertyName, aListener ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission.hxx b/forms/source/xforms/submission.hxx new file mode 100644 index 000000000..1e7f17e4c --- /dev/null +++ b/forms/source/xforms/submission.hxx @@ -0,0 +1,232 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <cppuhelper/implbase.hxx> +#include "propertysetbase.hxx" +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> +#include <com/sun/star/xml/xpath/XXPathObject.hpp> +#include <com/sun/star/xforms/XSubmission.hpp> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include "computedexpression.hxx" + +// forward declaractions +namespace com::sun::star { + namespace xforms { class XModel; } + namespace uno { class Any; } + namespace beans { class UnknownPropertyException; + class PropertyVetoException; } + namespace lang { class IllegalArgumentException; + class WrappedTargetException; } +} +namespace xforms { class Model; } + + +namespace xforms +{ + +/** An XForms submission. + * + * See http://www.w3.org/TR/xforms/ for more information. + */ +typedef cppu::ImplInheritanceHelper< + PropertySetBase, + css::lang::XUnoTunnel, + css::xforms::XSubmission +> Submission_t; + +class Submission : public Submission_t +{ + // submission properties + OUString msID; + OUString msBind; + ComputedExpression maRef; + OUString msAction; + OUString msMethod; + OUString msVersion; + bool mbIndent; + OUString msMediaType; + OUString msEncoding; + bool mbOmitXmlDeclaration; + bool mbStandalone; + OUString msCDataSectionElement; + OUString msReplace; + OUString msSeparator; + css::uno::Sequence< OUString > msIncludeNamespacePrefixes; + +private: + + /// the Model to which this Submission belongs; may be NULL + css::uno::Reference<css::xforms::XModel> mxModel; + + // this will extract the document from the model that will be submitted + css::uno::Reference< css::xml::dom::XDocumentFragment > + createSubmissionDocument(const css::uno::Reference< css::xml::xpath::XXPathObject >& aObject, + bool bRemoveWSNodes); + static css::uno::Reference< css::xml::dom::XDocument > + getInstanceDocument(const css::uno::Reference< css::xml::xpath::XXPathObject >& aObject); + +public: + Submission(); + virtual ~Submission() noexcept override; + + + // property methods: get/set value + + + /// get XForms model + css::uno::Reference<css::xforms::XModel> + getModel() const { return mxModel;} + + /// set XForms model + void setModel( + const css::uno::Reference<css::xforms::XModel>& ); + + OUString getID() const { return msID;} /// get ID for this submission + void setID( const OUString& ); /// set ID for this submission + + OUString getBind() const { return msBind;} + void setBind( const OUString& ); + + OUString getRef() const; + void setRef( const OUString& ); + + OUString getAction() const { return msAction;} + void setAction( const OUString& ); + + OUString getMethod() const { return msMethod;} + void setMethod( const OUString& ); + + OUString getVersion() const { return msVersion;} + void setVersion( const OUString& ); + + bool getIndent() const { return mbIndent;} + void setIndent( bool ); + + OUString getMediaType() const { return msMediaType;} + void setMediaType( const OUString& ); + + OUString getEncoding() const { return msEncoding;} + void setEncoding( const OUString& ); + + bool getOmitXmlDeclaration() const { return mbOmitXmlDeclaration;} + void setOmitXmlDeclaration( bool ); + + bool getStandalone() const { return mbStandalone;} + void setStandalone( bool ); + + OUString getCDataSectionElement() const { return msCDataSectionElement;} + void setCDataSectionElement( const OUString& ); + + OUString getReplace() const { return msReplace;} + void setReplace( const OUString& ); + + OUString getSeparator() const { return msSeparator;} + void setSeparator( const OUString& ); + + css::uno::Sequence< OUString > getIncludeNamespacePrefixes() const { return msIncludeNamespacePrefixes;} + void setIncludeNamespacePrefixes( const css::uno::Sequence< OUString >& ); + + /** perform the submission + * @returns if submission was successful */ + bool doSubmit( const css::uno::Reference< css::task::XInteractionHandler >& aHandler ); + + // helpers for UNO tunnel + static css::uno::Sequence<sal_Int8> getUnoTunnelId(); + +private: + + /// check whether object is live, and throw suitable exception if not + /// (to be used be API methods before acting on the object) + /// + /// @throws css::uno::RuntimeException + void liveCheck(); + + /// get the model implementation + xforms::Model* getModelImpl() const; + +protected: + + + // XPropertySet & friends: + // implement abstract methods from PropertySetHelper + + + virtual sal_Bool SAL_CALL convertFastPropertyValue( + css::uno::Any& rConvertedValue, + css::uno::Any& rOldValue, + sal_Int32 nHandle, + const css::uno::Any& rValue ) override; + +private: + void initializePropertySet(); + + +public: + + + // XNamed: + // get/set name + + + virtual OUString SAL_CALL getName() override; + + virtual void SAL_CALL setName( const OUString& ) override; + + + // XUnoTunnel + + + virtual sal_Int64 SAL_CALL getSomething( + const css::uno::Sequence<sal_Int8>& ) override; + + + // XSubmission + + + virtual void SAL_CALL submit( ) override; + virtual void SAL_CALL submitWithInteraction( + const css::uno::Reference< css::task::XInteractionHandler >& aHandler ) override; + virtual void SAL_CALL addSubmissionVetoListener( + const css::uno::Reference< css::form::submission::XSubmissionVetoListener >& listener ) override; + virtual void SAL_CALL removeSubmissionVetoListener( + const css::uno::Reference< css::form::submission::XSubmissionVetoListener >& listener ) override; + + + // XPropertySet + // (need to disambiguate this) + + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; + virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; + virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override; + virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override; + virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override; + virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; + virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; +}; + + +} // namespace xforms + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/replace.cxx b/forms/source/xforms/submission/replace.cxx new file mode 100644 index 000000000..e6154ef61 --- /dev/null +++ b/forms/source/xforms/submission/replace.cxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include "submission.hxx" +#include "serialization_app_xml.hxx" + +#include <rtl/ustring.hxx> +#include <rtl/ref.hxx> +#include <tools/diagnose_ex.h> +#include <o3tl/string_view.hxx> + +#include <comphelper/processfactory.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/DocumentBuilder.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/task/InteractionHandler.hpp> + +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::task; +using namespace com::sun::star::xml::dom; + +CSubmission::SubmissionResult CSubmission::replace(std::u16string_view aReplace, const Reference<XDocument>& aDocument, const Reference<XFrame>& aFrame) +{ + if (!m_aResultStream.is()) + return CSubmission::UNKNOWN_ERROR; + + try { + Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); + if (o3tl::equalsIgnoreAsciiCase(aReplace, u"all") + || o3tl::equalsIgnoreAsciiCase(aReplace, u"document")) { + Reference< XComponentLoader > xLoader; + if (aFrame.is()) + xLoader.set(aFrame, UNO_QUERY); + + if (!xLoader.is()) + xLoader.set( Desktop::create(xContext), UNO_QUERY_THROW); + + // open the stream from the result... + // build media descriptor + Sequence< PropertyValue > descriptor{ + PropertyValue("InputStream", + -1, Any(m_aResultStream), PropertyState_DIRECT_VALUE), + PropertyValue("ReadOnly", + -1, Any(true), PropertyState_DIRECT_VALUE) + }; + + OUString aURL = m_aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE); + xLoader->loadComponentFromURL(aURL, "_default", FrameSearchFlag::ALL, descriptor); + + return CSubmission::SUCCESS; + + } else if (o3tl::equalsIgnoreAsciiCase(aReplace, u"instance")) { + if (aDocument.is()) { + // parse the result stream into a new document + Reference< XDocumentBuilder > xBuilder(DocumentBuilder::create(xContext)); + Reference< XDocument > aNewDocument = xBuilder->parse(m_aResultStream); + + if (aNewDocument.is()) { + // and replace the content of the current instance + Reference< XElement > oldRoot = aDocument->getDocumentElement(); + Reference< XElement > newRoot = aNewDocument->getDocumentElement(); + + Reference< XNode > aImportedNode = aDocument->importNode(newRoot, true); + aDocument->replaceChild(aImportedNode, oldRoot); + return CSubmission::SUCCESS; + } else { + return CSubmission::UNKNOWN_ERROR; + } + } else { + // nothing to replace + return CSubmission::UNKNOWN_ERROR; + } + } else if (o3tl::equalsIgnoreAsciiCase(aReplace, u"none")) { + // do nothing \o/ + return CSubmission::SUCCESS; + } + } catch (const Exception&) { + TOOLS_WARN_EXCEPTION( "forms.xforms", "Exception during replace"); + } + return CSubmission::UNKNOWN_ERROR; +} + +::std::unique_ptr< CSerialization > CSubmission::createSerialization(const Reference< XInteractionHandler >& _xHandler,Reference<XCommandEnvironment>& _rOutEnv) +{ + // PUT always uses application/xml + ::std::unique_ptr< CSerialization > apSerialization(new CSerializationAppXML()); + apSerialization->setSource(m_aFragment); + apSerialization->serialize(); + + // create a commandEnvironment and use the default interaction handler + rtl::Reference<CCommandEnvironmentHelper> pHelper = new CCommandEnvironmentHelper; + if( _xHandler.is() ) + pHelper->m_aInteractionHandler = _xHandler; + else + pHelper->m_aInteractionHandler.set( + InteractionHandler::createWithParent(m_xContext, nullptr), UNO_QUERY_THROW); + + rtl::Reference<CProgressHandlerHelper> pProgressHelper = new CProgressHandlerHelper; + pHelper->m_aProgressHandler.set(pProgressHelper); + + // UCB has ownership of environment... + _rOutEnv = pHelper; + return apSerialization; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/serialization.hxx b/forms/source/xforms/submission/serialization.hxx new file mode 100644 index 000000000..19f072b0b --- /dev/null +++ b/forms/source/xforms/submission/serialization.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> + +/** +Serialize an XObject +*/ + +class CSerialization +{ +protected: + css::uno::Reference<css::xml::dom::XDocumentFragment> m_aFragment; + +public: + virtual ~CSerialization() {} + + /** + sets the XObject that is to serialized + */ + void setSource(const css::uno::Reference<css::xml::dom::XDocumentFragment>& aFragment) + { + m_aFragment = aFragment; + } + + /** + start the serialization process + */ + virtual void serialize() = 0; + + /** + get the serialized bytes. + reads up to buffer->getLength() bytes and returns the number of + bytes read. + returns -1 on error + */ + virtual css::uno::Reference<css::io::XInputStream> getInputStream() = 0; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/serialization_app_xml.cxx b/forms/source/xforms/submission/serialization_app_xml.cxx new file mode 100644 index 000000000..61729d027 --- /dev/null +++ b/forms/source/xforms/submission/serialization_app_xml.cxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "serialization_app_xml.hxx" + +#include <com/sun/star/io/Pipe.hpp> +#include <com/sun/star/xml/dom/DocumentBuilder.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <com/sun/star/xml/sax/XSAXSerializable.hpp> +#include <com/sun/star/xml/sax/Writer.hpp> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> + +#include <tools/diagnose_ex.h> +#include <comphelper/processfactory.hxx> + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::xml::dom::DocumentBuilder; +using ::com::sun::star::xml::dom::XNode; +using ::com::sun::star::xml::dom::XDocument; +using ::com::sun::star::xml::sax::XSAXSerializable; +using ::com::sun::star::beans::StringPair; +using ::com::sun::star::xml::dom::NodeType_DOCUMENT_NODE; +using ::com::sun::star::xml::dom::NodeType_ELEMENT_NODE; +using ::com::sun::star::xml::dom::XDocumentBuilder; +using ::com::sun::star::xml::sax::Writer; +using ::com::sun::star::xml::sax::XDocumentHandler; + +CSerializationAppXML::CSerializationAppXML() + : m_xBuffer(css::io::Pipe::create(comphelper::getProcessComponentContext())) +{ +} + +Reference< css::io::XInputStream > +CSerializationAppXML::getInputStream() +{ + // The pipes output is provided through it's + // XOutputStream interface aspect + return m_xBuffer; +} + +void +CSerializationAppXML::serialize_node(const Reference< XNode >& rNode) +{ + try + { + Reference< XSAXSerializable > xSerializer( rNode, UNO_QUERY ); + if ( !xSerializer.is() ) + { + // ensure we have a "real" node + Reference< XNode > xNode = rNode; + if ( xNode->getNodeType() == NodeType_DOCUMENT_NODE ) + { + Reference< XDocument > const xDoc( xNode, UNO_QUERY_THROW ); + xNode.set( xDoc->getDocumentElement(), UNO_QUERY_THROW ); + } + ENSURE_OR_RETURN_VOID( xNode->getNodeType() == NodeType_ELEMENT_NODE, + "CSerializationAppXML::serialize_node: invalid node type!" ); + + // create a new document + Reference< XDocumentBuilder > const xDocBuilder = DocumentBuilder::create( comphelper::getProcessComponentContext() ); + Reference< XDocument > const xDocument( xDocBuilder->newDocument(), UNO_SET_THROW ); + + // copy the to-be-serialized node + Reference< XNode > const xImportedNode( xDocument->importNode( xNode, true ), UNO_SET_THROW ); + xDocument->appendChild( xImportedNode ); + + // ask the doc for the serializer + xSerializer.set( xDocument, UNO_QUERY ); + } + + ENSURE_OR_RETURN_VOID( xSerializer.is(), + "CSerializationAppXML::serialize_node: no serialization access to the node/document!" ); + + // create a SAXWriter to take the serialization events, and connect it to our pipe + Reference< css::xml::sax::XWriter > const xSaxWriter = Writer::create( comphelper::getProcessComponentContext() ); + xSaxWriter->setOutputStream( Reference< css::io::XOutputStream >( m_xBuffer, UNO_QUERY_THROW) ); + + // do the serialization + xSerializer->serialize( Reference< XDocumentHandler >(xSaxWriter, UNO_QUERY_THROW), Sequence< StringPair >() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("forms.xforms"); + } +} + +void +CSerializationAppXML::serialize() +{ + if (!m_aFragment.is()) return; + + Reference< XNode > cur = m_aFragment->getFirstChild(); + while (cur.is()) + { + serialize_node(cur); + cur = cur->getNextSibling(); + } + m_xBuffer->closeOutput(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/serialization_app_xml.hxx b/forms/source/xforms/submission/serialization_app_xml.hxx new file mode 100644 index 000000000..51fb1eb54 --- /dev/null +++ b/forms/source/xforms/submission/serialization_app_xml.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/io/XPipe.hpp> + +#include "serialization.hxx" + +class CSerializationAppXML : public CSerialization +{ +private: + css::uno::Reference<css::io::XPipe> m_xBuffer; + + void serialize_node(const css::uno::Reference<css::xml::dom::XNode>& aNode); + +public: + CSerializationAppXML(); + + virtual void serialize() override; + virtual css::uno::Reference<css::io::XInputStream> getInputStream() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/serialization_urlencoded.cxx b/forms/source/xforms/submission/serialization_urlencoded.cxx new file mode 100644 index 000000000..22a625ccb --- /dev/null +++ b/forms/source/xforms/submission/serialization_urlencoded.cxx @@ -0,0 +1,181 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <com/sun/star/io/Pipe.hpp> +#include <com/sun/star/xml/xpath/XPathObjectType.hpp> +#include <com/sun/star/xml/dom/XNode.hpp> +#include <com/sun/star/xml/dom/XText.hpp> +#include <com/sun/star/xml/dom/XNodeList.hpp> +#include <com/sun/star/xml/dom/NodeType.hpp> +#include <rtl/character.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <comphelper/processfactory.hxx> + +#include <stdio.h> + +#include "serialization_urlencoded.hxx" + +using namespace css::uno; +using namespace css::io; +using namespace css::xml::xpath; +using namespace css::xml::dom; + +CSerializationURLEncoded::CSerializationURLEncoded() + : m_aPipe(Pipe::create(comphelper::getProcessComponentContext())) +{ +} + + +/* + rfc2396 + reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + "$" | "," + mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" + unreserved = alphanum | mark +*/ +bool CSerializationURLEncoded::is_unreserved(char c) +{ + if (rtl::isAsciiAlphanumeric(static_cast<unsigned char>(c))) + return true; + switch (c) { + case '-': + case '_': + case '.': + case '!': + case '~': + case '*': + case '\'': + case '(': + case ')': + return true; + } + return false; +} +void CSerializationURLEncoded::encode_and_append( + std::u16string_view aString, OStringBuffer& aBuffer) +{ + OString utf8String = OUStringToOString(aString, RTL_TEXTENCODING_UTF8); + const sal_uInt8 *pString = reinterpret_cast< const sal_uInt8 * >( utf8String.getStr() ); + char tmpChar[4]; + + while( *pString != 0) + { + if( *pString < 0x80 ) + { + if ( is_unreserved(*pString) ) { + aBuffer.append(char(*pString)); + } else if (*pString == 0x20) { + aBuffer.append('+'); + } else if (*pString == 0x0d && *(pString+1) == 0x0a) { + aBuffer.append("%0D%0A"); + pString++; + } else if (*pString == 0x0a) { + aBuffer.append("%0D%0A"); + } else { + snprintf(tmpChar, 4, "%%%X", *pString % 0x100); + aBuffer.append(tmpChar); + } + } else { + snprintf(tmpChar, 4, "%%%X", *pString % 0x100); + aBuffer.append(tmpChar); + while (*pString >= 0x80) { + // continuation... + pString++; + snprintf(tmpChar, 4, "%%%X", *pString % 0x100); + aBuffer.append(tmpChar); + } + } + pString++; + } +} + +void CSerializationURLEncoded::serialize_node(const Reference< XNode >& aNode) +{ + // serialize recursive + // every element node E that has a text child T will be serialized in document order + // <E1>T1<E2>T2</E2></E1><E3>T3</E3> -> E1=T2&E2=T2&E3=T3 (En := local name) + + // this node + Reference< XNodeList > aChildList = aNode->getChildNodes(); + Reference< XNode > aChild; + // is this an element node? + if (aNode->getNodeType() == NodeType_ELEMENT_NODE) + { + OUString aName = aNode->getNodeName(); + // find any text children + OUStringBuffer aValue; + Reference< XText > aText; + for(sal_Int32 i=0; i < aChildList->getLength(); i++) + { + aChild = aChildList->item(i); + if (aChild->getNodeType() == NodeType_TEXT_NODE) + { + aText.set(aChild, UNO_QUERY); + aValue.append(aText->getData()); + } + } + + // found anything? + if (!aValue.isEmpty()) + { + OUString aUnencValue = aValue.makeStringAndClear(); + OStringBuffer aEncodedBuffer; + encode_and_append(aName, aEncodedBuffer); + aEncodedBuffer.append("="); + encode_and_append(aUnencValue, aEncodedBuffer); + aEncodedBuffer.append("&"); + sal_Int8 const *pData = reinterpret_cast<sal_Int8 const *>(aEncodedBuffer.getStr()); + Sequence< sal_Int8 > sData(pData, aEncodedBuffer.getLength()); + m_aPipe->writeBytes(sData); + } + } + + // element children... + for(sal_Int32 i=0; i < aChildList->getLength(); i++) + { + aChild = aChildList->item(i); + // if this is an element node, it might be a candidate for serialization + if (aChild.is() && aChild->getNodeType() == NodeType_ELEMENT_NODE) + serialize_node(aChild); + } +} + +void CSerializationURLEncoded::serialize() +{ + + // output stream to the pipe buffer + + css::uno::Reference< css::xml::dom::XNode > cur = m_aFragment->getFirstChild(); + while (cur.is()) + { + serialize_node(cur); + cur = cur->getNextSibling(); + } + m_aPipe->closeOutput(); +} + +Reference< XInputStream > CSerializationURLEncoded::getInputStream() +{ + return m_aPipe; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/serialization_urlencoded.hxx b/forms/source/xforms/submission/serialization_urlencoded.hxx new file mode 100644 index 000000000..2ae91c1f1 --- /dev/null +++ b/forms/source/xforms/submission/serialization_urlencoded.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <string_view> + +#include <com/sun/star/io/XPipe.hpp> + +#include <rtl/strbuf.hxx> + +#include "serialization.hxx" + +class CSerializationURLEncoded : public CSerialization +{ +private: + css::uno::Reference<css::io::XPipe> m_aPipe; + + static bool is_unreserved(char); + static void encode_and_append(std::u16string_view aString, OStringBuffer& aBuffer); + void serialize_node(const css::uno::Reference<css::xml::dom::XNode>& aNode); + +public: + CSerializationURLEncoded(); + virtual void serialize() override; + virtual css::uno::Reference<css::io::XInputStream> getInputStream() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/submission.hxx b/forms/source/xforms/submission/submission.hxx new file mode 100644 index 000000000..ac80947aa --- /dev/null +++ b/forms/source/xforms/submission/submission.hxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <tools/urlobj.hxx> +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/xml/dom/XDocumentFragment.hpp> + +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/ucb/XProgressHandler.hpp> + +#include <com/sun/star/task/XInteractionHandler.hpp> + +#include <com/sun/star/frame/XFrame.hpp> + +#include <cppuhelper/implbase.hxx> + +#include "serialization.hxx" + +#include <memory> + +class CSubmissionPut; +class CSubmissionPost; +class CSubmissionGet; + +class CCommandEnvironmentHelper final : public cppu::WeakImplHelper< css::ucb::XCommandEnvironment > +{ + friend class CSubmissionPut; + friend class CSubmissionPost; + friend class CSubmissionGet; + friend class CSubmission; + + css::uno::Reference< css::task::XInteractionHandler > m_aInteractionHandler; + css::uno::Reference< css::ucb::XProgressHandler > m_aProgressHandler; + +public: + virtual css::uno::Reference< css::task::XInteractionHandler > SAL_CALL getInteractionHandler() override + { + return m_aInteractionHandler; + } + virtual css::uno::Reference< css::ucb::XProgressHandler > SAL_CALL getProgressHandler() override + { + return m_aProgressHandler; + } +}; + +class CProgressHandlerHelper final : public cppu::WeakImplHelper< css::ucb::XProgressHandler > +{ + friend class CSubmissionPut; + friend class CSubmissionPost; + friend class CSubmissionGet; + osl::Condition m_cFinished; + osl::Mutex m_mLock; + sal_Int32 m_count; +public: + CProgressHandlerHelper() + : m_count(0) + {} + virtual void SAL_CALL push( const css::uno::Any& /*aStatus*/) override + { + m_mLock.acquire(); + m_count++; + m_mLock.release(); + } + virtual void SAL_CALL update(const css::uno::Any& /*aStatus*/) override + { + } + virtual void SAL_CALL pop() override + { + m_mLock.acquire(); + m_count--; + if (m_count == 0) + m_cFinished.set(); + m_mLock.release(); + } +}; + +class CSubmission +{ + +protected: + INetURLObject m_aURLObj; + css::uno::Reference< css::xml::dom::XDocumentFragment > m_aFragment; + css::uno::Reference< css::io::XInputStream > m_aResultStream; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + + ::std::unique_ptr< CSerialization > createSerialization(const css::uno::Reference< css::task::XInteractionHandler >& aHandler + ,css::uno::Reference<css::ucb::XCommandEnvironment>& _rOutEnv); + +public: + enum SubmissionResult { + SUCCESS, + UNKNOWN_ERROR + }; + + CSubmission(std::u16string_view aURL, const css::uno::Reference< css::xml::dom::XDocumentFragment >& aFragment) + : m_aURLObj(aURL) + , m_aFragment(aFragment) + , m_xContext(::comphelper::getProcessComponentContext()) + {} + + bool IsWebProtocol() const + { + INetProtocol eProtocol = m_aURLObj.GetProtocol(); + return eProtocol == INetProtocol::Http || eProtocol == INetProtocol::Https; + } + + virtual ~CSubmission() {} + + virtual SubmissionResult submit(const css::uno::Reference< css::task::XInteractionHandler >& ) = 0; + + SubmissionResult replace(std::u16string_view, const css::uno::Reference< css::xml::dom::XDocument >&, const css::uno::Reference< css::frame::XFrame>&); + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/submission_get.cxx b/forms/source/xforms/submission/submission_get.cxx new file mode 100644 index 000000000..5a82aeae0 --- /dev/null +++ b/forms/source/xforms/submission/submission_get.cxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "submission_get.hxx" +#include "serialization_urlencoded.hxx" + +#include <rtl/strbuf.hxx> +#include <osl/diagnose.h> +#include <ucbhelper/content.hxx> +#include <com/sun/star/io/Pipe.hpp> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <tools/diagnose_ex.h> + +using namespace css::uno; +using namespace css::ucb; +using namespace css::task; +using namespace css::io; +using namespace osl; +using namespace ucbhelper; + + +CSubmissionGet::CSubmissionGet(std::u16string_view aURL, const css::uno::Reference< css::xml::dom::XDocumentFragment >& aFragment) + : CSubmission(aURL, aFragment) +{ +} + +CSubmission::SubmissionResult CSubmissionGet::submit(const css::uno::Reference< css::task::XInteractionHandler >& aInteractionHandler) +{ + // GET always uses application/x-www-formurlencoded + CSerializationURLEncoded aSerialization; + aSerialization.setSource(m_aFragment); + aSerialization.serialize(); + + css::uno::Reference< XInputStream > aInStream = aSerialization.getInputStream(); + + // create a commandEnvironment and use the default interaction handler + rtl::Reference<CCommandEnvironmentHelper> pHelper = new CCommandEnvironmentHelper; + if( aInteractionHandler.is() ) + pHelper->m_aInteractionHandler = aInteractionHandler; + else + pHelper->m_aInteractionHandler.set( + css::task::InteractionHandler::createWithParent(m_xContext, nullptr), UNO_QUERY_THROW); + rtl::Reference<CProgressHandlerHelper> pProgressHelper = new CProgressHandlerHelper; + pHelper->m_aProgressHandler.set(pProgressHelper); + + // UCB has ownership of environment... + css::uno::Reference< XCommandEnvironment > aEnvironment(pHelper); + + // append query string to the URL + try { + OStringBuffer aUTF8QueryURL(OUStringToOString(m_aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE), + RTL_TEXTENCODING_UTF8)); + OStringBuffer aQueryString; + + const sal_Int32 size = 1024; + sal_Int32 n = 0; + Sequence< sal_Int8 > aByteBuffer(size); + while ((n = aInStream->readSomeBytes(aByteBuffer, size-1)) != 0) + aQueryString.append(reinterpret_cast<char const *>(aByteBuffer.getConstArray()), n); + if (!aQueryString.isEmpty() && m_aURLObj.GetProtocol() != INetProtocol::File) + { + aUTF8QueryURL.append('?'); + aUTF8QueryURL.append(aQueryString); + } + OUString aQueryURL = OStringToOUString(aUTF8QueryURL.makeStringAndClear(), RTL_TEXTENCODING_UTF8); + ucbhelper::Content aContent(aQueryURL, aEnvironment, m_xContext); + css::uno::Reference< XOutputStream > aPipe( css::io::Pipe::create(m_xContext), UNO_QUERY_THROW ); + if (!aContent.openStream(aPipe)) + return UNKNOWN_ERROR; + // get reply + try { + m_aResultStream = aContent.openStream(); + } catch (const Exception&) { + OSL_FAIL("Cannot open reply stream from content"); + } + } catch (const Exception&) + { + // XXX + TOOLS_WARN_EXCEPTION( "forms.misc", "Exception during UCB operation."); + return UNKNOWN_ERROR; + } + + return SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/submission_get.hxx b/forms/source/xforms/submission/submission_get.hxx new file mode 100644 index 000000000..086fab25b --- /dev/null +++ b/forms/source/xforms/submission/submission_get.hxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "submission.hxx" + +class CSubmissionGet : public CSubmission +{ +public: + CSubmissionGet(std::u16string_view aURL, + const css::uno::Reference<css::xml::dom::XDocumentFragment>& aFragment); + virtual SubmissionResult + submit(const css::uno::Reference<css::task::XInteractionHandler>& aInteractionHandler) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/submission_post.cxx b/forms/source/xforms/submission/submission_post.cxx new file mode 100644 index 000000000..89ffd2323 --- /dev/null +++ b/forms/source/xforms/submission/submission_post.cxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <memory> + +#include "submission_post.hxx" + +#include <osl/diagnose.h> +#include <ucbhelper/content.hxx> +#include <ucbhelper/activedatasink.hxx> +#include <com/sun/star/ucb/PostCommandArgument2.hpp> +#include <tools/diagnose_ex.h> + +using namespace css::uno; +using namespace css::ucb; +using namespace css::task; +using namespace css::io; +using namespace osl; +using namespace ucbhelper; + + +CSubmissionPost::CSubmissionPost(std::u16string_view aURL, const css::uno::Reference< css::xml::dom::XDocumentFragment >& aFragment) + : CSubmission(aURL, aFragment) +{ +} + +CSubmission::SubmissionResult CSubmissionPost::submit(const css::uno::Reference< css::task::XInteractionHandler >& aInteractionHandler) +{ + // PUT always uses application/xml + css::uno::Reference< XCommandEnvironment > aEnvironment; + std::unique_ptr< CSerialization > apSerialization(createSerialization(aInteractionHandler,aEnvironment)); + + try { + ucbhelper::Content aContent(m_aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE), aEnvironment, comphelper::getProcessComponentContext()); + + // use post command + PostCommandArgument2 aPostArgument; + aPostArgument.Source = apSerialization->getInputStream(); + css::uno::Reference< XActiveDataSink > aSink(new ucbhelper::ActiveDataSink); + aPostArgument.Sink = aSink; + aPostArgument.MediaType = "application/xml"; + aPostArgument.Referer.clear(); + Any aCommandArgument; + aCommandArgument <<= aPostArgument; + aContent.executeCommand( "post", aCommandArgument); + + try { + m_aResultStream = aSink->getInputStream(); + } catch (const Exception&) { + OSL_FAIL("Cannot open reply stream from content"); + } + } catch (const Exception&) + { + TOOLS_WARN_EXCEPTION( "forms.misc", "Exception during UCB operation."); + return UNKNOWN_ERROR; + } + + return SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/submission_post.hxx b/forms/source/xforms/submission/submission_post.hxx new file mode 100644 index 000000000..0fb63472b --- /dev/null +++ b/forms/source/xforms/submission/submission_post.hxx @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "submission.hxx" + +class CSubmissionPost : public CSubmission +{ +public: + CSubmissionPost(std::u16string_view aURL, const css::uno::Reference< css::xml::dom::XDocumentFragment >& aFragment); + virtual SubmissionResult submit(const css::uno::Reference< css::task::XInteractionHandler >& aInteractionHandler) override; + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/submission_put.cxx b/forms/source/xforms/submission/submission_put.cxx new file mode 100644 index 000000000..678cd7921 --- /dev/null +++ b/forms/source/xforms/submission/submission_put.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <memory> + +#include "submission_put.hxx" + +#include <comphelper/processfactory.hxx> +#include <ucbhelper/content.hxx> +#include <tools/diagnose_ex.h> + +using namespace css::uno; +using namespace css::ucb; +using namespace css::task; +using namespace css::io; +using namespace osl; +using namespace ucbhelper; + + +CSubmissionPut::CSubmissionPut(std::u16string_view aURL, const css::uno::Reference< css::xml::dom::XDocumentFragment >& aFragment) + : CSubmission(aURL, aFragment) +{ +} + +CSubmission::SubmissionResult CSubmissionPut::submit(const css::uno::Reference< css::task::XInteractionHandler >& aInteractionHandler) +{ + css::uno::Reference< XCommandEnvironment > aEnvironment; + std::unique_ptr< CSerialization > apSerialization(createSerialization(aInteractionHandler,aEnvironment)); + + try { + ucbhelper::Content aContent(m_aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE), aEnvironment, comphelper::getProcessComponentContext()); + + // insert serialized data to content -> PUT + css::uno::Reference< XInputStream > aInStream = apSerialization->getInputStream(); + aContent.writeStream(aInStream, true); + //aContent.closeStream(); + + // no content as a result of put... + } + catch ( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "forms.misc", "Exception during UCB operation." ); + return UNKNOWN_ERROR; + } + + + return SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/xforms/submission/submission_put.hxx b/forms/source/xforms/submission/submission_put.hxx new file mode 100644 index 000000000..2dce84307 --- /dev/null +++ b/forms/source/xforms/submission/submission_put.hxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "submission.hxx" + +class CSubmissionPut : public CSubmission +{ +public: + CSubmissionPut(std::u16string_view aURL, + const css::uno::Reference<css::xml::dom::XDocumentFragment>& aFragment); + virtual SubmissionResult + submit(const css::uno::Reference<css::task::XInteractionHandler>& aInteractionHandler) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |