summaryrefslogtreecommitdiffstats
path: root/filter/source/xsltdialog
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--filter/source/xsltdialog/typedetectionexport.cxx264
-rw-r--r--filter/source/xsltdialog/typedetectionexport.hxx41
-rw-r--r--filter/source/xsltdialog/typedetectionimport.cxx316
-rw-r--r--filter/source/xsltdialog/typedetectionimport.hxx92
-rw-r--r--filter/source/xsltdialog/xmlfiltercommon.hxx83
-rw-r--r--filter/source/xsltdialog/xmlfilterdialogcomponent.cxx285
-rw-r--r--filter/source/xsltdialog/xmlfilterjar.cxx361
-rw-r--r--filter/source/xsltdialog/xmlfilterjar.hxx52
-rw-r--r--filter/source/xsltdialog/xmlfiltersettingsdialog.cxx1384
-rw-r--r--filter/source/xsltdialog/xmlfiltersettingsdialog.hxx97
-rw-r--r--filter/source/xsltdialog/xmlfiltertabdialog.cxx263
-rw-r--r--filter/source/xsltdialog/xmlfiltertabdialog.hxx54
-rw-r--r--filter/source/xsltdialog/xmlfiltertabpagebasic.cxx128
-rw-r--r--filter/source/xsltdialog/xmlfiltertabpagebasic.hxx43
-rw-r--r--filter/source/xsltdialog/xmlfiltertabpagexslt.cxx165
-rw-r--r--filter/source/xsltdialog/xmlfiltertabpagexslt.hxx56
-rw-r--r--filter/source/xsltdialog/xmlfiltertestdialog.cxx697
-rw-r--r--filter/source/xsltdialog/xmlfiltertestdialog.hxx81
-rw-r--r--filter/source/xsltdialog/xsltdlg.component26
19 files changed, 4488 insertions, 0 deletions
diff --git a/filter/source/xsltdialog/typedetectionexport.cxx b/filter/source/xsltdialog/typedetectionexport.cxx
new file mode 100644
index 000000000..30c4f894b
--- /dev/null
+++ b/filter/source/xsltdialog/typedetectionexport.cxx
@@ -0,0 +1,264 @@
+/* -*- 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 <sal/config.h>
+
+#include <string_view>
+
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <tools/urlobj.hxx>
+#include <tools/diagnose_ex.h>
+
+#include "typedetectionexport.hxx"
+#include "xmlfiltercommon.hxx"
+
+#include <comphelper/attributelist.hxx>
+#include <rtl/ref.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::xml::sax;
+
+
+TypeDetectionExporter::TypeDetectionExporter( Reference< XComponentContext > const & xContext )
+: mxContext( xContext )
+{
+}
+
+static OUString createRelativeURL( std::u16string_view rFilterName, const OUString& rURL )
+{
+ if( !rURL.isEmpty() &&
+ !rURL.startsWith("http:") &&
+ !rURL.startsWith("https:") &&
+ !rURL.startsWith("jar:") &&
+ !rURL.startsWith("ftp:") )
+ {
+ INetURLObject aURL( rURL );
+ OUString aName(aURL.GetLastName());
+ if( aName.isEmpty() )
+ {
+ sal_Int32 nPos = rURL.lastIndexOf( '/' );
+ if( nPos == -1 )
+ {
+ aName = rURL;
+ }
+ else
+ {
+ aName = rURL.copy( nPos + 1 );
+ }
+ }
+
+ return OUString( OUString::Concat("vnd.sun.star.Package:") + rFilterName + "/" + aName );
+ }
+ else
+ {
+ return rURL;
+ }
+}
+
+void TypeDetectionExporter::doExport( const Reference< XOutputStream >& xOS, const std::vector<filter_info_impl*>& rFilters )
+{
+ try
+ {
+ static const OUStringLiteral sComponentData ( u"oor:component-data" );
+ static const OUStringLiteral sNode ( u"node" );
+ static const OUStringLiteral sName ( u"oor:name" );
+ static const OUStringLiteral sWhiteSpace ( u" " );
+ static const OUStringLiteral sUIName ( u"UIName" );
+ static const OUStringLiteral sComma ( u"," );
+ static const OUStringLiteral sDelim ( u";" );
+ static const OUStringLiteral sData ( u"Data" );
+ static const OUStringLiteral sDocTypePrefix ( u"doctype:" );
+ static const OUStringLiteral sFilterAdaptorService( u"com.sun.star.comp.Writer.XmlFilterAdaptor" );
+ static const OUStringLiteral sXSLTFilterService ( u"com.sun.star.documentconversion.XSLTFilter" );
+ static const OUStringLiteral sCdataAttribute ( u"CDATA" );
+
+
+ // set up sax writer and connect to given output stream
+ Reference< XWriter > xHandler = Writer::create( mxContext );
+ xHandler->setOutputStream( xOS );
+
+ rtl::Reference<::comphelper::AttributeList> pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( "xmlns:oor", sCdataAttribute, "http://openoffice.org/2001/registry" );
+ pAttrList->AddAttribute ( "xmlns:xs", sCdataAttribute, "http://www.w3.org/2001/XMLSchema" );
+ pAttrList->AddAttribute ( sName, sCdataAttribute, "TypeDetection" );
+ pAttrList->AddAttribute ( "oor:package", sCdataAttribute, "org.openoffice.Office" );
+
+ xHandler->startDocument();
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sComponentData, pAttrList );
+
+ // export types
+ {
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( sName, sCdataAttribute, "Types" );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sNode, pAttrList );
+
+ for (auto const& filter : rFilters)
+ {
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute( sName, sCdataAttribute, filter->maType );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sNode, pAttrList );
+ OUString sValue = "0" + sComma + sComma;
+ if( !filter->maDocType.isEmpty() )
+ {
+ sValue += sDocTypePrefix + filter->maDocType;
+ }
+ sValue += sComma + sComma + filter->maExtension + sComma +
+ OUString::number( filter->mnDocumentIconID ) + sComma;
+
+ addProperty( xHandler, sData, sValue );
+ addLocaleProperty( xHandler, sUIName, filter->maInterfaceName );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sNode );
+ }
+
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sNode );
+ }
+
+ // export filters
+ {
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( sName, sCdataAttribute, "Filters" );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sNode, pAttrList );
+
+ for (auto const& filter : rFilters)
+ {
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute( sName, sCdataAttribute, filter->maFilterName );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sNode, pAttrList );
+ addLocaleProperty( xHandler, sUIName, filter->maInterfaceName );
+
+ const application_info_impl* pAppInfo = getApplicationInfo( filter->maExportService );
+ OUString sValue =
+ "0" +
+ sComma +
+ filter->maType +
+ sComma +
+ filter->maDocumentService +
+ sComma +
+ sFilterAdaptorService +
+ sComma +
+ OUString::number( filter->maFlags ) +
+ sComma +
+ sXSLTFilterService +
+ sDelim +
+ OUString::boolean( filter->mbNeedsXSLT2 ) +
+ sDelim +
+ pAppInfo->maXMLImporter +
+ sDelim +
+ pAppInfo->maXMLExporter +
+ sDelim +
+ createRelativeURL( filter->maFilterName, filter->maImportXSLT ) +
+ sDelim +
+ createRelativeURL( filter->maFilterName, filter->maExportXSLT ) +
+ sDelim +
+ // entry DTD obsolete and removed, but delimiter kept
+ sDelim +
+ filter->maComment +
+ sComma +
+ "0" +
+ sComma +
+ createRelativeURL( filter->maFilterName, filter->maImportTemplate );
+ addProperty( xHandler, sData, sValue );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sNode );
+ }
+
+ xHandler->endElement( sNode );
+ }
+
+ // finish
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sComponentData );
+ xHandler->endDocument();
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void TypeDetectionExporter::addProperty( const Reference< XWriter >& xHandler, const OUString& rName, const OUString& rValue )
+{
+ try
+ {
+ static const OUStringLiteral sCdataAttribute( u"CDATA" );
+ static const OUStringLiteral sProp( u"prop" );
+ static const OUStringLiteral sValue( u"value" );
+ static const OUStringLiteral sWhiteSpace ( u" " );
+
+ rtl::Reference<::comphelper::AttributeList>pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( "oor:name", sCdataAttribute, rName );
+ pAttrList->AddAttribute ( "oor:type", sCdataAttribute, "xs:string" );
+
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sProp, pAttrList );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sValue, pAttrList );
+ xHandler->characters( rValue );
+ xHandler->endElement( sValue );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sProp );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void TypeDetectionExporter::addLocaleProperty( const Reference< XWriter >& xHandler, const OUString& rName, const OUString& rValue )
+{
+ try
+ {
+ static const OUStringLiteral sCdataAttribute( u"CDATA" );
+ static const OUStringLiteral sProp( u"prop" );
+ static const OUStringLiteral sValue( u"value" );
+ static const OUStringLiteral sWhiteSpace ( u" " );
+
+ rtl::Reference<::comphelper::AttributeList> pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( "oor:name", sCdataAttribute, rName );
+ pAttrList->AddAttribute ( "oor:type", sCdataAttribute, "xs:string" );
+
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sProp, pAttrList );
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( "xml:lang", sCdataAttribute, "en-US" );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sValue, pAttrList );
+ xHandler->characters( rValue );
+ xHandler->endElement( sValue );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sProp );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/typedetectionexport.hxx b/filter/source/xsltdialog/typedetectionexport.hxx
new file mode 100644
index 000000000..a253540bb
--- /dev/null
+++ b/filter/source/xsltdialog/typedetectionexport.hxx
@@ -0,0 +1,41 @@
+/* -*- 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/xml/sax/XWriter.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+#include "xmlfilterjar.hxx"
+
+class TypeDetectionExporter
+{
+public:
+ explicit TypeDetectionExporter( css::uno::Reference< css::uno::XComponentContext > const & mxContext );
+
+ void doExport(const css::uno::Reference < css::io::XOutputStream >& xOS, const std::vector<filter_info_impl*>& rFilters );
+
+private:
+ static void addProperty( const css::uno::Reference< css::xml::sax::XWriter >& xWriter, const OUString& rName, const OUString& rValue );
+ static void addLocaleProperty( const css::uno::Reference< css::xml::sax::XWriter >& xWriter, const OUString& rName, const OUString& rValue );
+
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/typedetectionimport.cxx b/filter/source/xsltdialog/typedetectionimport.cxx
new file mode 100644
index 000000000..be5766927
--- /dev/null
+++ b/filter/source/xsltdialog/typedetectionimport.cxx
@@ -0,0 +1,316 @@
+/* -*- 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/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <tools/diagnose_ex.h>
+#include <rtl/ref.hxx>
+#include <o3tl/string_view.hxx>
+
+#include "typedetectionimport.hxx"
+#include "xmlfiltercommon.hxx"
+
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::xml::sax;
+using namespace com::sun::star;
+
+TypeDetectionImporter::TypeDetectionImporter()
+{
+}
+
+TypeDetectionImporter::~TypeDetectionImporter()
+{
+}
+
+void TypeDetectionImporter::doImport( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& xIS,
+ std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
+{
+ try
+ {
+ Reference< XParser > xParser = xml::sax::Parser::create( rxContext );
+
+ rtl::Reference<TypeDetectionImporter> pImporter = new TypeDetectionImporter;
+ xParser->setDocumentHandler( pImporter );
+
+ InputSource source;
+ source.aInputStream = xIS;
+
+ // start parsing
+ xParser->parseStream( source );
+
+ pImporter->fillFilterVector( rFilters );
+ }
+ catch( const Exception& /* e */ )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void TypeDetectionImporter::fillFilterVector( std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
+{
+ // create filter infos from imported filter nodes
+ for (auto const& filterNode : maFilterNodes)
+ {
+ std::unique_ptr<filter_info_impl> pFilter = createFilterForNode(filterNode.get());
+ if( pFilter )
+ rFilters.push_back( std::move(pFilter) );
+ }
+ maFilterNodes.clear();
+
+ // now delete type nodes
+ maTypeNodes.clear();
+}
+
+static std::u16string_view getSubdata( int index, sal_Unicode delimiter, std::u16string_view rData )
+{
+ sal_Int32 nLastIndex = 0;
+
+ size_t nNextIndex = rData.find( delimiter );
+
+ std::u16string_view aSubdata;
+
+ while( index )
+ {
+ nLastIndex = nNextIndex == std::u16string_view::npos ? 0 : nNextIndex + 1;
+ nNextIndex = rData.find( delimiter, nLastIndex );
+
+ index--;
+
+ if( (index > 0) && (nLastIndex == 0) )
+ return aSubdata;
+ }
+
+ if( nNextIndex == std::u16string_view::npos )
+ {
+ aSubdata = rData.substr( nLastIndex );
+ }
+ else
+ {
+ aSubdata = rData.substr( nLastIndex, nNextIndex - nLastIndex );
+ }
+
+ return aSubdata;
+}
+
+Node* TypeDetectionImporter::findTypeNode( const OUString& rType )
+{
+ auto aIter = std::find_if(maTypeNodes.begin(), maTypeNodes.end(),
+ [&rType](const std::unique_ptr<Node>& rxNode) { return rxNode->maName == rType; });
+ if (aIter != maTypeNodes.end())
+ return aIter->get();
+
+ return nullptr;
+}
+
+std::unique_ptr<filter_info_impl> TypeDetectionImporter::createFilterForNode( Node * pNode )
+{
+ std::unique_ptr<filter_info_impl> pFilter(new filter_info_impl);
+
+ pFilter->maFilterName = pNode->maName;
+ pFilter->maInterfaceName = pNode->maPropertyMap["UIName"];
+
+ OUString aData = pNode->maPropertyMap["Data"];
+
+ sal_Unicode aComma(',');
+
+ pFilter->maType = getSubdata( 1, aComma, aData );
+ pFilter->maDocumentService = getSubdata( 2, aComma, aData );
+
+ std::u16string_view aFilterService( getSubdata( 3, aComma, aData ) );
+ pFilter->maFlags = o3tl::toInt32(getSubdata( 4, aComma, aData ));
+
+ // parse filter user data
+ sal_Unicode aDelim(';');
+ std::u16string_view aFilterUserData( getSubdata( 5, aComma, aData ) );
+
+ std::u16string_view aAdapterService( getSubdata( 0, aDelim, aFilterUserData ) );
+ //Import/ExportService
+ pFilter->mbNeedsXSLT2 = OUString(getSubdata( 1, aDelim, aFilterUserData )).toBoolean();
+ pFilter->maImportService = getSubdata( 2, aDelim, aFilterUserData );
+ pFilter->maExportService = getSubdata( 3, aDelim, aFilterUserData );
+ pFilter->maImportXSLT = getSubdata( 4, aDelim, aFilterUserData );
+ pFilter->maExportXSLT = getSubdata( 5, aDelim, aFilterUserData );
+ pFilter->maComment = getSubdata( 7, aDelim, aFilterUserData );
+
+
+ pFilter->maImportTemplate = getSubdata( 7, aComma, aData );
+
+ Node* pTypeNode = findTypeNode( pFilter->maType );
+ if( pTypeNode )
+ {
+ OUString aTypeUserData( pTypeNode->maPropertyMap["Data"] );
+
+ pFilter->maDocType = getSubdata( 2, aComma, aTypeUserData );
+ pFilter->maExtension = getSubdata( 4, aComma, aTypeUserData );
+ pFilter->mnDocumentIconID = o3tl::toInt32(getSubdata( 5, aComma, aTypeUserData ));
+ }
+
+ bool bOk = true;
+
+ if( pTypeNode == nullptr )
+ bOk = false;
+
+ if( pFilter->maFilterName.isEmpty() )
+ bOk = false;
+
+ if( pFilter->maInterfaceName.isEmpty() )
+ bOk = false;
+
+ if( pFilter->maType.isEmpty() )
+ bOk = false;
+
+ if( pFilter->maFlags == 0 )
+ bOk = false;
+
+ if( aFilterService != u"com.sun.star.comp.Writer.XmlFilterAdaptor" )
+ bOk = false;
+
+ if( aAdapterService != u"com.sun.star.documentconversion.XSLTFilter" )
+ bOk = false;
+
+ if( pFilter->maExtension.isEmpty() )
+ bOk = false;
+
+ if( !bOk )
+ return nullptr;
+
+ return pFilter;
+}
+
+void SAL_CALL TypeDetectionImporter::startDocument( )
+{
+}
+
+void SAL_CALL TypeDetectionImporter::endDocument( )
+{
+}
+
+void SAL_CALL TypeDetectionImporter::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs )
+{
+ ImportState eNewState = e_Unknown;
+
+ if( maStack.empty() )
+ {
+ // #109668# support legacy name as well on import
+ if( aName == "oor:component-data" || aName == "oor:node" )
+ {
+ eNewState = e_Root;
+ }
+ }
+ else if( maStack.top() == e_Root )
+ {
+ if( aName == "node" )
+ {
+ OUString aNodeName( xAttribs->getValueByName( "oor:name" ) );
+
+ if( aNodeName == "Filters" )
+ {
+ eNewState = e_Filters;
+ }
+ else if( aNodeName == "Types" )
+ {
+ eNewState = e_Types;
+ }
+ }
+ }
+ else if( (maStack.top() == e_Filters) || (maStack.top() == e_Types) )
+ {
+ if( aName == "node" )
+ {
+ maNodeName = xAttribs->getValueByName( "oor:name" );
+
+ eNewState = (maStack.top() == e_Filters) ? e_Filter : e_Type;
+ }
+ }
+ else if( (maStack.top() == e_Filter) || (maStack.top() == e_Type))
+ {
+ if( aName == "prop" )
+ {
+ maPropertyName = xAttribs->getValueByName( "oor:name" );
+ eNewState = e_Property;
+ }
+ }
+ else if( maStack.top() == e_Property )
+ {
+ if( aName == "value" )
+ {
+ eNewState = e_Value;
+ maValue.clear();
+ }
+ }
+
+ maStack.push( eNewState );
+}
+void SAL_CALL TypeDetectionImporter::endElement( const OUString& /* aName */ )
+{
+ if( maStack.empty() )
+ return;
+
+ ImportState eCurrentState = maStack.top();
+ switch( eCurrentState )
+ {
+ case e_Filter:
+ case e_Type:
+ {
+ std::unique_ptr<Node> pNode(new Node);
+ pNode->maName = maNodeName;
+ pNode->maPropertyMap = maPropertyMap;
+ maPropertyMap.clear();
+
+ if( eCurrentState == e_Filter )
+ {
+ maFilterNodes.push_back( std::move(pNode) );
+ }
+ else
+ {
+ maTypeNodes.push_back( std::move(pNode) );
+ }
+ }
+ break;
+
+ case e_Property:
+ maPropertyMap[ maPropertyName ] = maValue;
+ break;
+ default: break;
+ }
+
+ maStack.pop();
+}
+void SAL_CALL TypeDetectionImporter::characters( const OUString& aChars )
+{
+ if( !maStack.empty() && maStack.top() == e_Value )
+ {
+ maValue += aChars;
+ }
+}
+void SAL_CALL TypeDetectionImporter::ignorableWhitespace( const OUString& /* aWhitespaces */ )
+{
+}
+void SAL_CALL TypeDetectionImporter::processingInstruction( const OUString& /* aTarget */, const OUString& /* aData */ )
+{
+}
+void SAL_CALL TypeDetectionImporter::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /* xLocator */ )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/typedetectionimport.hxx b/filter/source/xsltdialog/typedetectionimport.hxx
new file mode 100644
index 000000000..3b69ef9af
--- /dev/null
+++ b/filter/source/xsltdialog/typedetectionimport.hxx
@@ -0,0 +1,92 @@
+/* -*- 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/XInputStream.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include "xmlfilterjar.hxx"
+
+#include <map>
+#include <memory>
+#include <vector>
+#include <stack>
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { struct PropertyValue; }
+}
+
+enum ImportState
+{
+ e_Root,
+ e_Filters,
+ e_Types,
+ e_Filter,
+ e_Type,
+ e_Property,
+ e_Value,
+ e_Unknown
+};
+
+typedef std::map<OUString, OUString> PropertyMap;
+
+struct Node
+{
+ OUString maName;
+ PropertyMap maPropertyMap;
+};
+
+class TypeDetectionImporter : public cppu::WeakImplHelper < css::xml::sax::XDocumentHandler >
+{
+public:
+ TypeDetectionImporter();
+ virtual ~TypeDetectionImporter() override;
+
+ static void doImport( const css::uno::Reference< css::uno::XComponentContext >& rxContext, const css::uno::Reference < css::io::XInputStream >& xOS,
+ std::vector< std::unique_ptr<filter_info_impl> >& rFilters );
+
+ virtual void SAL_CALL startDocument( ) override;
+ virtual void SAL_CALL endDocument( ) override;
+ virtual void SAL_CALL startElement( const OUString& aName, const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) override;
+ virtual void SAL_CALL endElement( const OUString& aName ) override;
+ virtual void SAL_CALL characters( const OUString& aChars ) override;
+ virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override;
+ virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override;
+ virtual void SAL_CALL setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override;
+
+private:
+ void fillFilterVector( std::vector< std::unique_ptr<filter_info_impl> >& rFilters );
+ std::unique_ptr<filter_info_impl> createFilterForNode( Node * pNode );
+ Node* findTypeNode( const OUString& rType );
+
+ std::stack< ImportState > maStack;
+ PropertyMap maPropertyMap;
+
+ std::vector< std::unique_ptr<Node> > maFilterNodes;
+ std::vector< std::unique_ptr<Node> > maTypeNodes;
+
+ OUString maValue;
+ OUString maNodeName;
+ OUString maPropertyName;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltercommon.hxx b/filter/source/xsltdialog/xmlfiltercommon.hxx
new file mode 100644
index 000000000..4ac225183
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltercommon.hxx
@@ -0,0 +1,83 @@
+/* -*- 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/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <unotools/resmgr.hxx>
+
+#include <string_view>
+#include <vector>
+
+
+extern OUString string_encode( const OUString & rText );
+extern OUString string_decode( const OUString & rText );
+
+bool copyStreams( const css::uno::Reference< css::io::XInputStream >& xIS, const css::uno::Reference< css::io::XOutputStream >& xOS );
+bool createDirectory( std::u16string_view rURL );
+
+
+class filter_info_impl
+{
+public:
+ OUString maFilterName;
+ OUString maType;
+ OUString maDocumentService;
+ OUString maInterfaceName;
+ OUString maComment;
+ OUString maExtension;
+ OUString maExportXSLT;
+ OUString maImportXSLT;
+ OUString maImportTemplate;
+ OUString maDocType;
+ OUString maImportService;
+ OUString maExportService;
+
+ sal_Int32 maFlags;
+ sal_Int32 maFileFormatVersion;
+ sal_Int32 mnDocumentIconID;
+
+ bool mbReadonly;
+
+ bool mbNeedsXSLT2;
+
+ filter_info_impl();
+ bool operator==( const filter_info_impl& ) const;
+
+ css::uno::Sequence< OUString > getFilterUserData() const;
+};
+
+
+struct application_info_impl
+{
+ OUString maDocumentService;
+ OUString maDocumentUIName;
+ OUString maXMLImporter;
+ OUString maXMLExporter;
+
+ application_info_impl(const char * pDocumentService, const OUString& rUINameRes, const char * mpXMLImporter, const char * mpXMLExporter);
+};
+
+
+extern std::vector< application_info_impl > const & getApplicationInfos();
+extern OUString getApplicationUIName( std::u16string_view rServiceName );
+extern const application_info_impl* getApplicationInfo( std::u16string_view rServiceName );
+OUString XsltResId(TranslateId pId);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfilterdialogcomponent.cxx b/filter/source/xsltdialog/xmlfilterdialogcomponent.cxx
new file mode 100644
index 000000000..6f4b1db34
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfilterdialogcomponent.cxx
@@ -0,0 +1,285 @@
+/* -*- 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 <osl/mutex.hxx>
+
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/component.hxx>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <vcl/svapp.hxx>
+
+#include "xmlfiltersettingsdialog.hxx"
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::frame;
+
+namespace {
+
+class XMLFilterDialogComponentBase
+{
+protected:
+ ::osl::Mutex maMutex;
+};
+
+
+class XMLFilterDialogComponent : public XMLFilterDialogComponentBase,
+ public OComponentHelper,
+ public css::ui::dialogs::XExecutableDialog,
+ public XServiceInfo,
+ public XInitialization,
+ public XTerminateListener
+{
+public:
+ explicit XMLFilterDialogComponent( const Reference< XComponentContext >& rxContext );
+
+ // XInterface
+ virtual Any SAL_CALL queryInterface( const Type& aType ) override;
+ virtual Any SAL_CALL queryAggregation( Type const & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+protected:
+ // XTypeProvider
+ virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+ virtual Sequence< Type > SAL_CALL getTypes() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XExecutableDialog
+ virtual void SAL_CALL setTitle( const OUString& aTitle ) override;
+ virtual sal_Int16 SAL_CALL execute( ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
+
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination( const EventObject& Event ) override;
+ virtual void SAL_CALL notifyTermination( const EventObject& Event ) override;
+ virtual void SAL_CALL disposing( const EventObject& Source ) override;
+
+ /** Called in dispose method after the listeners were notified.
+ */
+ virtual void SAL_CALL disposing() override;
+
+private:
+ css::uno::Reference<css::awt::XWindow> mxParent; /// parent window
+ css::uno::Reference< XComponentContext > mxContext;
+
+ std::shared_ptr<XMLFilterSettingsDialog> mxDialog;
+};
+
+}
+
+XMLFilterDialogComponent::XMLFilterDialogComponent(const css::uno::Reference< XComponentContext >& rxContext)
+ : OComponentHelper(maMutex)
+ , mxContext(rxContext)
+{
+ Reference< XDesktop2 > xDesktop = Desktop::create( rxContext );
+ Reference< XTerminateListener > xListener( this );
+ xDesktop->addTerminateListener( xListener );
+}
+
+// XInterface
+Any SAL_CALL XMLFilterDialogComponent::queryInterface( const Type& aType )
+{
+ return OComponentHelper::queryInterface( aType );
+}
+
+
+Any SAL_CALL XMLFilterDialogComponent::queryAggregation( Type const & rType )
+{
+ if (rType == cppu::UnoType<css::ui::dialogs::XExecutableDialog>::get())
+ {
+ void * p = static_cast< css::ui::dialogs::XExecutableDialog * >( this );
+ return Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<XServiceInfo>::get())
+ {
+ void * p = static_cast< XServiceInfo * >( this );
+ return Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<XInitialization>::get())
+ {
+ void * p = static_cast< XInitialization * >( this );
+ return Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<XTerminateListener>::get())
+ {
+ void * p = static_cast< XTerminateListener * >( this );
+ return Any( &p, rType );
+ }
+ return OComponentHelper::queryAggregation( rType );
+}
+
+
+void SAL_CALL XMLFilterDialogComponent::acquire() noexcept
+{
+ OComponentHelper::acquire();
+}
+
+
+void SAL_CALL XMLFilterDialogComponent::release() noexcept
+{
+ OComponentHelper::release();
+}
+
+
+OUString SAL_CALL XMLFilterDialogComponent::getImplementationName()
+{
+ return "com.sun.star.comp.ui.XSLTFilterDialog";
+}
+
+Sequence< sal_Int8 > SAL_CALL XMLFilterDialogComponent::getImplementationId()
+{
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+}
+
+
+Sequence< Type > XMLFilterDialogComponent::getTypes()
+{
+ return { cppu::UnoType<XComponent>::get(),
+ cppu::UnoType<XTypeProvider>::get(),
+ cppu::UnoType<XAggregation>::get(),
+ cppu::UnoType<XWeak>::get(),
+ cppu::UnoType<XServiceInfo>::get(),
+ cppu::UnoType<XInitialization>::get(),
+ cppu::UnoType<XTerminateListener>::get(),
+ cppu::UnoType<css::ui::dialogs::XExecutableDialog>::get() };
+}
+
+Sequence< OUString > SAL_CALL XMLFilterDialogComponent::getSupportedServiceNames()
+{
+ return { "com.sun.star.ui.dialogs.XSLTFilterDialog" };
+}
+
+sal_Bool SAL_CALL XMLFilterDialogComponent::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+/** Called in dispose method after the listeners were notified.
+*/
+void SAL_CALL XMLFilterDialogComponent::disposing()
+{
+ ::SolarMutexGuard aGuard;
+
+ if (mxDialog)
+ mxDialog->response(RET_CLOSE);
+}
+
+
+// XTerminateListener
+void SAL_CALL XMLFilterDialogComponent::queryTermination( const EventObject& /* Event */ )
+{
+ ::SolarMutexGuard aGuard;
+ if (!mxDialog)
+ return;
+ mxDialog->present();
+}
+
+void SAL_CALL XMLFilterDialogComponent::notifyTermination( const EventObject& /* Event */ )
+{
+ {
+ ::SolarMutexGuard aGuard;
+ if (mxDialog)
+ mxDialog->response(RET_CLOSE);
+ }
+
+ // we are going down, so dispose us!
+ dispose();
+}
+
+void SAL_CALL XMLFilterDialogComponent::disposing( const EventObject& /* Source */ )
+{
+}
+
+void SAL_CALL XMLFilterDialogComponent::setTitle( const OUString& /* _rTitle */ )
+{
+}
+
+sal_Int16 SAL_CALL XMLFilterDialogComponent::execute()
+{
+ ::SolarMutexGuard aGuard;
+
+ bool bLaunch = false;
+ if (!mxDialog)
+ {
+ Reference< XComponent > xKeepAlive( this );
+ mxDialog = std::make_shared<XMLFilterSettingsDialog>(Application::GetFrameWeld(mxParent), mxContext);
+ bLaunch = true;
+ }
+
+ mxDialog->UpdateWindow();
+
+ if (!bLaunch)
+ {
+ mxDialog->present();
+ return 0;
+ }
+
+ weld::DialogController::runAsync(mxDialog, [this](sal_Int32)
+ {
+ mxDialog.reset();
+ });
+
+ return 0;
+}
+
+void SAL_CALL XMLFilterDialogComponent::initialize( const Sequence< Any >& aArguments )
+{
+ for(const Any& rArgument : aArguments)
+ {
+ PropertyValue aProperty;
+ if(rArgument >>= aProperty)
+ {
+ if( aProperty.Name == "ParentWindow" )
+ {
+ aProperty.Value >>= mxParent;
+ }
+ }
+ }
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_XSLTFilterDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XMLFilterDialogComponent(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfilterjar.cxx b/filter/source/xsltdialog/xmlfilterjar.cxx
new file mode 100644
index 000000000..2366aa80e
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfilterjar.cxx
@@ -0,0 +1,361 @@
+/* -*- 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/XActiveDataControl.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+
+#include <comphelper/oslfile2streamwrap.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <osl/file.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unotools/tempfile.hxx>
+#include <svl/urihelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/stream.hxx>
+#include <tools/urlobj.hxx>
+
+#include <rtl/uri.hxx>
+
+#include "xmlfiltercommon.hxx"
+#include "xmlfilterjar.hxx"
+#include "typedetectionexport.hxx"
+#include "typedetectionimport.hxx"
+
+using namespace osl;
+using namespace comphelper;
+using namespace com::sun::star;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::util;
+using namespace com::sun::star::container;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::io;
+
+using ::rtl::Uri;
+
+constexpr OUStringLiteral sVndSunStarPackage(u"vnd.sun.star.Package:");
+
+XMLFilterJarHelper::XMLFilterJarHelper( const Reference< XComponentContext >& rxContext )
+: mxContext( rxContext ),
+ sXSLTPath( "$(user)/xslt/" ),
+ sTemplatePath( "$(user)/template/" ),
+ sProgPath( "$(prog)/" )
+{
+ SvtPathOptions aOptions;
+ sProgPath = aOptions.SubstituteVariable( sProgPath );
+ sXSLTPath = aOptions.SubstituteVariable( sXSLTPath );
+ sTemplatePath = aOptions.SubstituteVariable( sTemplatePath );
+}
+
+static OUString encodeZipUri( const OUString& rURI )
+{
+ return Uri::encode( rURI, rtl_UriCharClassUric, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8 );
+}
+
+/// @throws Exception
+static Reference< XInterface > addFolder( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, const OUString& rName )
+{
+ if ( rName == ".." || rName == "." )
+ throw lang::IllegalArgumentException();
+
+ Sequence< Any > aArgs{ Any(true) };
+
+ Reference< XInterface > xFolder( xFactory->createInstanceWithArguments(aArgs) );
+ Reference< XNamed > xNamed( xFolder, UNO_QUERY );
+ Reference< XChild > xChild( xFolder, UNO_QUERY );
+
+ if( xNamed.is() && xChild.is() )
+ {
+ OUString aName( encodeZipUri( rName ) );
+ xNamed->setName( aName );
+ xChild->setParent( xRootFolder );
+ }
+
+ return xFolder;
+}
+
+/// @throws Exception
+static void addFile_( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, Reference< XInputStream > const & xInput, const OUString& aName )
+{
+ Reference< XActiveDataSink > xSink( xFactory->createInstance(), UNO_QUERY );
+ Reference< XUnoTunnel > xTunnel( xSink, UNO_QUERY );
+ if( xSink.is() && xTunnel.is())
+ {
+ Reference< XNameContainer > xNameContainer(xRootFolder, UNO_QUERY );
+ xNameContainer->insertByName(encodeZipUri( aName ), Any(xTunnel));
+ xSink->setInputStream( xInput );
+ }
+}
+
+void XMLFilterJarHelper::addFile( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, const OUString& rSourceFile )
+{
+ if( rSourceFile.isEmpty() ||
+ rSourceFile.startsWith("http:") ||
+ rSourceFile.startsWith("https:") ||
+ rSourceFile.startsWith("jar:") ||
+ rSourceFile.startsWith("ftp:") )
+ return;
+
+ OUString aFileURL( rSourceFile );
+
+ if( !aFileURL.matchIgnoreAsciiCase("file://") )
+ {
+ aFileURL = URIHelper::SmartRel2Abs( INetURLObject(sProgPath), aFileURL, Link<OUString *, bool>(), false );
+ }
+
+ INetURLObject aURL( aFileURL );
+ OUString aName( aURL.getName() );
+
+ SvFileStream* pStream = new SvFileStream(aFileURL, StreamMode::READ );
+ Reference< XInputStream > xInput( new utl::OSeekableInputStreamWrapper( pStream, true ) );
+ addFile_( xRootFolder, xFactory, xInput, aName );
+}
+
+bool XMLFilterJarHelper::savePackage( const OUString& rPackageURL, const std::vector<filter_info_impl*>& rFilters )
+{
+ try
+ {
+ osl::File::remove( rPackageURL );
+
+ // create the package jar file
+
+ Sequence< Any > aArguments{ Any(rPackageURL),
+ // let ZipPackage be used ( no manifest.xml is required )
+ Any(beans::NamedValue(
+ "StorageFormat", Any(OUString(ZIP_STORAGE_FORMAT_STRING)))) };
+
+ Reference< XHierarchicalNameAccess > xIfc(
+ mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.packages.comp.ZipPackage",
+ aArguments, mxContext ), UNO_QUERY );
+
+ if( xIfc.is() )
+ {
+ Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
+
+ // get root zip folder
+ Reference< XInterface > xRootFolder;
+ xIfc->getByHierarchicalName( "/" ) >>= xRootFolder;
+
+ // export filters files
+ for (auto const& filter : rFilters)
+ {
+ Reference< XInterface > xFilterRoot( addFolder( xRootFolder, xFactory, filter->maFilterName ) );
+
+ if( xFilterRoot.is() )
+ {
+ if( !filter->maExportXSLT.isEmpty() )
+ addFile( xFilterRoot, xFactory, filter->maExportXSLT );
+ try
+ {
+ if( !filter->maImportXSLT.isEmpty() )
+ addFile( xFilterRoot, xFactory, filter->maImportXSLT );
+ }
+ catch(const css::container::ElementExistException&)
+ {
+ // in case of same named import / export XSLT the latter
+ // is ignored
+ TOOLS_WARN_EXCEPTION("filter.xslt", "same named xslt filter exception!");
+ }
+
+ if( !filter->maImportTemplate.isEmpty() )
+ addFile( xFilterRoot, xFactory, filter->maImportTemplate );
+ }
+ }
+
+ // create TypeDetection.xcu
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString aTempFileURL( aTempFile.GetURL() );
+
+ {
+ osl::File aOutputFile( aTempFileURL );
+ (void)aOutputFile.open(osl_File_OpenFlag_Write);
+ Reference< XOutputStream > xOS( new OSLOutputStreamWrapper( aOutputFile ) );
+
+ TypeDetectionExporter aExporter( mxContext );
+ aExporter.doExport(xOS,rFilters);
+ }
+
+ Reference< XInputStream > XIS( new utl::OSeekableInputStreamWrapper( new SvFileStream(aTempFileURL, StreamMode::READ ), true ) );
+ addFile_( xRootFolder, xFactory, XIS, "TypeDetection.xcu" );
+
+ Reference< XChangesBatch > xBatch( xIfc, UNO_QUERY );
+ if( xBatch.is() )
+ xBatch->commitChanges();
+
+ return true;
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ osl::File::remove( rPackageURL );
+
+ return false;
+}
+
+
+void XMLFilterJarHelper::openPackage( const OUString& rPackageURL,
+ std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
+{
+ try
+ {
+ // create the package jar file
+
+ // let ZipPackage be used ( no manifest.xml is required )
+ beans::NamedValue aArg;
+ aArg.Name = "StorageFormat";
+ aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
+ Sequence< Any > aArguments{ Any(rPackageURL), Any(aArg) };
+
+ Reference< XHierarchicalNameAccess > xIfc(
+ mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.packages.comp.ZipPackage",
+ aArguments, mxContext ), UNO_QUERY );
+
+ if( xIfc.is() )
+ {
+ // get root zip folder
+ Reference< XInterface > xRootFolder;
+ xIfc->getByHierarchicalName( "/" ) >>= xRootFolder;
+
+ OUString szTypeDetection("TypeDetection.xcu");
+ if( xIfc->hasByHierarchicalName( szTypeDetection ) )
+ {
+ Reference< XActiveDataSink > xTypeDetection;
+ xIfc->getByHierarchicalName( szTypeDetection ) >>= xTypeDetection;
+
+ if( xTypeDetection.is() )
+ {
+ Reference< XInputStream > xIS( xTypeDetection->getInputStream() );
+
+ std::vector< std::unique_ptr<filter_info_impl> > aFilters;
+ TypeDetectionImporter::doImport( mxContext, xIS, aFilters );
+
+ // copy all files used by the filters imported from the
+ // typedetection to office/user/xslt
+ for (auto& filter : aFilters)
+ {
+ if( copyFiles( xIfc, filter.get() ) )
+ {
+ rFilters.push_back(std::move(filter));
+ }
+ else
+ {
+ // failed to copy all files
+ filter.reset();
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+bool XMLFilterJarHelper::copyFiles( const Reference< XHierarchicalNameAccess >& xIfc, filter_info_impl* pFilter )
+{
+ bool bOk = copyFile( xIfc, pFilter->maExportXSLT, sXSLTPath );
+
+ if( bOk )
+ bOk = copyFile( xIfc, pFilter->maImportXSLT, sXSLTPath );
+
+ if( bOk )
+ bOk = copyFile( xIfc, pFilter->maImportTemplate, sTemplatePath );
+
+ return bOk;
+}
+
+bool XMLFilterJarHelper::copyFile( const Reference< XHierarchicalNameAccess >& xIfc, OUString& rURL, std::u16string_view rTargetURL )
+{
+ if( !rURL.matchIgnoreAsciiCase( sVndSunStarPackage ) )
+ return true;
+
+ try
+ {
+ OUString szPackagePath( encodeZipUri( rURL.copy( sVndSunStarPackage.getLength() ) ) );
+
+ if ( ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, u".." )
+ || ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, u"." ) )
+ throw lang::IllegalArgumentException();
+
+ if( xIfc->hasByHierarchicalName( szPackagePath ) )
+ {
+ Reference< XActiveDataSink > xFileEntry;
+ xIfc->getByHierarchicalName( szPackagePath ) >>= xFileEntry;
+
+ if( xFileEntry.is() )
+ {
+ Reference< XInputStream > xIS( xFileEntry->getInputStream() );
+
+ INetURLObject aBaseURL( rTargetURL );
+
+ rURL = URIHelper::SmartRel2Abs( aBaseURL, szPackagePath, Link<OUString *, bool>(), false );
+
+ if( !rURL.isEmpty() )
+ {
+ // create output directory if needed
+ if( !createDirectory( rURL ) )
+ return false;
+
+ ::osl::File file(rURL);
+ ::osl::FileBase::RC rc =
+ file.open(osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
+ if (::osl::FileBase::E_EXIST == rc) {
+ rc = file.open(osl_File_OpenFlag_Write);
+ if (::osl::FileBase::E_None == rc) {
+ file.setSize(0); // #i97170# truncate
+ }
+ }
+ if (::osl::FileBase::E_None != rc) {
+ throw RuntimeException();
+ }
+ Reference< XOutputStream > const xOS(
+ new comphelper::OSLOutputStreamWrapper(file));
+
+ return copyStreams( xIS, xOS );
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfilterjar.hxx b/filter/source/xsltdialog/xmlfilterjar.hxx
new file mode 100644
index 000000000..d634bb6c4
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfilterjar.hxx
@@ -0,0 +1,52 @@
+/* -*- 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/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <memory>
+#include <vector>
+
+class filter_info_impl;
+
+class XMLFilterJarHelper
+{
+public:
+ explicit XMLFilterJarHelper( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+
+ bool savePackage( const OUString& rPackageURL, const std::vector<filter_info_impl*>& rFilters );
+ void openPackage( const OUString& rPackageURL, std::vector< std::unique_ptr<filter_info_impl> >& rFilters );
+
+private:
+ /// @throws css::uno::Exception
+ void addFile( css::uno::Reference< css::uno::XInterface > const & xRootFolder, css::uno::Reference< css::lang::XSingleServiceFactory > const & xFactory, const OUString& rSourceFile );
+
+ static bool copyFile( const css::uno::Reference< css::container::XHierarchicalNameAccess >& xIfc, OUString& rURL, std::u16string_view rTargetURL );
+ bool copyFiles( const css::uno::Reference< css::container::XHierarchicalNameAccess >& xIfc, filter_info_impl* pFilter );
+
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+
+ OUString sXSLTPath;
+ OUString sTemplatePath;
+ OUString sProgPath;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx
new file mode 100644
index 000000000..62a8513d7
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx
@@ -0,0 +1,1384 @@
+/* -*- 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/beans/XPropertySet.hpp>
+#include <com/sun/star/util/XFlushable.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <o3tl/string_view.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/resmgr.hxx>
+#include <unotools/streamwrap.hxx>
+#include <osl/file.hxx>
+#include <o3tl/enumrange.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <tools/stream.hxx>
+
+#include <rtl/uri.hxx>
+
+#include <algorithm>
+#include <memory>
+
+#include <strings.hrc>
+#include "xmlfiltersettingsdialog.hxx"
+#include "xmlfiltertabdialog.hxx"
+#include "xmlfiltertestdialog.hxx"
+#include "xmlfilterjar.hxx"
+#include <strings.hxx>
+
+using namespace osl;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace com::sun::star::container;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::util;
+
+using ::rtl::Uri;
+
+OUString XsltResId(TranslateId aId)
+{
+ return Translate::get(aId, Translate::Create("flt"));
+}
+
+XMLFilterSettingsDialog::XMLFilterSettingsDialog(weld::Window* pParent,
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : GenericDialogController(pParent, "filter/ui/xmlfiltersettings.ui", "XMLFilterSettingsDialog")
+ , mxContext( rxContext )
+ , m_sTemplatePath("$(user)/template/")
+ , m_sDocTypePrefix("doctype:")
+ , m_xPBNew(m_xBuilder->weld_button("new"))
+ , m_xPBEdit(m_xBuilder->weld_button("edit"))
+ , m_xPBTest(m_xBuilder->weld_button("test"))
+ , m_xPBDelete(m_xBuilder->weld_button("delete"))
+ , m_xPBSave(m_xBuilder->weld_button("save"))
+ , m_xPBOpen(m_xBuilder->weld_button("open"))
+ , m_xPBClose(m_xBuilder->weld_button("close"))
+ , m_xFilterListBox(m_xBuilder->weld_tree_view("filterlist"))
+{
+ m_xFilterListBox->set_selection_mode(SelectionMode::Multiple);
+
+ m_xFilterListBox->set_size_request(m_xFilterListBox->get_approximate_digit_width() * 65,
+ m_xFilterListBox->get_height_rows(12));
+
+ m_xFilterListBox->connect_changed( LINK( this, XMLFilterSettingsDialog, SelectionChangedHdl_Impl ) );
+ m_xFilterListBox->connect_row_activated( LINK( this, XMLFilterSettingsDialog, DoubleClickHdl_Impl ) );
+ m_xFilterListBox->set_accessible_name(XsltResId(STR_XML_FILTER_LISTBOX));
+
+ m_xPBNew->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBEdit->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBTest->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBDelete->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBSave->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBOpen->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBClose->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+
+ try
+ {
+ mxFilterContainer.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", rxContext ), UNO_QUERY );
+ mxTypeDetection.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", rxContext ), UNO_QUERY );
+ mxExtendedTypeDetection.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.ExtendedTypeDetectionFactory", rxContext ), UNO_QUERY );
+
+ SvtPathOptions aOptions;
+ m_sTemplatePath = aOptions.SubstituteVariable( m_sTemplatePath );
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+XMLFilterSettingsDialog::~XMLFilterSettingsDialog()
+{
+}
+
+IMPL_LINK(XMLFilterSettingsDialog, ClickHdl_Impl, weld::Button&, rButton, void)
+{
+ // tdf#122171 block closing libreoffice until the following dialog is dismissed
+ incBusy();
+
+ if (m_xPBNew.get() == &rButton)
+ {
+ onNew();
+ }
+ else if (m_xPBEdit.get() == &rButton)
+ {
+ onEdit();
+ }
+ else if (m_xPBTest.get() == &rButton)
+ {
+ onTest();
+ }
+ else if (m_xPBDelete.get() == &rButton)
+ {
+ onDelete();
+ }
+ else if (m_xPBSave.get() == &rButton)
+ {
+ onSave();
+ }
+ else if (m_xPBOpen.get() == &rButton)
+ {
+ onOpen();
+ }
+
+ decBusy();
+
+ if (m_xPBClose.get() == &rButton)
+ m_xDialog->response(RET_CLOSE);
+}
+
+IMPL_LINK_NOARG(XMLFilterSettingsDialog, SelectionChangedHdl_Impl, weld::TreeView&, void)
+{
+ updateStates();
+}
+
+IMPL_LINK_NOARG(XMLFilterSettingsDialog, DoubleClickHdl_Impl, weld::TreeView&, bool)
+{
+ onEdit();
+ return true;
+}
+
+void XMLFilterSettingsDialog::UpdateWindow()
+{
+ m_xFilterListBox->grab_focus();
+ disposeFilterList();
+ m_xFilterListBox->clear();
+ initFilterList();
+ updateStates();
+}
+
+void XMLFilterSettingsDialog::updateStates()
+{
+ std::vector<int> aRows = m_xFilterListBox->get_selected_rows();
+
+ bool bHasSelection = !aRows.empty();
+
+ bool bMultiSelection = aRows.size() > 1;
+ bool bIsReadonly = false;
+ bool bIsDefault = false;
+ if (bHasSelection)
+ {
+ filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(aRows[0]));
+ bIsReadonly = pInfo->mbReadonly;
+
+ for( auto nFact : o3tl::enumrange<SvtModuleOptions::EFactory>())
+ {
+ OUString sDefault = maModuleOpt.GetFactoryDefaultFilter(nFact);
+ if( sDefault == pInfo->maFilterName )
+ {
+ bIsDefault = true;
+ break;
+ }
+ }
+ }
+ m_xPBEdit->set_sensitive( bHasSelection && !bMultiSelection && !bIsReadonly);
+ m_xPBTest->set_sensitive( bHasSelection && !bMultiSelection );
+ m_xPBDelete->set_sensitive( bHasSelection && !bMultiSelection && !bIsReadonly && !bIsDefault);
+ m_xPBSave->set_sensitive( bHasSelection );
+}
+
+/** is called when the user clicks on the "New" button */
+void XMLFilterSettingsDialog::onNew()
+{
+ filter_info_impl aTempInfo;
+
+ // create a unique filter name
+ aTempInfo.maFilterName = createUniqueFilterName(XsltResId(STR_DEFAULT_FILTER_NAME));
+
+ // init default extension
+ aTempInfo.maExtension = STR_DEFAULT_EXTENSION;
+
+ // set default ui name
+ aTempInfo.maInterfaceName = createUniqueInterfaceName(XsltResId(STR_DEFAULT_UI_NAME));
+
+ // set default application
+ aTempInfo.maDocumentService = "com.sun.star.text.TextDocument";
+
+ // execute XML Filter Dialog
+ XMLFilterTabDialog aDlg(m_xDialog.get(), mxContext, &aTempInfo);
+ if (aDlg.run() == RET_OK)
+ {
+ // insert the new filter
+ insertOrEdit( aDlg.getNewFilterInfo() );
+ }
+}
+
+/** is called when the user clicks on the "Edit" Button */
+void XMLFilterSettingsDialog::onEdit()
+{
+ // get selected filter info
+ filter_info_impl* pOldInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_selected_id());
+ if (!pOldInfo)
+ return;
+
+ // execute XML Filter Dialog
+ XMLFilterTabDialog aDlg(m_xDialog.get(), mxContext, pOldInfo);
+ if (aDlg.run() == RET_OK)
+ {
+ filter_info_impl* pNewInfo = aDlg.getNewFilterInfo();
+
+ if( !(*pOldInfo == *pNewInfo) )
+ {
+ // change filter
+ insertOrEdit( pNewInfo, pOldInfo );
+ }
+ }
+}
+
+/** helper to create a sequence of strings from an extensions strings
+ "ext1;ext2;ext3" will become { "ext1", "ext2", "ext3" } */
+static Sequence< OUString > createExtensionsSequence( const OUString& rExtensions )
+{
+ // first count how many extensions we have inside the string
+ int nExtensions = 0;
+
+ int nLength = rExtensions.getLength();
+ if( nLength )
+ {
+ // a non empty string has at least one extension
+ nExtensions++;
+
+ // now count the delimiters ';'
+ const sal_Unicode * pString = rExtensions.getStr();
+ int i;
+ for( i = 0; i < nLength; i++, pString++ )
+ {
+ if( *pString == ';' )
+ nExtensions++;
+ }
+ }
+
+ Sequence< OUString > aExtensions( nExtensions );
+ auto aExtensionsRange = asNonConstRange(aExtensions);
+
+ // extract the extensions from the source string and fill the sequence
+
+ int nLastIndex = 0;
+ int nCurrentIndex = 0;
+ int i;
+
+ for( i = 0; i < nExtensions; i++ )
+ {
+ nLastIndex = rExtensions.indexOf( ';', nLastIndex );
+
+ if( nLastIndex == -1 )
+ {
+ aExtensionsRange[i] = rExtensions.copy( nCurrentIndex );
+ break;
+ }
+ else
+ {
+ aExtensionsRange[i] = rExtensions.copy( nCurrentIndex, nLastIndex - nCurrentIndex );
+ nCurrentIndex = nLastIndex + 1;
+ nLastIndex = nCurrentIndex;
+ }
+ }
+
+ return aExtensions;
+}
+
+/** checks if the given name is unique inside the filter factory. If not,
+ numbers are added until the returned name is unique */
+OUString XMLFilterSettingsDialog::createUniqueFilterName( const OUString& rFilterName )
+{
+ OUString aFilterName( rFilterName );
+
+ sal_Int32 nId = 2;
+
+ while( mxFilterContainer->hasByName( aFilterName ) )
+ {
+ aFilterName = rFilterName + " " + OUString::number( nId++ );
+ }
+
+ return aFilterName;
+}
+
+/** checks if the given name is unique inside the type detection. If not,
+ numbers are added until the returned name is unique */
+OUString XMLFilterSettingsDialog::createUniqueTypeName( const OUString& rTypeName )
+{
+ OUString aTypeName( rTypeName );
+
+ sal_Int32 nId = 2;
+
+ while( mxFilterContainer->hasByName( aTypeName ) )
+ {
+ aTypeName = rTypeName + " " + OUString::number( nId++ );
+ }
+
+ return aTypeName;
+}
+
+/** checks if the given name is a unique ui name inside the filter factory. If not,
+ numbers are added until the returned name is unique */
+OUString XMLFilterSettingsDialog::createUniqueInterfaceName( const OUString& rInterfaceName )
+{
+ sal_Int32 nDefaultNumber = 0;
+
+ try
+ {
+ const Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
+
+ Sequence< PropertyValue > aValues;
+ for( OUString const & filterName : aFilterNames)
+ {
+ Any aAny( mxFilterContainer->getByName( filterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ const sal_Int32 nValueCount( aValues.getLength() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 nValue;
+
+ for( nValue = 0; nValue < nValueCount; nValue++, pValues++ )
+ {
+ if ( pValues->Name == "UIName" )
+ {
+ OUString aInterfaceName;
+ pValues->Value >>= aInterfaceName;
+
+
+ // see if this filter matches our default filter name
+ if( aInterfaceName.match( rInterfaceName ) )
+ {
+ // if yes, make sure we generate a unique name with a higher number
+ // this is dump but fast
+ sal_Int32 nNumber = o3tl::toInt32(aInterfaceName.subView( rInterfaceName.getLength() ));
+ if( nNumber >= nDefaultNumber )
+ nDefaultNumber = nNumber + 1;
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ OUString aInterfaceName( rInterfaceName );
+ if( nDefaultNumber )
+ {
+ aInterfaceName += " " + OUString::number( nDefaultNumber );
+ }
+
+ return aInterfaceName;
+}
+
+/** inserts a new filter into the ui and configuration if pOldInfo is NULL.
+ If pOldInfo is not null, the old filter will be replaced with the new settings */
+bool XMLFilterSettingsDialog::insertOrEdit( filter_info_impl* pNewInfo, const filter_info_impl* pOldInfo )
+{
+ bool bOk = true;
+
+ if( pOldInfo )
+ {
+ // see if we need to update the type name
+ if( pOldInfo->maFilterName != pNewInfo->maFilterName )
+ {
+ if( pOldInfo->maType == pOldInfo->maFilterName )
+ {
+ pNewInfo->maType.clear();
+ }
+ }
+
+ // see if we need to clean up old stuff first
+ try
+ {
+ // if filter name changed, we need to remove the old filter first
+ if( pOldInfo->maFilterName != pNewInfo->maFilterName )
+ mxFilterContainer->removeByName( pOldInfo->maFilterName );
+
+ // if type name changed, we need to remove the old type first
+ if( pOldInfo->maType != pNewInfo->maType )
+ mxTypeDetection->removeByName( pOldInfo->maType );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+
+ filter_info_impl* pFilterEntry( nullptr );
+
+ if( bOk )
+ {
+ // create or copy filter info
+ if( pOldInfo )
+ {
+ // change existing filter entry in filter list box
+ pFilterEntry = const_cast<filter_info_impl*>(pOldInfo);
+ *pFilterEntry = *pNewInfo;
+ }
+ else
+ {
+ // add new entry to filter list box
+ pFilterEntry = new filter_info_impl( *pNewInfo );
+ }
+ }
+
+ // check if we need to copy the template
+ if( bOk && !pFilterEntry->maImportTemplate.isEmpty() )
+ {
+ if( !pFilterEntry->maImportTemplate.matchIgnoreAsciiCase( m_sTemplatePath ) )
+ {
+ INetURLObject aSourceURL( pFilterEntry->maImportTemplate );
+ if (!aSourceURL.GetLastName().isEmpty())
+ {
+ OUString aDestURL = m_sTemplatePath + pFilterEntry->maFilterName + "/";
+ if( createDirectory( aDestURL ) )
+ {
+ aDestURL += aSourceURL.GetLastName();
+
+ SvFileStream aInputStream(pFilterEntry->maImportTemplate, StreamMode::READ );
+ Reference< XInputStream > xIS( new utl::OInputStreamWrapper( aInputStream ) );
+ SvFileStream aOutputStream(aDestURL, StreamMode::WRITE );
+ Reference< XOutputStream > xOS( new utl::OOutputStreamWrapper( aOutputStream ) );
+
+ if( copyStreams( xIS, xOS ) )
+ pFilterEntry->maImportTemplate = aDestURL;
+ }
+ }
+ }
+ }
+
+ if( bOk )
+ {
+ if( pFilterEntry->maType.isEmpty() )
+ {
+ pFilterEntry->maType = createUniqueTypeName( pNewInfo->maFilterName );
+ }
+
+ // update import/export flags
+ if( !pFilterEntry->maImportXSLT.isEmpty() )
+ {
+ pFilterEntry->maFlags |= 1;
+ }
+ else
+ {
+ pFilterEntry->maFlags &= ~1;
+ }
+
+ if( !pFilterEntry->maExportXSLT.isEmpty() )
+ {
+ pFilterEntry->maFlags |= 2;
+ }
+ else
+ {
+ pFilterEntry->maFlags &= ~2;
+ }
+ pFilterEntry->maFlags |= 0x80040;
+
+ // 2. create user data for filter entry
+ Sequence< OUString > aUserData( pFilterEntry->getFilterUserData());
+
+ // 3. create property values for filter entry
+ Sequence< PropertyValue > aFilterData{
+ comphelper::makePropertyValue("Type", pFilterEntry->maType),
+ comphelper::makePropertyValue("UIName", pFilterEntry->maInterfaceName),
+ comphelper::makePropertyValue("DocumentService", pFilterEntry->maDocumentService),
+ comphelper::makePropertyValue("FilterService", OUString( "com.sun.star.comp.Writer.XmlFilterAdaptor" )),
+ comphelper::makePropertyValue("Flags", pFilterEntry->maFlags),
+ comphelper::makePropertyValue("UserData", aUserData),
+ comphelper::makePropertyValue("FileFormatVersion", pFilterEntry->maFileFormatVersion),
+ comphelper::makePropertyValue("TemplateName", pFilterEntry->maImportTemplate)
+ };
+
+ // 4. insert new or replace existing filter
+ try
+ {
+ Any aAny( aFilterData );
+ if( mxFilterContainer->hasByName( pFilterEntry->maFilterName ) )
+ {
+ mxFilterContainer->replaceByName( pFilterEntry->maFilterName, aAny );
+ }
+ else
+ {
+ mxFilterContainer->insertByName( pFilterEntry->maFilterName, aAny );
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+
+ // 5. prepare type information
+ if( bOk )
+ {
+ OUString aDocType;
+ if( !pFilterEntry->maDocType.match( m_sDocTypePrefix ) )
+ {
+ aDocType = m_sDocTypePrefix + pFilterEntry->maDocType;
+ }
+ else
+ {
+ aDocType = pFilterEntry->maDocType;
+ }
+ if (aDocType == m_sDocTypePrefix)
+ aDocType.clear();
+
+ Sequence< PropertyValue > aValues{
+ comphelper::makePropertyValue("UIName", pFilterEntry->maInterfaceName),
+ comphelper::makePropertyValue("ClipboardFormat", aDocType),
+ comphelper::makePropertyValue("DocumentIconID", pFilterEntry->mnDocumentIconID),
+ comphelper::makePropertyValue("Extensions", createExtensionsSequence( pFilterEntry->maExtension ))
+ };
+
+ // the detect service will only be registered, if a doctype/search token was specified
+ if (aDocType.getLength() > m_sDocTypePrefix.getLength())
+ {
+ aValues.realloc(5);
+ auto pValues = aValues.getArray();
+ pValues[4].Name = "DetectService";
+ pValues[4].Value <<= OUString( "com.sun.star.comp.filters.XMLFilterDetect" );
+ }
+
+ // 6. insert new or replace existing type information
+ if( mxTypeDetection.is() )
+ {
+ try
+ {
+ Any aAny( aValues );
+ if( mxTypeDetection->hasByName( pFilterEntry->maType ) )
+ {
+ mxTypeDetection->replaceByName( pFilterEntry->maType, aAny );
+ }
+ else
+ {
+ mxTypeDetection->insertByName( pFilterEntry->maType, aAny );
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+
+ if( bOk )
+ {
+ try
+ {
+ Reference< XFlushable > xFlushable( mxTypeDetection, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+
+ if( !bOk )
+ {
+ // we failed to add the type, so lets remove the filter
+ try
+ {
+ mxFilterContainer->removeByName( pFilterEntry->maFilterName );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+ else // bOk
+ {
+ try
+ {
+ Reference< XFlushable > xFlushable( mxFilterContainer, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+
+ if( !bOk )
+ {
+ // we failed to add the filter, so lets remove the type
+ try
+ {
+ mxTypeDetection->removeByName( pFilterEntry->maType );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ }
+ }
+ }
+
+ if( bOk )
+ {
+ if( mxExtendedTypeDetection.is() )
+ {
+ OUString sFilterDetectService( "com.sun.star.comp.filters.XMLFilterDetect" );
+ if( mxExtendedTypeDetection->hasByName( sFilterDetectService ) )
+ {
+ Sequence< PropertyValue > aSequence;
+ if( mxExtendedTypeDetection->getByName( sFilterDetectService ) >>= aSequence )
+ {
+ auto aSequenceRange = asNonConstRange(aSequence);
+ sal_Int32 nCount = aSequence.getLength();
+ sal_Int32 nIndex;
+ for( nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ if ( aSequence[nIndex].Name == "Types" )
+ {
+ Sequence< OUString > aTypes;
+ if( aSequence[nIndex].Value >>= aTypes )
+ {
+ sal_Int32 nStrCount = aTypes.getLength();
+ sal_Int32 nStr;
+ for( nStr = 0; nStr < nStrCount; nStr++ )
+ {
+ if( aTypes[nStr] == pFilterEntry->maType )
+ break;
+ }
+
+ if( nStr == nStrCount )
+ {
+ aTypes.realloc( nStrCount + 1 );
+ aTypes.getArray()[nStrCount] = pFilterEntry->maType;
+
+ aSequenceRange[nIndex].Value <<= aTypes;
+
+ mxExtendedTypeDetection->replaceByName( sFilterDetectService, Any( aSequence ) );
+
+ Reference< XFlushable > xFlushable( mxExtendedTypeDetection, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // update ui
+ if( bOk )
+ {
+ if( pOldInfo )
+ {
+ changeEntry( pFilterEntry );
+ }
+ else
+ {
+ addFilterEntry( pFilterEntry );
+ maFilterVector.push_back( std::unique_ptr<filter_info_impl>(pFilterEntry) );
+ }
+ }
+
+ return bOk;
+}
+
+/** is called when the user clicks the "Test" button */
+void XMLFilterSettingsDialog::onTest()
+{
+ // get the first selected filter
+ filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_selected_id());
+ if (pInfo)
+ {
+ XMLFilterTestDialog aDlg(m_xDialog.get(), mxContext);
+ aDlg.test( *pInfo );
+ }
+}
+
+void XMLFilterSettingsDialog::onDelete()
+{
+ int nIndex = m_xFilterListBox->get_selected_index();
+ if (nIndex == -1)
+ return;
+ filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(nIndex));
+ if (pInfo)
+ {
+ OUString aMessage(XsltResId(STR_WARN_DELETE));
+ aMessage = aMessage.replaceFirst( "%s", pInfo->maFilterName );
+
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::YesNo,
+ aMessage));
+ xWarn->set_default_response(RET_YES);
+ if (xWarn->run() == RET_YES)
+ {
+ try
+ {
+ if( mxFilterContainer->hasByName( pInfo->maFilterName ) )
+ {
+ mxFilterContainer->removeByName( pInfo->maFilterName );
+
+ bool bTypeStillUsed = false;
+
+ // now loop over all filter and see if someone else uses the same type
+ Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
+ OUString* pFilterName = aFilterNames.getArray();
+
+ const sal_Int32 nCount = aFilterNames.getLength();
+ sal_Int32 nFilter;
+ Sequence< PropertyValue > aValues;
+
+ for( nFilter = 0; (nFilter < nCount) && !bTypeStillUsed; nFilter++, pFilterName++ )
+ {
+ Any aAny( mxFilterContainer->getByName( *pFilterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ const sal_Int32 nValueCount( aValues.getLength() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 nValue;
+
+ for (nValue = 0; nValue < nValueCount; nValue++, pValues++)
+ {
+ if ( pValues->Name == "Type" )
+ {
+ OUString aType;
+ pValues->Value >>= aType;
+ if( aType == pInfo->maType )
+ bTypeStillUsed = true;
+
+ break;
+ }
+ }
+ }
+
+ // if the type is not used anymore, remove it also
+ if( !bTypeStillUsed )
+ {
+ if( mxTypeDetection->hasByName( pInfo->maType ) )
+ {
+ mxTypeDetection->removeByName( pInfo->maType );
+ }
+ }
+
+ Reference< XFlushable > xFlushable( mxFilterContainer, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+
+ xFlushable.set( mxTypeDetection, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+
+ // now remove entry from ui
+ m_xFilterListBox->remove(nIndex);
+
+ // and delete the filter entry
+ maFilterVector.erase(std::find_if( maFilterVector.begin(), maFilterVector.end(),
+ [&] (std::unique_ptr<filter_info_impl> const & p)
+ { return p.get() == pInfo; }));
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+ }
+ }
+
+ updateStates();
+}
+
+void XMLFilterSettingsDialog::onSave()
+{
+ std::vector<filter_info_impl*> aFilters;
+
+ int nFilters = 0;
+
+ m_xFilterListBox->selected_foreach([&](weld::TreeIter& rEntry){
+ filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(rEntry));
+ aFilters.push_back(pInfo);
+ ++nFilters;
+ return false;
+ });
+
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE, m_xDialog.get());
+ aDlg.SetContext(sfx2::FileDialogHelper::XMLFilterSettings);
+
+ OUString aExtensions( "*.jar" );
+ OUString aFilterName = XsltResId(STR_FILTER_PACKAGE) +
+ " (" + aExtensions + ")";
+
+ aDlg.AddFilter( aFilterName, aExtensions );
+
+ if ( aDlg.Execute() != ERRCODE_NONE )
+ return;
+
+ XMLFilterJarHelper aJarHelper( mxContext );
+ aJarHelper.savePackage( aDlg.GetPath(), aFilters );
+
+ INetURLObject aURL( aDlg.GetPath() );
+
+ OUString sPlaceholder( "%s" );
+
+ OUString aMsg;
+ if( nFilters > 0 )
+ {
+ aMsg = XsltResId(STR_FILTERS_HAVE_BEEN_SAVED);
+ aMsg = aMsg.replaceFirst( sPlaceholder, OUString::number( nFilters ) );
+ aMsg = aMsg.replaceFirst(sPlaceholder, aURL.GetLastName());
+ }
+ else
+ {
+ aMsg = XsltResId(STR_FILTER_HAS_BEEN_SAVED);
+ aMsg = aMsg.replaceFirst( sPlaceholder, (*aFilters.begin())->maFilterName );
+ aMsg = aMsg.replaceFirst(sPlaceholder, aURL.GetLastName());
+ }
+
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ aMsg));
+ xInfoBox->run();
+}
+
+void XMLFilterSettingsDialog::onOpen()
+{
+ std::vector< std::unique_ptr<filter_info_impl> > aFilters;
+
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_xDialog.get());
+ aDlg.SetContext(sfx2::FileDialogHelper::XMLFilterSettings);
+
+ OUString aExtensions( "*.jar" );
+ OUString aFilterName = XsltResId(STR_FILTER_PACKAGE) +
+ " (" + aExtensions + ")";
+
+ aDlg.AddFilter( aFilterName, aExtensions );
+
+ if ( aDlg.Execute() != ERRCODE_NONE )
+ return;
+
+ OUString aURL( aDlg.GetPath() );
+
+ XMLFilterJarHelper aJarHelper( mxContext );
+ aJarHelper.openPackage( aURL, aFilters );
+
+ int nFilters = 0;
+ for (auto& filter : aFilters)
+ {
+ if( insertOrEdit(filter.get()) )
+ {
+ aFilterName = filter->maFilterName;
+ nFilters++;
+ }
+
+ filter.reset();
+ }
+
+ disposeFilterList();
+ initFilterList();
+
+ OUString sPlaceholder( "%s" );
+ OUString aMsg;
+ if( nFilters == 0 )
+ {
+ INetURLObject aURLObj( aURL );
+ aMsg = XsltResId(STR_NO_FILTERS_FOUND);
+ aMsg = aMsg.replaceFirst(sPlaceholder, aURLObj.GetLastName());
+ }
+ else if( nFilters == 1 )
+ {
+ aMsg = XsltResId(STR_FILTER_INSTALLED);
+ aMsg = aMsg.replaceFirst( sPlaceholder, aFilterName );
+
+ }
+ else
+ {
+ aMsg = XsltResId(STR_FILTERS_INSTALLED);
+ aMsg = aMsg.replaceFirst( sPlaceholder, OUString::number( nFilters ) );
+ }
+
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ aMsg));
+ xInfoBox->run();
+}
+
+void XMLFilterSettingsDialog::disposeFilterList()
+{
+ maFilterVector.clear();
+ m_xFilterListBox->clear();
+}
+
+void XMLFilterSettingsDialog::initFilterList()
+{
+ if( mxFilterContainer.is() )
+ {
+ const Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
+
+ Sequence< PropertyValue > aValues;
+
+ std::unique_ptr<filter_info_impl> pTempFilter( new filter_info_impl );
+ Sequence< OUString > aUserData;
+
+ for( OUString const & filterName : aFilterNames )
+ {
+ aUserData.realloc(0);
+
+ try
+ {
+ Any aAny( mxFilterContainer->getByName( filterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ OUString aFilterService;
+ pTempFilter->maFilterName = filterName;
+
+ const sal_Int32 nValueCount( aValues.getLength() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 nValue;
+
+ for( nValue = 0; nValue < nValueCount; nValue++, pValues++ )
+ {
+ if ( pValues->Name == "Type" )
+ {
+ pValues->Value >>= pTempFilter->maType;
+ }
+ else if ( pValues->Name == "UIName" )
+ {
+ pValues->Value >>= pTempFilter->maInterfaceName;
+ }
+ else if ( pValues->Name == "DocumentService" )
+ {
+ pValues->Value >>= pTempFilter->maDocumentService;
+ }
+ else if ( pValues->Name == "FilterService" )
+ {
+ pValues->Value >>= aFilterService;
+ }
+ else if ( pValues->Name == "Flags" )
+ {
+ pValues->Value >>= pTempFilter->maFlags;
+ }
+ else if ( pValues->Name == "UserData" )
+ {
+ pValues->Value >>= aUserData;
+ }
+ else if ( pValues->Name == "FileFormatVersion" )
+ {
+ pValues->Value >>= pTempFilter->maFileFormatVersion;
+ }
+ else if ( pValues->Name == "TemplateName" )
+ {
+ pValues->Value >>= pTempFilter->maImportTemplate;
+ }
+ else if ( pValues->Name == "Finalized" )
+ {
+ pValues->Value >>= pTempFilter->mbReadonly;
+ }
+ }
+
+ // if this is not a XmlFilterAdaptor entry, skip it
+ if( aFilterService != "com.sun.star.comp.Writer.XmlFilterAdaptor" )
+ continue;
+
+
+ // if we don't have the needed user data, skip it
+ if( aUserData.getLength() < 6 )
+ continue;
+
+ // if this is not an XSLTFilter entry, skip it
+ if( aUserData[0] != "com.sun.star.documentconversion.XSLTFilter" )
+ continue;
+
+ // get filter information from userdata
+ pTempFilter->mbNeedsXSLT2 = aUserData[1].toBoolean();
+ pTempFilter->maImportService = aUserData[2];
+ pTempFilter->maExportService = aUserData[3];
+ pTempFilter->maImportXSLT = aUserData[4];
+ pTempFilter->maExportXSLT = aUserData[5];
+ if( aUserData.getLength() >= 8 )
+ pTempFilter->maComment = aUserData[7];
+
+ // get type information
+ if( mxTypeDetection.is() )
+ {
+ try
+ {
+ aAny = mxTypeDetection->getByName( pTempFilter->maType );
+ Sequence< PropertyValue > aValues2;
+
+ if( aAny >>= aValues2 )
+ {
+ const sal_Int32 nValueCount2( aValues2.getLength() );
+ PropertyValue* pValues2 = aValues2.getArray();
+ sal_Int32 nValue2;
+
+ for( nValue2 = 0; nValue2 < nValueCount2; nValue2++, pValues2++ )
+ {
+ if ( pValues2->Name == "ClipboardFormat" )
+ {
+ OUString aDocType;
+ pValues2->Value >>= aDocType;
+
+ if( aDocType.match( m_sDocTypePrefix ) )
+ aDocType = aDocType.copy( m_sDocTypePrefix.getLength() );
+
+ pTempFilter->maDocType = aDocType;
+ }
+ else if ( pValues2->Name == "Extensions" )
+ {
+ Sequence< OUString > aExtensions;
+ if( pValues2->Value >>= aExtensions )
+ {
+ pTempFilter->maExtension.clear();
+
+ sal_Int32 nCount3( aExtensions.getLength() );
+ OUString* pExtensions = aExtensions.getArray();
+ sal_Int32 n;
+ for( n = 0; n < nCount3; n++ )
+ {
+ if( n > 0 )
+ pTempFilter->maExtension += ";";
+ pTempFilter->maExtension += *pExtensions++;
+ }
+ }
+ }
+ else if ( pValues2->Name == "DocumentIconID" )
+ {
+ pValues2->Value >>= pTempFilter->mnDocumentIconID;
+ }
+ else if ( pValues2->Name == "Finalized" )
+ {
+ // both the filter and the type may be finalized
+ bool bTemp = false;
+ pValues2->Value >>= bTemp;
+ pTempFilter->mbReadonly |= bTemp;
+ }
+ }
+ }
+ }
+ catch( const css::container::NoSuchElementException& )
+ {
+ OSL_FAIL( "Type not found, user error?" ); // TODO: error?
+ }
+ }
+
+ // add entry to internal container and to ui filter list box
+ maFilterVector.push_back( std::unique_ptr<filter_info_impl>(pTempFilter.get()) );
+ addFilterEntry( pTempFilter.release() );
+
+
+ pTempFilter.reset( new filter_info_impl );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ }
+ }
+
+ if (m_xFilterListBox->n_children())
+ {
+ m_xFilterListBox->columns_autosize();
+ m_xFilterListBox->select(0);
+ }
+}
+
+application_info_impl::application_info_impl( const char * pDocumentService, const OUString& rUINameRes, const char * mpXMLImporter, const char * mpXMLExporter )
+: maDocumentService( pDocumentService, strlen( pDocumentService ), RTL_TEXTENCODING_ASCII_US ),
+ maDocumentUIName(Translate::ExpandVariables(rUINameRes)),
+ maXMLImporter( mpXMLImporter, strlen( mpXMLImporter ), RTL_TEXTENCODING_ASCII_US ),
+ maXMLExporter( mpXMLExporter, strlen( mpXMLExporter ), RTL_TEXTENCODING_ASCII_US )
+{
+}
+
+std::vector< application_info_impl > const & getApplicationInfos()
+{
+ static std::vector< application_info_impl > const aInfos
+ {
+ { "com.sun.star.text.TextDocument",
+ STR_APPL_NAME_WRITER,
+ "com.sun.star.comp.Writer.XMLImporter",
+ "com.sun.star.comp.Writer.XMLExporter" },
+
+ { "com.sun.star.sheet.SpreadsheetDocument",
+ STR_APPL_NAME_CALC,
+ "com.sun.star.comp.Calc.XMLImporter",
+ "com.sun.star.comp.Calc.XMLExporter" },
+
+ { "com.sun.star.presentation.PresentationDocument",
+ STR_APPL_NAME_IMPRESS,
+ "com.sun.star.comp.Impress.XMLImporter",
+ "com.sun.star.comp.Impress.XMLExporter" },
+
+ { "com.sun.star.drawing.DrawingDocument",
+ STR_APPL_NAME_DRAW,
+ "com.sun.star.comp.Draw.XMLImporter",
+ "com.sun.star.comp.Draw.XMLExporter" },
+
+ // --- oasis file formats...
+ { "com.sun.star.text.TextDocument",
+ STR_APPL_NAME_OASIS_WRITER,
+ "com.sun.star.comp.Writer.XMLOasisImporter",
+ "com.sun.star.comp.Writer.XMLOasisExporter" },
+
+ { "com.sun.star.sheet.SpreadsheetDocument",
+ STR_APPL_NAME_OASIS_CALC,
+ "com.sun.star.comp.Calc.XMLOasisImporter",
+ "com.sun.star.comp.Calc.XMLOasisExporter" },
+
+ { "com.sun.star.presentation.PresentationDocument",
+ STR_APPL_NAME_OASIS_IMPRESS,
+ "com.sun.star.comp.Impress.XMLOasisImporter",
+ "com.sun.star.comp.Impress.XMLOasisExporter" },
+
+ { "com.sun.star.drawing.DrawingDocument",
+ STR_APPL_NAME_OASIS_DRAW,
+ "com.sun.star.comp.Draw.XMLOasisImporter",
+ "com.sun.star.comp.Draw.XMLOasisExporter" },
+ };
+
+ return aInfos;
+}
+
+const application_info_impl* getApplicationInfo( std::u16string_view rServiceName )
+{
+ std::vector< application_info_impl > const & rInfos = getApplicationInfos();
+ for (auto const& info : rInfos)
+ {
+ if( rServiceName == info.maXMLExporter ||
+ rServiceName == info.maXMLImporter)
+ {
+ return &info;
+ }
+ }
+ return nullptr;
+}
+
+OUString getApplicationUIName( std::u16string_view rServiceName )
+{
+ const application_info_impl* pInfo = getApplicationInfo( rServiceName );
+ if( pInfo )
+ {
+ return pInfo->maDocumentUIName;
+ }
+ else
+ {
+ OUString aRet = XsltResId(STR_UNKNOWN_APPLICATION);
+ if( !rServiceName.empty() )
+ {
+ aRet += OUString::Concat(" (") + rServiceName + ")";
+ }
+ return aRet;
+ }
+}
+
+/** adds a new filter info entry to the ui filter list */
+void XMLFilterSettingsDialog::addFilterEntry( const filter_info_impl* pInfo )
+{
+ int nRow = m_xFilterListBox->n_children();
+ OUString sId(weld::toId(pInfo));
+ m_xFilterListBox->append(sId, pInfo->maFilterName);
+ m_xFilterListBox->set_text(nRow, getEntryString(pInfo), 1);
+}
+
+void XMLFilterSettingsDialog::changeEntry( const filter_info_impl* pInfo )
+{
+ const int nCount = m_xFilterListBox->n_children();
+ for(int nPos = 0; nPos < nCount; ++nPos)
+ {
+ filter_info_impl* pEntry = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(nPos));
+ if (pEntry == pInfo)
+ {
+ m_xFilterListBox->set_text(nPos, pInfo->maFilterName, 0);
+ m_xFilterListBox->set_text(nPos, getEntryString(pInfo), 1);
+ break;
+ }
+ }
+}
+
+OUString XMLFilterSettingsDialog::getEntryString( const filter_info_impl* pInfo )
+{
+ OUString aEntryStr;
+ if ( !pInfo->maExportService.isEmpty() )
+ aEntryStr = getApplicationUIName( pInfo->maExportService );
+ else
+ aEntryStr = getApplicationUIName( pInfo->maImportService );
+ aEntryStr += " - ";
+
+ if( pInfo->maFlags & 1 )
+ {
+ if( pInfo->maFlags & 2 )
+ {
+ aEntryStr += XsltResId(STR_IMPORT_EXPORT);
+ }
+ else
+ {
+ aEntryStr += XsltResId(STR_IMPORT_ONLY);
+ }
+ }
+ else if( pInfo->maFlags & 2 )
+ {
+ aEntryStr += XsltResId(STR_EXPORT_ONLY);
+ }
+ else
+ {
+ aEntryStr += XsltResId(STR_UNDEFINED_FILTER);
+ }
+
+ return aEntryStr;
+}
+
+filter_info_impl::filter_info_impl()
+ : maFlags(0x00080040)
+ , maFileFormatVersion(0)
+ , mnDocumentIconID(0)
+ , mbReadonly(false)
+ , mbNeedsXSLT2(false)
+{
+}
+
+bool filter_info_impl::operator==( const filter_info_impl& r ) const
+{
+ return maFilterName == r.maFilterName &&
+ maType == r.maType &&
+ maDocumentService == r.maDocumentService &&
+ maInterfaceName == r.maInterfaceName &&
+ maComment == r.maComment &&
+ maExtension == r.maExtension &&
+ maDocType == r.maDocType &&
+ maExportXSLT == r.maExportXSLT &&
+ maImportXSLT == r.maImportXSLT &&
+ maExportService == r.maExportService &&
+ maImportService == r.maImportService &&
+ maImportTemplate == r.maImportTemplate &&
+ maFlags == r.maFlags &&
+ maFileFormatVersion == r.maFileFormatVersion &&
+ mbNeedsXSLT2 == r.mbNeedsXSLT2;
+}
+
+
+Sequence< OUString > filter_info_impl::getFilterUserData() const
+{
+ return
+ {
+ "com.sun.star.documentconversion.XSLTFilter",
+ OUString::boolean( mbNeedsXSLT2 ),
+ maImportService,
+ maExportService,
+ maImportXSLT,
+ maExportXSLT,
+ maComment
+ };
+}
+
+OUString string_encode( const OUString & rText )
+{
+ static constexpr auto uricNoSlash = rtl::createUriCharClass(
+ u8"!$&'()*+-.0123456789:=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~");
+
+
+ return
+ Uri::encode( rText, uricNoSlash.data(), rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8 );
+}
+
+OUString string_decode( const OUString & rText )
+{
+ return Uri::decode( rText, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
+}
+
+bool copyStreams( const Reference< XInputStream >& xIS, const Reference< XOutputStream >& xOS )
+{
+ try
+ {
+ sal_Int32 nBufferSize = 512;
+ Sequence< sal_Int8 > aDataBuffer(nBufferSize);
+
+ sal_Int32 nRead;
+ do
+ {
+ nRead = xIS->readBytes( aDataBuffer, nBufferSize );
+
+ if( nRead )
+ {
+ if( nRead < nBufferSize )
+ {
+ nBufferSize = nRead;
+ aDataBuffer.realloc(nRead);
+ }
+
+ xOS->writeBytes( aDataBuffer );
+ }
+ }
+ while( nRead );
+
+ xOS->flush();
+
+ return true;
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ return false;
+}
+
+bool createDirectory( std::u16string_view rURL )
+{
+ size_t nLastIndex = sizeof( "file:///" ) - 2;
+ while( nLastIndex != std::u16string_view::npos )
+ {
+ nLastIndex = rURL.find( '/', nLastIndex + 1);
+ if( nLastIndex != std::u16string_view::npos )
+ {
+ OUString aDirURL( rURL.substr( 0, nLastIndex ) );
+ Directory aDir( aDirURL );
+ Directory::RC rc = aDir.open();
+ if( rc == Directory::E_NOENT )
+ rc = osl::Directory::create( aDirURL );
+
+ if( rc != Directory::E_None )
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx b/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx
new file mode 100644
index 000000000..c555e8b16
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx
@@ -0,0 +1,97 @@
+/* -*- 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/container/XNameContainer.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <vcl/weld.hxx>
+#include <vcl/locktoplevels.hxx>
+#include <unotools/moduleoptions.hxx>
+
+#include "xmlfiltercommon.hxx"
+
+class XMLFilterSettingsDialog : public weld::GenericDialogController
+{
+public:
+ XMLFilterSettingsDialog(weld::Window* pParent,
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+ virtual ~XMLFilterSettingsDialog() override;
+
+ DECL_LINK(ClickHdl_Impl, weld::Button&, void );
+ DECL_LINK(SelectionChangedHdl_Impl, weld::TreeView&, void);
+ DECL_LINK(DoubleClickHdl_Impl, weld::TreeView&, bool);
+
+ void UpdateWindow();
+
+ void present() { m_xDialog->present(); }
+
+ void onNew();
+ void onEdit();
+ void onTest();
+ void onDelete();
+ void onSave();
+ void onOpen();
+
+ void updateStates();
+private:
+ void initFilterList();
+ void disposeFilterList();
+
+ void incBusy() { maBusy.incBusy(m_xDialog.get()); }
+ void decBusy() { maBusy.decBusy(); }
+
+ bool insertOrEdit( filter_info_impl* pNewInfo, const filter_info_impl* pOldInfo = nullptr );
+
+ OUString createUniqueFilterName( const OUString& rUIName );
+ OUString createUniqueTypeName( const OUString& rTypeName );
+ OUString createUniqueInterfaceName( const OUString& rInterfaceName );
+
+ /** adds a new filter info entry to the ui filter list */
+ void addFilterEntry( const filter_info_impl* pInfo );
+
+ void changeEntry( const filter_info_impl* pInfo );
+
+ static OUString getEntryString( const filter_info_impl* pInfo );
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::container::XNameContainer > mxFilterContainer;
+ css::uno::Reference< css::container::XNameContainer > mxTypeDetection;
+ css::uno::Reference< css::container::XNameContainer > mxExtendedTypeDetection;
+
+ std::vector< std::unique_ptr<filter_info_impl> > maFilterVector;
+
+ TopLevelWindowLocker maBusy;
+
+ OUString m_sTemplatePath;
+ OUString m_sDocTypePrefix;
+
+ SvtModuleOptions maModuleOpt;
+
+ std::unique_ptr<weld::Button> m_xPBNew;
+ std::unique_ptr<weld::Button> m_xPBEdit;
+ std::unique_ptr<weld::Button> m_xPBTest;
+ std::unique_ptr<weld::Button> m_xPBDelete;
+ std::unique_ptr<weld::Button> m_xPBSave;
+ std::unique_ptr<weld::Button> m_xPBOpen;
+ std::unique_ptr<weld::Button> m_xPBClose;
+ std::unique_ptr<weld::TreeView> m_xFilterListBox;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabdialog.cxx b/filter/source/xsltdialog/xmlfiltertabdialog.cxx
new file mode 100644
index 000000000..ea73c486a
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabdialog.cxx
@@ -0,0 +1,263 @@
+/* -*- 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/container/XNameAccess.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/fileurl.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <osl/file.hxx>
+#include <unotools/resmgr.hxx>
+
+#include <strings.hrc>
+#include "xmlfiltertabdialog.hxx"
+#include "xmlfiltertabpagebasic.hxx"
+#include "xmlfiltertabpagexslt.hxx"
+#include "xmlfiltercommon.hxx"
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::container;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::lang;
+
+XMLFilterTabDialog::XMLFilterTabDialog(weld::Window *pParent,
+ const Reference< XComponentContext >& rxContext, const filter_info_impl* pInfo)
+ : GenericDialogController(pParent, "filter/ui/xsltfilterdialog.ui", "XSLTFilterDialog")
+ , mxContext(rxContext)
+ , m_xTabCtrl(m_xBuilder->weld_notebook("tabcontrol"))
+ , m_xOKBtn(m_xBuilder->weld_button("ok"))
+ , mpBasicPage(new XMLFilterTabPageBasic(m_xTabCtrl->get_page("general")))
+ , mpXSLTPage(new XMLFilterTabPageXSLT(m_xTabCtrl->get_page("transformation"), m_xDialog.get()))
+{
+ mpOldInfo = pInfo;
+ mpNewInfo.reset( new filter_info_impl( *mpOldInfo ) );
+
+ OUString aTitle(m_xDialog->get_title());
+ aTitle = aTitle.replaceAll("%s", mpNewInfo->maFilterName);
+ m_xDialog->set_title(aTitle);
+
+ m_xOKBtn->connect_clicked( LINK( this, XMLFilterTabDialog, OkHdl ) );
+
+ mpBasicPage->SetInfo( mpNewInfo.get() );
+ mpXSLTPage->SetInfo( mpNewInfo.get() );
+}
+
+XMLFilterTabDialog::~XMLFilterTabDialog()
+{
+}
+
+bool XMLFilterTabDialog::onOk()
+{
+ mpXSLTPage->FillInfo( mpNewInfo.get() );
+ mpBasicPage->FillInfo( mpNewInfo.get() );
+
+ OString sErrorPage;
+ TranslateId pErrorId;
+ weld::Widget* pFocusWindow = nullptr;
+ OUString aReplace1;
+ OUString aReplace2;
+
+ // 1. see if the filter name is ok
+ if( (mpNewInfo->maFilterName.isEmpty()) || (mpNewInfo->maFilterName != mpOldInfo->maFilterName) )
+ {
+ // if the user deleted the filter name, we reset the original filter name
+ if( mpNewInfo->maFilterName.isEmpty() )
+ {
+ mpNewInfo->maFilterName = mpOldInfo->maFilterName;
+ }
+ else
+ {
+ try
+ {
+ Reference< XNameAccess > xFilterContainer( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", mxContext ), UNO_QUERY );
+ if( xFilterContainer.is() )
+ {
+ if( xFilterContainer->hasByName( mpNewInfo->maFilterName ) )
+ {
+ sErrorPage = "general";
+ pErrorId = STR_ERROR_FILTER_NAME_EXISTS;
+ pFocusWindow = mpBasicPage->m_xEDFilterName.get();
+ aReplace1 = mpNewInfo->maFilterName;
+ }
+
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+ }
+ }
+
+ // 2. see if the interface name is ok
+ if( (mpNewInfo->maInterfaceName.isEmpty()) || (mpNewInfo->maInterfaceName != mpOldInfo->maInterfaceName) )
+ {
+ // if the user deleted the interface name, we reset the original filter name
+ if( mpNewInfo->maInterfaceName.isEmpty() )
+ {
+ mpNewInfo->maInterfaceName = mpOldInfo->maInterfaceName;
+ }
+ else
+ {
+ try
+ {
+ Reference< XNameAccess > xFilterContainer( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", mxContext ), UNO_QUERY );
+ if( xFilterContainer.is() )
+ {
+ Sequence< OUString > aFilterNames( xFilterContainer->getElementNames() );
+ OUString* pFilterName = aFilterNames.getArray();
+
+ const sal_Int32 nCount = aFilterNames.getLength();
+ sal_Int32 nFilter;
+
+ Sequence< PropertyValue > aValues;
+ for( nFilter = 0; (nFilter < nCount) && !pErrorId; nFilter++, pFilterName++ )
+ {
+ Any aAny( xFilterContainer->getByName( *pFilterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ const sal_Int32 nValueCount( aValues.getLength() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 nValue;
+
+ for( nValue = 0; (nValue < nValueCount) && !pErrorId; nValue++, pValues++ )
+ {
+ if ( pValues->Name == "UIName" )
+ {
+ OUString aInterfaceName;
+ pValues->Value >>= aInterfaceName;
+ if( aInterfaceName == mpNewInfo->maInterfaceName )
+ {
+ sErrorPage = "general";
+ pErrorId = STR_ERROR_TYPE_NAME_EXISTS;
+ pFocusWindow = mpBasicPage->m_xEDInterfaceName.get();
+ aReplace1 = mpNewInfo->maInterfaceName;
+ aReplace2 = *pFilterName;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+ }
+ }
+
+ if (!pErrorId)
+ {
+ // 4. see if the export xslt is valid
+ if( (mpNewInfo->maExportXSLT != mpOldInfo->maExportXSLT) && comphelper::isFileUrl( mpNewInfo->maExportXSLT ) )
+ {
+ osl::File aFile( mpNewInfo->maExportXSLT );
+ osl::File::RC aRC = aFile.open( osl_File_OpenFlag_Read );
+ if( aRC != osl::File::E_None )
+ {
+ pErrorId = STR_ERROR_EXPORT_XSLT_NOT_FOUND;
+ sErrorPage = "transformation";
+ pFocusWindow = mpXSLTPage->m_xEDExportXSLT->getWidget();
+ }
+ }
+ }
+
+ if (!pErrorId)
+ {
+ // 5. see if the import xslt is valid
+ if( (mpNewInfo->maImportXSLT != mpOldInfo->maImportXSLT) && comphelper::isFileUrl( mpNewInfo->maImportXSLT ) )
+ {
+ osl::File aFile( mpNewInfo->maImportXSLT );
+ osl::File::RC aRC = aFile.open( osl_File_OpenFlag_Read );
+ if( aRC != osl::File::E_None )
+ {
+ pErrorId = STR_ERROR_IMPORT_XSLT_NOT_FOUND;
+ sErrorPage = "transformation";
+ pFocusWindow = mpXSLTPage->m_xEDImportTemplate->getWidget();
+ }
+ }
+ }
+
+ // see if we have at least an import or an export xslt
+ if((mpNewInfo->maImportXSLT.isEmpty()) && (mpNewInfo->maExportXSLT.isEmpty()) )
+ {
+ pErrorId = STR_ERROR_EXPORT_XSLT_NOT_FOUND;
+ sErrorPage = "transformation";
+ pFocusWindow = mpXSLTPage->m_xEDExportXSLT->getWidget();
+ }
+
+ if (!pErrorId)
+ {
+ // 6. see if the import template is valid
+ if( (mpNewInfo->maImportTemplate != mpOldInfo->maImportTemplate) && comphelper::isFileUrl( mpNewInfo->maImportTemplate ) )
+ {
+ osl::File aFile( mpNewInfo->maImportTemplate );
+ osl::File::RC aRC = aFile.open( osl_File_OpenFlag_Read );
+ if( aRC != osl::File::E_None )
+ {
+ pErrorId = STR_ERROR_IMPORT_TEMPLATE_NOT_FOUND;
+ sErrorPage = "transformation";
+ pFocusWindow = mpXSLTPage->m_xEDImportTemplate->getWidget();
+ }
+ }
+ }
+
+ if (pErrorId)
+ {
+ m_xTabCtrl->set_current_page(sErrorPage);
+
+ OUString aMessage(XsltResId(pErrorId));
+
+ if( aReplace2.getLength() )
+ {
+ aMessage = aMessage.replaceAll( "%s1", aReplace1 );
+ aMessage = aMessage.replaceAll( "%s2", aReplace2 );
+ }
+ else if( aReplace1.getLength() )
+ {
+ aMessage = aMessage.replaceAll( "%s", aReplace1 );
+ }
+
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ aMessage));
+ xBox->run();
+
+ if( pFocusWindow )
+ pFocusWindow->grab_focus();
+
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+IMPL_LINK_NOARG(XMLFilterTabDialog, OkHdl, weld::Button&, void)
+{
+ if( onOk() )
+ m_xDialog->response(RET_OK);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabdialog.hxx b/filter/source/xsltdialog/xmlfiltertabdialog.hxx
new file mode 100644
index 000000000..e764102b0
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabdialog.hxx
@@ -0,0 +1,54 @@
+/* -*- 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/XComponentContext.hpp>
+#include <vcl/weld.hxx>
+
+class filter_info_impl;
+class XMLFilterTabPageBasic;
+class XMLFilterTabPageXSLT;
+
+class XMLFilterTabDialog : public weld::GenericDialogController
+{
+public:
+ XMLFilterTabDialog(weld::Window *pParent, const css::uno::Reference< css::uno::XComponentContext >& rxContext, const filter_info_impl* pInfo);
+ virtual ~XMLFilterTabDialog() override;
+
+ bool onOk();
+
+ filter_info_impl* getNewFilterInfo() const { return mpNewInfo.get(); }
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+
+ DECL_LINK(OkHdl, weld::Button&, void);
+
+ const filter_info_impl* mpOldInfo;
+ std::unique_ptr<filter_info_impl> mpNewInfo;
+
+ std::unique_ptr<weld::Notebook> m_xTabCtrl;
+ std::unique_ptr<weld::Button> m_xOKBtn;
+
+ std::unique_ptr<XMLFilterTabPageBasic> mpBasicPage;
+ std::unique_ptr<XMLFilterTabPageXSLT> mpXSLTPage;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabpagebasic.cxx b/filter/source/xsltdialog/xmlfiltertabpagebasic.cxx
new file mode 100644
index 000000000..63b969a2f
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabpagebasic.cxx
@@ -0,0 +1,128 @@
+/* -*- 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 <rtl/ustrbuf.hxx>
+#include <vcl/svapp.hxx>
+#include "xmlfiltercommon.hxx"
+#include "xmlfiltertabpagebasic.hxx"
+
+XMLFilterTabPageBasic::XMLFilterTabPageBasic(weld::Widget* pPage)
+ : m_xBuilder(Application::CreateBuilder(pPage, "filter/ui/xmlfiltertabpagegeneral.ui"))
+ , m_xContainer(m_xBuilder->weld_widget("XmlFilterTabPageGeneral"))
+ , m_xEDFilterName(m_xBuilder->weld_entry("filtername"))
+ , m_xCBApplication(m_xBuilder->weld_combo_box("application"))
+ , m_xEDInterfaceName(m_xBuilder->weld_entry("interfacename"))
+ , m_xEDExtension(m_xBuilder->weld_entry("extension"))
+ , m_xEDDescription(m_xBuilder->weld_text_view("description"))
+{
+ m_xEDDescription->set_size_request(-1, m_xEDDescription->get_height_rows(4));
+
+ std::vector< application_info_impl > const & rInfos = getApplicationInfos();
+ for (auto const& info : rInfos)
+ {
+ OUString aEntry( info.maDocumentUIName );
+ m_xCBApplication->append_text( aEntry );
+ }
+}
+
+XMLFilterTabPageBasic::~XMLFilterTabPageBasic()
+{
+}
+
+static OUString checkExtensions( const OUString& rExtensions )
+{
+ const sal_Unicode* pSource = rExtensions.getStr();
+ sal_Int32 nCount = rExtensions.getLength();
+
+ OUStringBuffer aRet;
+ while( nCount-- )
+ {
+ switch(*pSource)
+ {
+ case u',':
+ aRet.append(";");
+ break;
+ case u'.':
+ case u'*':
+ break;
+ default:
+ aRet.append( *pSource );
+ }
+
+ pSource++;
+ }
+
+ return aRet.makeStringAndClear();
+}
+
+void XMLFilterTabPageBasic::FillInfo( filter_info_impl* pInfo )
+{
+ if( !pInfo )
+ return;
+
+ if( !m_xEDFilterName->get_text().isEmpty() )
+ pInfo->maFilterName = m_xEDFilterName->get_text();
+
+ if( !m_xCBApplication->get_active_text().isEmpty() )
+ pInfo->maDocumentService = m_xCBApplication->get_active_text();
+
+ if( !m_xEDInterfaceName->get_text().isEmpty() )
+ pInfo->maInterfaceName = m_xEDInterfaceName->get_text();
+
+ if( !m_xEDExtension->get_text().isEmpty() )
+ pInfo->maExtension = checkExtensions( m_xEDExtension->get_text() );
+
+ pInfo->maComment = string_encode( m_xEDDescription->get_text() );
+
+ if( pInfo->maDocumentService.isEmpty() )
+ return;
+
+ std::vector< application_info_impl > const & rInfos = getApplicationInfos();
+ for (auto const& info : rInfos)
+ {
+ if( pInfo->maDocumentService == info.maDocumentUIName )
+ {
+ pInfo->maDocumentService = info.maDocumentService;
+ pInfo->maExportService = info.maXMLExporter;
+ pInfo->maImportService = info.maXMLImporter;
+ break;
+ }
+ }
+}
+
+void XMLFilterTabPageBasic::SetInfo(const filter_info_impl* pInfo)
+{
+ if( !pInfo )
+ return;
+
+ m_xEDFilterName->set_text( string_decode(pInfo->maFilterName) );
+ /*
+ if( pInfo->maDocumentService.getLength() )
+ maCBApplication.set_text( getApplicationUIName( pInfo->maDocumentService ) );
+ */
+ if( !pInfo->maExportService.isEmpty() )
+ m_xCBApplication->set_entry_text( getApplicationUIName( pInfo->maExportService ) );
+ else
+ m_xCBApplication->set_entry_text( getApplicationUIName( pInfo->maImportService ) );
+ m_xEDInterfaceName->set_text( string_decode(pInfo->maInterfaceName) );
+ m_xEDExtension->set_text( pInfo->maExtension );
+ m_xEDDescription->set_text( string_decode( pInfo->maComment ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx b/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx
new file mode 100644
index 000000000..c11a4c69e
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx
@@ -0,0 +1,43 @@
+/* -*- 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 <vcl/weld.hxx>
+
+class filter_info_impl;
+
+class XMLFilterTabPageBasic
+{
+public:
+ explicit XMLFilterTabPageBasic(weld::Widget* pPage);
+ ~XMLFilterTabPageBasic();
+
+ void FillInfo( filter_info_impl* pInfo );
+ void SetInfo(const filter_info_impl* pInfo);
+
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Widget> m_xContainer;
+ std::unique_ptr<weld::Entry> m_xEDFilterName;
+ std::unique_ptr<weld::ComboBox> m_xCBApplication;
+ std::unique_ptr<weld::Entry> m_xEDInterfaceName;
+ std::unique_ptr<weld::Entry> m_xEDExtension;
+ std::unique_ptr<weld::TextView> m_xEDDescription;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabpagexslt.cxx b/filter/source/xsltdialog/xmlfiltertabpagexslt.cxx
new file mode 100644
index 000000000..4d758da28
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabpagexslt.cxx
@@ -0,0 +1,165 @@
+/* -*- 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/ui/dialogs/TemplateDescription.hpp>
+#include <sfx2/filedlghelper.hxx>
+#include <unotools/pathoptions.hxx>
+#include <osl/file.hxx>
+#include <svl/urihelper.hxx>
+#include <vcl/svapp.hxx>
+
+#include "xmlfiltercommon.hxx"
+#include "xmlfiltertabpagexslt.hxx"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+XMLFilterTabPageXSLT::XMLFilterTabPageXSLT(weld::Widget* pPage, weld::Dialog* pDialog)
+ : sInstPath( "$(prog)/" )
+ , m_pDialog(pDialog)
+ , m_xBuilder(Application::CreateBuilder(pPage, "filter/ui/xmlfiltertabpagetransformation.ui"))
+ , m_xContainer(m_xBuilder->weld_widget("XmlFilterTabPageTransformation"))
+ , m_xEDDocType(m_xBuilder->weld_entry("doc"))
+ , m_xEDExportXSLT(new SvtURLBox(m_xBuilder->weld_combo_box("xsltexport")))
+ , m_xPBExprotXSLT(m_xBuilder->weld_button("browseexport"))
+ , m_xEDImportXSLT(new SvtURLBox(m_xBuilder->weld_combo_box("xsltimport")))
+ , m_xPBImportXSLT(m_xBuilder->weld_button("browseimport"))
+ , m_xEDImportTemplate(new SvtURLBox(m_xBuilder->weld_combo_box("tempimport")))
+ , m_xPBImportTemplate(m_xBuilder->weld_button("browsetemp"))
+ , m_xCBNeedsXSLT2(m_xBuilder->weld_check_button("filtercb"))
+{
+ SvtPathOptions aOptions;
+ sInstPath = aOptions.SubstituteVariable( sInstPath );
+
+ m_xPBExprotXSLT->connect_clicked( LINK ( this, XMLFilterTabPageXSLT, ClickBrowseHdl_Impl ) );
+ m_xPBImportXSLT->connect_clicked( LINK ( this, XMLFilterTabPageXSLT, ClickBrowseHdl_Impl ) );
+ m_xPBImportTemplate->connect_clicked( LINK ( this, XMLFilterTabPageXSLT, ClickBrowseHdl_Impl ) );
+}
+
+XMLFilterTabPageXSLT::~XMLFilterTabPageXSLT()
+{
+}
+
+void XMLFilterTabPageXSLT::FillInfo( filter_info_impl* pInfo )
+{
+ if( pInfo )
+ {
+ pInfo->maDocType = m_xEDDocType->get_text();
+ pInfo->maExportXSLT = GetURL(*m_xEDExportXSLT);
+ pInfo->maImportXSLT = GetURL(*m_xEDImportXSLT);
+ pInfo->maImportTemplate = GetURL(*m_xEDImportTemplate);
+ pInfo->mbNeedsXSLT2 = m_xCBNeedsXSLT2->get_active();
+ }
+}
+
+void XMLFilterTabPageXSLT::SetInfo(const filter_info_impl* pInfo)
+{
+ if( pInfo )
+ {
+ m_xEDDocType->set_text( pInfo->maDocType );
+
+ SetURL( *m_xEDExportXSLT, pInfo->maExportXSLT );
+ SetURL( *m_xEDImportXSLT, pInfo->maImportXSLT );
+ SetURL( *m_xEDImportTemplate, pInfo->maImportTemplate );
+ m_xCBNeedsXSLT2->set_active(pInfo->mbNeedsXSLT2);
+ }
+}
+
+void XMLFilterTabPageXSLT::SetURL( SvtURLBox& rURLBox, const OUString& rURL )
+{
+ OUString aPath;
+
+ if( rURL.matchIgnoreAsciiCase( "file://" ) )
+ {
+ osl::FileBase::getSystemPathFromFileURL( rURL, aPath );
+
+ rURLBox.SetBaseURL( rURL );
+ rURLBox.set_entry_text( aPath );
+ }
+ else if( rURL.matchIgnoreAsciiCase( "http://" ) ||
+ rURL.matchIgnoreAsciiCase( "https://" ) ||
+ rURL.matchIgnoreAsciiCase( "ftp://" ) )
+ {
+ rURLBox.SetBaseURL( rURL );
+ rURLBox.set_entry_text( rURL );
+ }
+ else if( !rURL.isEmpty() )
+ {
+ OUString aURL = URIHelper::SmartRel2Abs( INetURLObject(sInstPath), rURL, Link<OUString *, bool>(), false );
+ osl::FileBase::getSystemPathFromFileURL( aURL, aPath );
+
+ rURLBox.SetBaseURL( aURL );
+ rURLBox.set_entry_text( aPath );
+ }
+ else
+ {
+ rURLBox.SetBaseURL( sInstPath );
+ rURLBox.set_entry_text( "" );
+ }
+}
+
+OUString XMLFilterTabPageXSLT::GetURL(const SvtURLBox& rURLBox)
+{
+ OUString aURL;
+ OUString aStrPath(rURLBox.get_active_text());
+ if( aStrPath.matchIgnoreAsciiCase( "http://" ) ||
+ aStrPath.matchIgnoreAsciiCase( "https://" ) ||
+ aStrPath.matchIgnoreAsciiCase( "ftp://" ) )
+ {
+ return aStrPath;
+ }
+ else
+ {
+ osl::FileBase::getFileURLFromSystemPath( aStrPath, aURL );
+ }
+
+ return aURL;
+}
+
+IMPL_LINK ( XMLFilterTabPageXSLT, ClickBrowseHdl_Impl, weld::Button&, rButton, void )
+{
+ SvtURLBox* pURLBox;
+
+ if( &rButton == m_xPBExprotXSLT.get() )
+ {
+ pURLBox = m_xEDExportXSLT.get();
+ }
+ else if( &rButton == m_xPBImportXSLT.get() )
+ {
+ pURLBox = m_xEDImportXSLT.get();
+ }
+ else
+ {
+ pURLBox = m_xEDImportTemplate.get();
+ }
+
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_pDialog);
+
+ aDlg.SetDisplayDirectory(GetURL(*pURLBox));
+
+ if (aDlg.Execute() == ERRCODE_NONE)
+ {
+ OUString aURL(aDlg.GetPath());
+ SetURL(*pURLBox, aURL);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx b/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx
new file mode 100644
index 000000000..52538a834
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx
@@ -0,0 +1,56 @@
+/* -*- 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 <vcl/weld.hxx>
+#include <svtools/inettbc.hxx>
+
+class filter_info_impl;
+
+class XMLFilterTabPageXSLT
+{
+private:
+ void SetURL(SvtURLBox& rURLBox, const OUString& rURL);
+ static OUString GetURL(const SvtURLBox& rURLBox);
+
+ OUString sInstPath;
+
+public:
+ explicit XMLFilterTabPageXSLT(weld::Widget* pPage, weld::Dialog* pDialog);
+ ~XMLFilterTabPageXSLT();
+
+ void FillInfo( filter_info_impl* pInfo );
+ void SetInfo(const filter_info_impl* pInfo);
+
+ DECL_LINK( ClickBrowseHdl_Impl, weld::Button&, void );
+
+ weld::Dialog* m_pDialog;
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Widget> m_xContainer;
+ std::unique_ptr<weld::Entry> m_xEDDocType;
+ std::unique_ptr<SvtURLBox> m_xEDExportXSLT;
+ std::unique_ptr<weld::Button> m_xPBExprotXSLT;
+ std::unique_ptr<SvtURLBox> m_xEDImportXSLT;
+ std::unique_ptr<weld::Button> m_xPBImportXSLT;
+ std::unique_ptr<SvtURLBox> m_xEDImportTemplate;
+ std::unique_ptr<weld::Button> m_xPBImportTemplate;
+ std::unique_ptr<weld::CheckButton> m_xCBNeedsXSLT2;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertestdialog.cxx b/filter/source/xsltdialog/xmlfiltertestdialog.cxx
new file mode 100644
index 000000000..ca38ab547
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertestdialog.cxx
@@ -0,0 +1,697 @@
+/* -*- 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/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XGraphicStorageHandler.hpp>
+#include <com/sun/star/document/XEmbeddedObjectResolver.hpp>
+#include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/system/SystemShellExecute.hpp>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/xml/XImportFilter.hpp>
+#include <com/sun/star/xml/XExportFilter.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+
+#include <comphelper/oslfile2streamwrap.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <osl/file.hxx>
+#include <unotools/tempfile.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/debug.hxx>
+#include <tools/urlobj.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include "xmlfiltercommon.hxx"
+#include "xmlfiltertestdialog.hxx"
+
+
+using namespace utl;
+using namespace osl;
+using namespace comphelper;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+using namespace com::sun::star::document;
+using namespace com::sun::star::frame;
+using namespace com::sun::star::task;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace com::sun::star::system;
+using namespace com::sun::star::xml;
+using namespace com::sun::star::xml::sax;
+
+namespace {
+
+class GlobalEventListenerImpl : public ::cppu::WeakImplHelper< css::document::XDocumentEventListener >
+{
+public:
+ explicit GlobalEventListenerImpl( XMLFilterTestDialog* pDialog );
+
+ // XDocumentEventListener
+ virtual void SAL_CALL documentEventOccured( const css::document::DocumentEvent& Event ) override;
+
+ // lang::XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+private:
+ XMLFilterTestDialog* mpDialog;
+};
+
+}
+
+GlobalEventListenerImpl::GlobalEventListenerImpl( XMLFilterTestDialog* pDialog )
+: mpDialog( pDialog )
+{
+}
+
+void SAL_CALL GlobalEventListenerImpl::documentEventOccured( const css::document::DocumentEvent& Event )
+{
+ ::SolarMutexGuard aGuard;
+ if( Event.EventName == "OnFocus" || Event.EventName == "OnUnload" )
+ {
+ Reference< XComponent > xComp( Event.Source, UNO_QUERY );
+ mpDialog->updateCurrentDocumentButtonState( &xComp );
+ }
+}
+
+void SAL_CALL GlobalEventListenerImpl::disposing( const css::lang::EventObject& /* Source */ )
+{
+}
+
+/** returns true if the given component supports the given service */
+static bool checkComponent( Reference< XComponent > const & rxComponent, const OUString& rServiceName )
+{
+ try
+ {
+ Reference< XServiceInfo > xInfo( rxComponent, UNO_QUERY );
+ if( xInfo.is() )
+ {
+ if( xInfo->supportsService( rServiceName ) )
+ {
+ // special case for impress documents which supports same service as draw documents
+ if ( rServiceName == "com.sun.star.drawing.DrawingDocument" )
+ {
+ // so if we want a draw we need to check if it's not an impress
+ if( !xInfo->supportsService("com.sun.star.presentation.PresentationDocument") )
+ return true;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ return false;
+}
+
+XMLFilterTestDialog::XMLFilterTestDialog(weld::Window* pParent,
+ const Reference<XComponentContext>& rxContext)
+ : GenericDialogController(pParent, "filter/ui/testxmlfilter.ui", "TestXMLFilterDialog")
+ , mxContext(rxContext)
+ , m_xExport(m_xBuilder->weld_widget("export"))
+ , m_xFTExportXSLTFile(m_xBuilder->weld_label("exportxsltfile"))
+ , m_xPBExportBrowse(m_xBuilder->weld_button("exportbrowse"))
+ , m_xPBCurrentDocument(m_xBuilder->weld_button("currentdocument"))
+ , m_xFTNameOfCurrentFile(m_xBuilder->weld_label("currentfilename"))
+ , m_xImport(m_xBuilder->weld_widget("import"))
+ , m_xFTImportXSLTFile(m_xBuilder->weld_label("importxsltfile"))
+ , m_xFTImportTemplate(m_xBuilder->weld_label("templateimport"))
+ , m_xFTImportTemplateFile(m_xBuilder->weld_label("importxslttemplate"))
+ , m_xCBXDisplaySource(m_xBuilder->weld_check_button("displaysource"))
+ , m_xPBImportBrowse(m_xBuilder->weld_button("importbrowse"))
+ , m_xPBRecentFile(m_xBuilder->weld_button("recentfile"))
+ , m_xFTNameOfRecentFile(m_xBuilder->weld_label("recentfilename"))
+ , m_xPBClose(m_xBuilder->weld_button("close"))
+{
+ m_xPBExportBrowse->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+ m_xPBCurrentDocument->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+ m_xPBImportBrowse->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+ m_xPBRecentFile->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+ m_xPBClose->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+
+ m_sDialogTitle = m_xDialog->get_title();
+
+ try
+ {
+ mxGlobalBroadcaster = theGlobalEventBroadcaster::get(mxContext);
+ mxGlobalEventListener = new GlobalEventListenerImpl( this );
+ mxGlobalBroadcaster->addDocumentEventListener( mxGlobalEventListener );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+XMLFilterTestDialog::~XMLFilterTestDialog()
+{
+ try
+ {
+ if( mxGlobalBroadcaster.is() )
+ mxGlobalBroadcaster->removeDocumentEventListener( mxGlobalEventListener );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void XMLFilterTestDialog::test( const filter_info_impl& rFilterInfo )
+{
+ m_xFilterInfo.reset(new filter_info_impl( rFilterInfo ));
+
+ m_sImportRecentFile.clear();
+
+ initDialog();
+
+ m_xDialog->run();
+}
+
+static OUString getFileNameFromURL( std::u16string_view rURL )
+{
+ INetURLObject aURL( rURL );
+ OUString aName( aURL.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset) );
+ return aName;
+}
+
+void XMLFilterTestDialog::updateCurrentDocumentButtonState( Reference< XComponent > const * pRef /* = NULL */ )
+{
+ if( pRef && pRef->is() )
+ {
+ if( checkComponent( *pRef, m_xFilterInfo->maDocumentService ) )
+ mxLastFocusModel = *pRef;
+ }
+
+ bool bExport = (m_xFilterInfo->maFlags & 2) == 2;
+ Reference< XComponent > xCurrentDocument;
+ if( bExport )
+ xCurrentDocument = getFrontMostDocument( m_xFilterInfo->maDocumentService );
+ m_xPBCurrentDocument->set_sensitive( bExport && xCurrentDocument.is() );
+ m_xFTNameOfCurrentFile->set_sensitive( bExport && xCurrentDocument.is() );
+
+ if( !xCurrentDocument.is() )
+ return;
+
+ OUString aTitle;
+ Reference< XDocumentPropertiesSupplier > xDPS( xCurrentDocument, UNO_QUERY );
+ if( xDPS.is() )
+ {
+ Reference< XDocumentProperties > xProps( xDPS->getDocumentProperties() );
+ if( xProps.is() )
+ {
+ aTitle = xProps->getTitle();
+ }
+ }
+
+ if( aTitle.isEmpty() )
+ {
+ Reference< XStorable > xStorable( xCurrentDocument, UNO_QUERY );
+ if( xStorable.is() )
+ {
+ if( xStorable->hasLocation() )
+ {
+ OUString aURL( xStorable->getLocation() );
+ aTitle = getFileNameFromURL( aURL );
+ }
+ }
+ }
+
+ m_xFTNameOfCurrentFile->set_label( aTitle );
+}
+
+void XMLFilterTestDialog::initDialog()
+{
+ DBG_ASSERT( m_xFilterInfo, "i need a filter I can test!" );
+ if( nullptr == m_xFilterInfo )
+ return;
+
+ OUString aTitle( m_sDialogTitle );
+ aTitle = aTitle.replaceFirst( "%s", m_xFilterInfo->maFilterName );
+ m_xDialog->set_title( aTitle );
+
+ bool bImport = (m_xFilterInfo->maFlags & 1) == 1;
+ bool bExport = (m_xFilterInfo->maFlags & 2) == 2;
+
+ updateCurrentDocumentButtonState();
+
+ m_xExport->set_sensitive(bExport);
+ m_xFTExportXSLTFile->set_label( getFileNameFromURL( m_xFilterInfo->maExportXSLT ) );
+
+
+ m_xImport->set_sensitive(bImport);
+ m_xFTImportTemplate->set_sensitive(bImport && !m_xFilterInfo->maImportTemplate.isEmpty());
+ m_xFTImportTemplateFile->set_sensitive(bImport && !m_xFilterInfo->maImportTemplate.isEmpty());
+ m_xPBRecentFile->set_sensitive(bImport && !m_sImportRecentFile.isEmpty());
+ m_xFTNameOfRecentFile->set_sensitive(bImport && !m_sImportRecentFile.isEmpty());
+
+ m_xFTImportXSLTFile->set_label( getFileNameFromURL( m_xFilterInfo->maImportXSLT ) );
+ m_xFTImportTemplateFile->set_label( getFileNameFromURL( m_xFilterInfo->maImportTemplate ) );
+ m_xFTNameOfRecentFile->set_label( getFileNameFromURL( m_sImportRecentFile ) );
+}
+
+void XMLFilterTestDialog::onExportBrowse()
+{
+ try
+ {
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_xDialog.get());
+
+ Reference< XNameAccess > xFilterContainer( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", mxContext ), UNO_QUERY );
+ Reference< XNameAccess > xTypeDetection( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", mxContext ), UNO_QUERY );
+ if( xFilterContainer.is() && xTypeDetection.is() )
+ {
+ const Sequence< OUString > aFilterNames( xFilterContainer->getElementNames() );
+
+ for( OUString const & filterName : aFilterNames )
+ {
+ Sequence< PropertyValue > aValues;
+
+ Any aAny( xFilterContainer->getByName( filterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ OUString aInterfaceName;
+ OUString aType, aService;
+ sal_Int32 nFlags( 0 );
+
+ int nFound = 0;
+
+ for( const PropertyValue& rValue : std::as_const(aValues) )
+ {
+ if ( rValue.Name == "Type" )
+ {
+ rValue.Value >>= aType;
+ nFound |= 1;
+ }
+ else if ( rValue.Name == "DocumentService" )
+ {
+ rValue.Value >>= aService;
+ nFound |= 2;
+ }
+ else if ( rValue.Name == "Flags" )
+ {
+ rValue.Value >>= nFlags;
+ nFound |= 4;
+ }
+ else if ( rValue.Name == "UIName" )
+ {
+ rValue.Value >>= aInterfaceName;
+ nFound |= 8;
+ }
+
+ if (nFound == 15)
+ break;
+ }
+
+ if( (nFound == 15) && (!aType.isEmpty() && aService == m_xFilterInfo->maDocumentService) )
+ {
+ // see if this filter is not suppressed in dialog
+ if( (nFlags & 0x1000) == 0 )
+ {
+ aAny = xTypeDetection->getByName( aType );
+ Sequence< PropertyValue > aValues2;
+
+ if( aAny >>= aValues2 )
+ {
+ OUString aExtension;
+ for( const PropertyValue& rProp : std::as_const(aValues2) )
+ {
+ if ( rProp.Name == "Extensions" )
+ {
+ Sequence< OUString > aExtensions;
+ if( rProp.Value >>= aExtensions )
+ {
+ const sal_Int32 nCount( aExtensions.getLength() );
+ OUString* pExtensions = aExtensions.getArray();
+ sal_Int32 n;
+ for( n = 0; n < nCount; n++ )
+ {
+ if( n > 0 )
+ aExtension += ";";
+ aExtension += "*." + *pExtensions++;
+ }
+ }
+ }
+ }
+
+ OUString aFilterName( aInterfaceName + " (" + aExtension + ")" );
+
+ aDlg.AddFilter( aFilterName, aExtension );
+
+ if( (nFlags & 0x100) == 0x100 )
+ aDlg.SetCurrentFilter( aFilterName );
+ }
+ }
+ }
+
+ }
+ }
+
+ aDlg.SetDisplayDirectory( m_sExportRecentFile );
+
+ if ( aDlg.Execute() == ERRCODE_NONE )
+ {
+ m_sExportRecentFile = aDlg.GetPath();
+
+ Reference< XDesktop2 > xLoader = Desktop::create( mxContext );
+ Reference< XInteractionHandler2 > xInter = InteractionHandler::createWithParent(mxContext, nullptr);
+ Sequence< PropertyValue > aArguments{ comphelper::makePropertyValue("InteractionHandler",
+ xInter) };
+ Reference< XComponent > xComp( xLoader->loadComponentFromURL( m_sExportRecentFile, "_default", 0, aArguments ) );
+ if( xComp.is() )
+ {
+ doExport( xComp );
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ initDialog();
+}
+
+void XMLFilterTestDialog::onExportCurrentDocument()
+{
+ doExport( getFrontMostDocument( m_xFilterInfo->maDocumentService ) );
+}
+
+void XMLFilterTestDialog::doExport( const Reference< XComponent >& xComp )
+{
+ try
+ {
+ Reference< XStorable > xStorable( xComp, UNO_QUERY );
+ if( xStorable.is() )
+ {
+ OUString const ext(".xml");
+ utl::TempFile aTempFile(u"", true, &ext);
+ OUString aTempFileURL( aTempFile.GetURL() );
+
+ const application_info_impl* pAppInfo = getApplicationInfo( m_xFilterInfo->maExportService );
+ if( pAppInfo )
+ {
+ File aOutputFile( aTempFileURL );
+ (void)aOutputFile.open( osl_File_OpenFlag_Write );
+
+ // create xslt exporter
+ Reference< XOutputStream > xIS( new comphelper::OSLOutputStreamWrapper( aOutputFile ) );
+ int bUseDocType = m_xFilterInfo->maDocType.isEmpty() ? 0 : 1;
+ Sequence< PropertyValue > aSourceData( 2 + bUseDocType );
+ auto pSourceData = aSourceData.getArray();
+ int i = 0;
+
+
+ pSourceData[i ].Name = "OutputStream";
+ pSourceData[i++].Value <<= xIS;
+
+ pSourceData[i].Name = "Indent";
+ pSourceData[i++].Value <<= true;
+
+ if( bUseDocType )
+ {
+ pSourceData[i ].Name = "DocType_Public";
+ pSourceData[i++].Value <<= m_xFilterInfo->maDocType;
+ }
+
+ Reference< XExportFilter > xExporter( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.documentconversion.XSLTFilter", mxContext ), UNO_QUERY );
+ Reference< XDocumentHandler > xHandler( xExporter, UNO_QUERY );
+ if( xHandler.is() )
+ {
+ Sequence< OUString > aFilterUserData( m_xFilterInfo->getFilterUserData() );
+ xExporter->exporter( aSourceData, aFilterUserData );
+
+ Reference< XMultiServiceFactory > xDocFac( xComp, UNO_QUERY );
+
+ Reference< XEmbeddedObjectResolver > xObjectResolver;
+ Reference<XGraphicStorageHandler> xGraphicStorageHandler;
+
+ if( xDocFac.is() )
+ {
+ try
+ {
+ xGraphicStorageHandler.set(xDocFac->createInstance("com.sun.star.document.ExportGraphicStorageHandler"), UNO_QUERY);
+ xObjectResolver.set( xDocFac->createInstance("com.sun.star.document.ExportEmbeddedObjectResolver"), UNO_QUERY );
+ }
+ catch( const Exception& )
+ {
+ }
+ }
+
+ Sequence< Any > aArgs( 1 + ( xGraphicStorageHandler.is() ? 1 : 0 ) + ( xObjectResolver.is() ? 1 : 0 ) );
+ Any* pArgs = aArgs.getArray();
+ if (xGraphicStorageHandler.is())
+ *pArgs++ <<= xGraphicStorageHandler;
+
+ if (xObjectResolver.is())
+ *pArgs++ <<= xObjectResolver;
+
+ // *pArgs++ <<= xInfoSet;
+ *pArgs <<= xHandler;
+
+ Reference< XFilter > xFilter( mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( pAppInfo->maXMLExporter, aArgs, mxContext ), UNO_QUERY );
+ if( xFilter.is() )
+ {
+ Reference< XExporter > xExporter2( xFilter, UNO_QUERY );
+ if( xExporter2.is() )
+ {
+ xExporter2->setSourceDocument( xComp );
+
+ Sequence< PropertyValue > aDescriptor{comphelper::makePropertyValue(
+ "FileName", aTempFileURL) };
+
+ if( xFilter->filter( aDescriptor ) )
+ displayXMLFile( aTempFileURL );
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void XMLFilterTestDialog::displayXMLFile( const OUString& rURL )
+{
+ Reference< XSystemShellExecute > xSystemShellExecute(
+ SystemShellExecute::create(comphelper::getProcessComponentContext()) );
+ xSystemShellExecute->execute( rURL, OUString(), SystemShellExecuteFlags::URIS_ONLY );
+}
+
+void XMLFilterTestDialog::onImportBrowse()
+{
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_xDialog.get());
+ OUString aFilterName( m_xFilterInfo->maInterfaceName );
+ OUString aExtensions;
+
+ int nLastIndex = 0;
+ int nCurrentIndex = 0;
+ for( int i = 0; nLastIndex != -1; i++ )
+ {
+ nLastIndex = m_xFilterInfo->maExtension.indexOf( ';', nLastIndex );
+
+ if( i > 0 )
+ aExtensions += ";";
+
+ aExtensions += "*.";
+
+ if( nLastIndex == -1 )
+ {
+
+ aExtensions += m_xFilterInfo->maExtension.subView( nCurrentIndex );
+ }
+ else
+ {
+ aExtensions += m_xFilterInfo->maExtension.subView( nCurrentIndex, nLastIndex - nCurrentIndex );
+ nCurrentIndex = nLastIndex + 1;
+ nLastIndex = nCurrentIndex;
+ }
+ }
+
+ aFilterName += " (" + aExtensions + ")";
+
+ aDlg.AddFilter( aFilterName, aExtensions );
+ aDlg.SetDisplayDirectory( m_sImportRecentFile );
+
+ if ( aDlg.Execute() == ERRCODE_NONE )
+ {
+ m_sImportRecentFile = aDlg.GetPath();
+ import( m_sImportRecentFile );
+ }
+
+ initDialog();
+}
+
+void XMLFilterTestDialog::import( const OUString& rURL )
+{
+ try
+ {
+ Reference< XDesktop2 > xLoader = Desktop::create( mxContext );
+ Reference< XInteractionHandler2 > xInter = InteractionHandler::createWithParent(mxContext, nullptr);
+
+ Sequence< PropertyValue > aArguments{
+ comphelper::makePropertyValue("FilterName", m_xFilterInfo->maFilterName),
+ comphelper::makePropertyValue("InteractionHandler", xInter)
+ };
+
+ xLoader->loadComponentFromURL( rURL, "_default", 0, aArguments );
+
+ if( m_xCBXDisplaySource->get_active() )
+ {
+ OUString const ext(".xml");
+ TempFile aTempFile(u"", true, &ext);
+ OUString aTempFileURL( aTempFile.GetURL() );
+
+ Reference< XImportFilter > xImporter( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.documentconversion.XSLTFilter", mxContext ), UNO_QUERY );
+ if( xImporter.is() )
+ {
+ osl::File aInputFile( rURL );
+ (void)aInputFile.open( osl_File_OpenFlag_Read );
+
+ Reference< XInputStream > xIS( new comphelper::OSLInputStreamWrapper( aInputFile ) );
+
+ Sequence< PropertyValue > aSourceData{
+ comphelper::makePropertyValue("InputStream", xIS),
+ comphelper::makePropertyValue("FileName", rURL),
+ comphelper::makePropertyValue("Indent", true)
+ };
+
+ Reference< XWriter > xWriter = Writer::create( mxContext );
+
+ File aOutputFile( aTempFileURL );
+ (void)aOutputFile.open( osl_File_OpenFlag_Write );
+
+ Reference< XOutputStream > xOS( new OSLOutputStreamWrapper( aOutputFile ) );
+ xWriter->setOutputStream( xOS );
+
+ Sequence< OUString > aFilterUserData( m_xFilterInfo->getFilterUserData() );
+ xImporter->importer( aSourceData, xWriter, aFilterUserData );
+ }
+
+ displayXMLFile( aTempFileURL );
+ }
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+IMPL_LINK(XMLFilterTestDialog, ClickHdl_Impl, weld::Button&, rButton, void )
+{
+ if (m_xPBExportBrowse.get() == &rButton)
+ {
+ onExportBrowse();
+ }
+ else if (m_xPBCurrentDocument.get() == &rButton)
+ {
+ onExportCurrentDocument();
+ }
+ else if (m_xPBImportBrowse.get() == &rButton)
+ {
+ onImportBrowse();
+ }
+ else if (m_xPBRecentFile.get() == &rButton)
+ {
+ import( m_sImportRecentFile );
+ }
+ else if (m_xPBClose.get() == &rButton)
+ {
+ m_xDialog->response(RET_CLOSE);
+ }
+}
+
+/** returns the front most open component that supports the given service */
+Reference< XComponent > XMLFilterTestDialog::getFrontMostDocument( const OUString& rServiceName )
+{
+ Reference< XComponent > xRet;
+
+ try
+ {
+ Reference< XDesktop2 > xDesktop = Desktop::create( mxContext );
+ Reference< XComponent > xTest( mxLastFocusModel );
+ if( checkComponent( xTest, rServiceName ) )
+ {
+ xRet = xTest;
+ }
+ else
+ {
+ xTest = xDesktop->getCurrentComponent();
+
+ if( checkComponent( xTest, rServiceName ) )
+ {
+ xRet = xTest;
+ }
+ else
+ {
+ Reference< XEnumerationAccess > xAccess( xDesktop->getComponents() );
+ if( xAccess.is() )
+ {
+ Reference< XEnumeration > xEnum( xAccess->createEnumeration() );
+ if( xEnum.is() )
+ {
+ while( xEnum->hasMoreElements() )
+ {
+ if( (xEnum->nextElement() >>= xTest) && xTest.is() )
+ {
+ if( checkComponent( xTest, rServiceName ) )
+ {
+ xRet = xTest;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ return xRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertestdialog.hxx b/filter/source/xsltdialog/xmlfiltertestdialog.hxx
new file mode 100644
index 000000000..bce1e19e1
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertestdialog.hxx
@@ -0,0 +1,81 @@
+/* -*- 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/lang/XComponent.hpp>
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <cppuhelper/weakref.hxx>
+#include <vcl/weld.hxx>
+
+class filter_info_impl;
+
+class XMLFilterTestDialog : public weld::GenericDialogController
+{
+public:
+ XMLFilterTestDialog(weld::Window* pParent,
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+ virtual ~XMLFilterTestDialog() override;
+
+ void test( const filter_info_impl& rFilterInfo );
+
+ void updateCurrentDocumentButtonState( css::uno::Reference< css::lang::XComponent > const * pRef = nullptr );
+
+private:
+ DECL_LINK(ClickHdl_Impl, weld::Button&, void);
+
+ void onExportBrowse();
+ void onExportCurrentDocument();
+ void onImportBrowse();
+ void initDialog();
+
+ css::uno::Reference< css::lang::XComponent > getFrontMostDocument( const OUString& rServiceName );
+ void import( const OUString& rURL );
+ static void displayXMLFile( const OUString& rURL );
+ void doExport( const css::uno::Reference< css::lang::XComponent >& xComp );
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::document::XDocumentEventBroadcaster > mxGlobalBroadcaster;
+ css::uno::Reference< css::document::XDocumentEventListener > mxGlobalEventListener;
+ css::uno::WeakReference< css::lang::XComponent > mxLastFocusModel;
+
+ OUString m_sImportRecentFile;
+ OUString m_sExportRecentFile;
+ std::unique_ptr<filter_info_impl> m_xFilterInfo;
+ OUString m_sDialogTitle;
+
+ std::unique_ptr<weld::Widget> m_xExport;
+ std::unique_ptr<weld::Label> m_xFTExportXSLTFile;
+ std::unique_ptr<weld::Button> m_xPBExportBrowse;
+ std::unique_ptr<weld::Button> m_xPBCurrentDocument;
+ std::unique_ptr<weld::Label> m_xFTNameOfCurrentFile;
+ std::unique_ptr<weld::Widget> m_xImport;
+ std::unique_ptr<weld::Label> m_xFTImportXSLTFile;
+ std::unique_ptr<weld::Label> m_xFTImportTemplate;
+ std::unique_ptr<weld::Label> m_xFTImportTemplateFile;
+ std::unique_ptr<weld::CheckButton> m_xCBXDisplaySource;
+ std::unique_ptr<weld::Button> m_xPBImportBrowse;
+ std::unique_ptr<weld::Button> m_xPBRecentFile;
+ std::unique_ptr<weld::Label> m_xFTNameOfRecentFile;
+ std::unique_ptr<weld::Button> m_xPBClose;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xsltdlg.component b/filter/source/xsltdialog/xsltdlg.component
new file mode 100644
index 000000000..6d4a693f3
--- /dev/null
+++ b/filter/source/xsltdialog/xsltdlg.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.ui.XSLTFilterDialog"
+ constructor="filter_XSLTFilterDialog_get_implementation">
+ <service name="com.sun.star.ui.dialogs.XSLTFilterDialog"/>
+ </implementation>
+</component>