From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- dbaccess/source/filter/xml/xmlfilter.cxx | 617 +++++++++++++++++++++++++++++++ 1 file changed, 617 insertions(+) create mode 100644 dbaccess/source/filter/xml/xmlfilter.cxx (limited to 'dbaccess/source/filter/xml/xmlfilter.cxx') diff --git a/dbaccess/source/filter/xml/xmlfilter.cxx b/dbaccess/source/filter/xml/xmlfilter.cxx new file mode 100644 index 000000000..d089359c8 --- /dev/null +++ b/dbaccess/source/filter/xml/xmlfilter.cxx @@ -0,0 +1,617 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xmlfilter.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xmlDatabase.hxx" +#include "xmlEnums.hxx" +#include +#include +#include "xmlStyleImport.hxx" +#include +#include "xmlHelper.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_sdb_DBFilter_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence const&) +{ + return cppu::acquire(new ::dbaxml::ODBFilter(context)); +} + + +namespace dbaxml +{ + using namespace ::com::sun::star::util; + /// read a component (file + filter version) +static ErrCode ReadThroughComponent( + const uno::Reference& xInputStream, + const uno::Reference& xModelComponent, + const uno::Reference & rxContext, + ODBFilter& _rFilter ) +{ + OSL_ENSURE(xInputStream.is(), "input stream missing"); + OSL_ENSURE(xModelComponent.is(), "document missing"); + OSL_ENSURE(rxContext.is(), "factory missing"); + + // prepare ParserInputSource + InputSource aParserInput; + aParserInput.aInputStream = xInputStream; + + // connect model and filter + _rFilter.setTargetDocument( xModelComponent ); + + // finally, parser the stream + try + { + _rFilter.parseStream( aParserInput ); + } + catch (const SAXParseException&) + { +#if OSL_DEBUG_LEVEL > 0 + TOOLS_WARN_EXCEPTION("dbaccess", "SAX parse exception caught while importing"); +#endif + return ErrCode(1); + } + catch (const SAXException&) + { + return ErrCode(1); + } + catch (const packages::zip::ZipIOException&) + { + return ERRCODE_IO_BROKENPACKAGE; + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + // success! + return ERRCODE_NONE; +} + + +/// read a component (storage version) +static ErrCode ReadThroughComponent( + const uno::Reference< embed::XStorage >& xStorage, + const uno::Reference& xModelComponent, + const char* pStreamName, + const uno::Reference & rxContext, + ODBFilter& _rFilter) +{ + OSL_ENSURE( xStorage.is(), "Need storage!"); + OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!"); + + if ( !xStorage ) + // TODO/LATER: better error handling + return ErrCode(1); + + uno::Reference< io::XStream > xDocStream; + + try + { + // open stream (and set parser input) + OUString sStreamName = OUString::createFromAscii(pStreamName); + if ( !xStorage->hasByName( sStreamName ) || !xStorage->isStreamElement( sStreamName ) ) + { + // stream name not found! return immediately with OK signal + return ERRCODE_NONE; + } + + // get input stream + xDocStream = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ ); + } + catch (const packages::WrongPasswordException&) + { + return ERRCODE_SFX_WRONGPASSWORD; + } + catch (const uno::Exception&) + { + return ErrCode(1); // TODO/LATER: error handling + } + + uno::Reference< XInputStream > xInputStream = xDocStream->getInputStream(); + // read from the stream + return ReadThroughComponent( xInputStream + ,xModelComponent + ,rxContext + ,_rFilter ); +} + + +ODBFilter::ODBFilter( const uno::Reference< XComponentContext >& _rxContext ) + : SvXMLImport(_rxContext, getImplementationName_Static()) + , m_bNewFormat(false) +{ + + GetMM100UnitConverter().SetCoreMeasureUnit(util::MeasureUnit::MM_10TH); + GetMM100UnitConverter().SetXMLMeasureUnit(util::MeasureUnit::CM); + GetNamespaceMap().Add( "_db", + GetXMLToken(XML_N_DB), + XML_NAMESPACE_DB ); + + GetNamespaceMap().Add( "__db", + GetXMLToken(XML_N_DB_OASIS), + XML_NAMESPACE_DB ); +} + + +ODBFilter::~ODBFilter() noexcept +{ + +} + + +OUString ODBFilter::getImplementationName_Static() +{ + return "com.sun.star.comp.sdb.DBFilter"; +} + + +namespace { +class FocusWindowWaitGuard +{ +public: + FocusWindowWaitGuard() + { + SolarMutexGuard aGuard; + mpWindow.set(Application::GetFocusWindow()); + if (mpWindow) + mpWindow->EnterWait(); + } + ~FocusWindowWaitGuard() + { + if (mpWindow) + { + SolarMutexGuard aGuard; + mpWindow->LeaveWait(); + } + } +private: + VclPtr mpWindow; +}; +} + +sal_Bool SAL_CALL ODBFilter::filter( const Sequence< PropertyValue >& rDescriptor ) +{ + FocusWindowWaitGuard aWindowFocusGuard; + bool bRet = false; + + if ( GetModel().is() ) + bRet = implImport( rDescriptor ); + + return bRet; +} + + +bool ODBFilter::implImport( const Sequence< PropertyValue >& rDescriptor ) +{ + OUString sFileName; + ::comphelper::NamedValueCollection aMediaDescriptor( rDescriptor ); + + uno::Reference xStorage = GetSourceStorage(); + + bool bRet = true; + if (!xStorage.is()) + { + if (aMediaDescriptor.has("URL")) + sFileName = aMediaDescriptor.getOrDefault("URL", OUString()); + if (sFileName.isEmpty() && aMediaDescriptor.has("FileName")) + sFileName = aMediaDescriptor.getOrDefault("FileName", sFileName); + + OSL_ENSURE(!sFileName.isEmpty(), "ODBFilter::implImport: no URL given!"); + bRet = !sFileName.isEmpty(); + } + + if ( bRet ) + { + + tools::SvRef pMedium; + if (!xStorage.is()) + { + OUString sStreamRelPath; + if (sFileName.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:")) + { + // In this case the authority contains the real path, and the path is the embedded stream name. + auto const uri = css::uri::UriReferenceFactory::create(GetComponentContext()) + ->parse(sFileName); + if (uri.is() && uri->isAbsolute() + && uri->hasAuthority() && !uri->hasQuery() && !uri->hasFragment()) + { + auto const auth = uri->getAuthority(); + auto const decAuth = rtl::Uri::decode( + auth, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8); + auto path = uri->getPath(); + if (!path.isEmpty()) { + assert(path[0] == '/'); + path = path.copy(1); + } + auto const decPath = rtl::Uri::decode( + path, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8); + //TODO: really decode path? + if (auth.isEmpty() == decAuth.isEmpty() && path.isEmpty() == decPath.isEmpty()) + { + // Decoding of auth and path to UTF-8 succeeded: + sFileName = decAuth; + sStreamRelPath = decPath; + } else { + SAL_WARN( + "dbaccess", + "<" << sFileName << "> cannot be parse as vnd.sun.star.pkg URL"); + } + } else { + SAL_WARN( + "dbaccess", + "<" << sFileName << "> cannot be parse as vnd.sun.star.pkg URL"); + } + } + + pMedium = new SfxMedium(sFileName, (StreamMode::READ | StreamMode::NOCREATE)); + try + { + xStorage.set(pMedium->GetStorage(false), UNO_SET_THROW); + + if (!sStreamRelPath.isEmpty()) + xStorage = xStorage->openStorageElement(sStreamRelPath, embed::ElementModes::READ); + } + catch (const RuntimeException&) + { + throw; + } + catch (const Exception&) + { + Any aError = ::cppu::getCaughtException(); + throw lang::WrappedTargetRuntimeException(OUString(), *this, aError); + } + } + + uno::Reference xOfficeDoc(GetModel(),UNO_QUERY_THROW); + m_xDataSource.set(xOfficeDoc->getDataSource(),UNO_QUERY_THROW); + uno::Reference< XNumberFormatsSupplier > xNum(m_xDataSource->getPropertyValue(PROPERTY_NUMBERFORMATSSUPPLIER),UNO_QUERY); + SetNumberFormatsSupplier(xNum); + + uno::Reference xModel(GetModel()); + ErrCode nRet = ReadThroughComponent( xStorage + ,xModel + ,"settings.xml" + ,GetComponentContext() + ,*this + ); + + if ( nRet == ERRCODE_NONE ) + nRet = ReadThroughComponent( xStorage + ,xModel + ,"content.xml" + ,GetComponentContext() + ,*this + ); + + bRet = nRet == ERRCODE_NONE; + + if ( bRet ) + { + uno::Reference< XModifiable > xModi(GetModel(),UNO_QUERY); + if ( xModi.is() ) + xModi->setModified(false); + } + else + { + if ( nRet == ERRCODE_IO_BROKENPACKAGE ) + ;// TODO/LATER: no way to transport the error outside from the filter! + else + { + // TODO/LATER: this is completely wrong! Filter code should never call ErrorHandler directly! But for now this is the only way! + ErrorHandler::HandleError( nRet ); + if( nRet.IsWarning() ) + bRet = true; + } + } + } + + return bRet; +} + +namespace { + +class DBXMLDocumentSettingsContext : public SvXMLImportContext +{ +public: + DBXMLDocumentSettingsContext(SvXMLImport & rImport) + : SvXMLImportContext(rImport) + { + } + + virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override + { + if (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS)) + { + return new XMLDocumentSettingsContext(GetImport()); + } + return nullptr; + } +}; + +class DBXMLDocumentStylesContext : public SvXMLImportContext +{ +public: + DBXMLDocumentStylesContext(SvXMLImport & rImport) + : SvXMLImportContext(rImport) + { + } + + virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override + { + ODBFilter & rImport(static_cast(GetImport())); + switch (nElement) + { + case XML_ELEMENT(OFFICE, XML_STYLES): + case XML_ELEMENT(OOO, XML_STYLES): + rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); + return rImport.CreateStylesContext(false); + case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES): + case XML_ELEMENT(OOO, XML_AUTOMATIC_STYLES): + rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); + return rImport.CreateStylesContext(true); + } + return nullptr; + } +}; + +class DBXMLDocumentBodyContext : public SvXMLImportContext +{ +public: + DBXMLDocumentBodyContext(SvXMLImport & rImport) + : SvXMLImportContext(rImport) + { + } + + virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override + { + ODBFilter & rImport(static_cast(GetImport())); + switch (nElement) + { + case XML_ELEMENT(OFFICE, XML_DATABASE): + case XML_ELEMENT(OOO, XML_DATABASE): + rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); + return new OXMLDatabase(rImport); + default: break; + } + return nullptr; + } +}; + +class DBXMLDocumentContentContext : public SvXMLImportContext +{ +public: + DBXMLDocumentContentContext(SvXMLImport & rImport) + : SvXMLImportContext(rImport) + { + } + + virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override + { + ODBFilter & rImport(static_cast(GetImport())); + switch (nElement) + { + case XML_ELEMENT(OFFICE, XML_BODY): + case XML_ELEMENT(OOO, XML_BODY): + return new DBXMLDocumentBodyContext(rImport); + case XML_ELEMENT(OFFICE, XML_SCRIPTS): + return new XMLScriptContext(GetImport(), rImport.GetModel()); + case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES): + case XML_ELEMENT(OOO, XML_AUTOMATIC_STYLES): + rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); + return rImport.CreateStylesContext(true); + default: break; + } + return nullptr; + } +}; + +} + +SvXMLImportContext* ODBFilter::CreateFastContext(sal_Int32 nElement, + const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& /*xAttrList*/ ) +{ + SvXMLImportContext *pContext = nullptr; + + switch( nElement ) + { + case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS): + case XML_ELEMENT(OOO, XML_DOCUMENT_SETTINGS): + GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); + pContext = new DBXMLDocumentSettingsContext(*this); + break; + case XML_ELEMENT(OFFICE, XML_DOCUMENT_STYLES): + case XML_ELEMENT(OOO, XML_DOCUMENT_STYLES): + pContext = new DBXMLDocumentStylesContext(*this); + break; + case XML_ELEMENT(OFFICE, XML_DOCUMENT_CONTENT): + case XML_ELEMENT(OOO, XML_DOCUMENT_CONTENT): + pContext = new DBXMLDocumentContentContext(*this); + break; + } + + return pContext; +} + + +void ODBFilter::SetViewSettings(const Sequence& aViewProps) +{ + const PropertyValue *pIter = aViewProps.getConstArray(); + const PropertyValue *pEnd = pIter + aViewProps.getLength(); + for (; pIter != pEnd; ++pIter) + { + if ( pIter->Name == "Queries" ) + { + fillPropertyMap(pIter->Value,m_aQuerySettings); + } + else if ( pIter->Name == "Tables" ) + { + fillPropertyMap(pIter->Value,m_aTablesSettings); + } + } +} + + +void ODBFilter::SetConfigurationSettings(const Sequence& aConfigProps) +{ + const PropertyValue *pIter = aConfigProps.getConstArray(); + const PropertyValue *pEnd = pIter + aConfigProps.getLength(); + for (; pIter != pEnd; ++pIter) + { + if ( pIter->Name == "layout-settings" ) + { + Sequence aWindows; + pIter->Value >>= aWindows; + uno::Reference xProp(getDataSource()); + if ( xProp.is() ) + xProp->setPropertyValue(PROPERTY_LAYOUTINFORMATION,Any(aWindows)); + } + } +} + + +void ODBFilter::fillPropertyMap(const Any& _rValue,TPropertyNameMap& _rMap) +{ + Sequence aWindows; + _rValue >>= aWindows; + const PropertyValue *pIter = aWindows.getConstArray(); + const PropertyValue *pEnd = pIter + aWindows.getLength(); + for (; pIter != pEnd; ++pIter) + { + Sequence aValue; + pIter->Value >>= aValue; + _rMap.emplace( pIter->Name,aValue ); + } + +} + +SvXMLImportContext* ODBFilter::CreateStylesContext( bool bIsAutoStyle ) +{ + SvXMLImportContext *pContext = new OTableStylesContext(*this, bIsAutoStyle); + if (bIsAutoStyle) + SetAutoStyles(static_cast(pContext)); + else + SetStyles(static_cast(pContext)); + + return pContext; +} + + +rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetTableStylesPropertySetMapper() const +{ + if ( !m_xTableStylesPropertySetMapper.is() ) + { + m_xTableStylesPropertySetMapper = OXMLHelper::GetTableStylesPropertySetMapper( false); + } + return m_xTableStylesPropertySetMapper; +} + + +rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetColumnStylesPropertySetMapper() const +{ + if ( !m_xColumnStylesPropertySetMapper.is() ) + { + m_xColumnStylesPropertySetMapper = OXMLHelper::GetColumnStylesPropertySetMapper( false); + } + return m_xColumnStylesPropertySetMapper; +} + + +rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetCellStylesPropertySetMapper() const +{ + if ( !m_xCellStylesPropertySetMapper.is() ) + { + m_xCellStylesPropertySetMapper = OXMLHelper::GetCellStylesPropertySetMapper( false); + } + return m_xCellStylesPropertySetMapper; +} + + +void ODBFilter::setPropertyInfo() +{ + Reference xDataSource(getDataSource()); + if ( !xDataSource.is() ) + return; + + ::connectivity::DriversConfig aDriverConfig(GetComponentContext()); + const OUString sURL = ::comphelper::getString(xDataSource->getPropertyValue(PROPERTY_URL)); + ::comphelper::NamedValueCollection aDataSourceSettings = aDriverConfig.getProperties( sURL ); + + Sequence aInfo; + if ( !m_aInfoSequence.empty() ) + aInfo = comphelper::containerToSequence(m_aInfoSequence); + aDataSourceSettings.merge( ::comphelper::NamedValueCollection( aInfo ), true ); + + aDataSourceSettings >>= aInfo; + if ( aInfo.hasElements() ) + { + try + { + xDataSource->setPropertyValue(PROPERTY_INFO,Any(aInfo)); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + } +} + +} // namespace dbaxml + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3