nss: upgrade to release 3.73
[LibreOffice.git] / dbaccess / source / filter / xml / xmlfilter.cxx
blob24516771289c208c9a57675e9f684d0ac1bb6e46
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <vcl/errinf.hxx>
24 #include <com/sun/star/frame/XModel.hpp>
25 #include <com/sun/star/uri/UriReferenceFactory.hpp>
26 #include <com/sun/star/util/MeasureUnit.hpp>
27 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
28 #include <com/sun/star/packages/WrongPasswordException.hpp>
29 #include <com/sun/star/packages/zip/ZipIOException.hpp>
30 #include <com/sun/star/embed/ElementModes.hpp>
31 #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
32 #include "xmlfilter.hxx"
33 #include <vcl/svapp.hxx>
34 #include <vcl/window.hxx>
35 #include <xmloff/xmlnamespace.hxx>
36 #include <xmloff/xmlscripti.hxx>
37 #include <xmloff/xmltoken.hxx>
38 #include <xmloff/namespacemap.hxx>
39 #include <com/sun/star/xml/sax/InputSource.hpp>
40 #include <com/sun/star/xml/sax/SAXParseException.hpp>
41 #include <xmloff/ProgressBarHelper.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <com/sun/star/io/XInputStream.hpp>
44 #include "xmlDatabase.hxx"
45 #include "xmlEnums.hxx"
46 #include <strings.hxx>
47 #include <xmloff/DocumentSettingsContext.hxx>
48 #include "xmlStyleImport.hxx"
49 #include <xmloff/xmluconv.hxx>
50 #include "xmlHelper.hxx"
51 #include <com/sun/star/util/XModifiable.hpp>
52 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
53 #include <svtools/sfxecode.hxx>
54 #include <tools/diagnose_ex.h>
55 #include <osl/diagnose.h>
56 #include <comphelper/sequence.hxx>
57 #include <comphelper/types.hxx>
58 #include <comphelper/namedvaluecollection.hxx>
59 #include <cppuhelper/exc_hlp.hxx>
60 #include <connectivity/DriversConfig.hxx>
61 #include <rtl/uri.hxx>
63 using namespace ::com::sun::star;
65 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
66 com_sun_star_comp_sdb_DBFilter_get_implementation(
67 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
69 return cppu::acquire(new ::dbaxml::ODBFilter(context));
73 namespace dbaxml
75 using namespace ::com::sun::star::util;
76 /// read a component (file + filter version)
77 static ErrCode ReadThroughComponent(
78 const uno::Reference<XInputStream>& xInputStream,
79 const uno::Reference<XComponent>& xModelComponent,
80 const uno::Reference<XComponentContext> & rxContext,
81 ODBFilter& _rFilter )
83 OSL_ENSURE(xInputStream.is(), "input stream missing");
84 OSL_ENSURE(xModelComponent.is(), "document missing");
85 OSL_ENSURE(rxContext.is(), "factory missing");
87 // prepare ParserInputSource
88 InputSource aParserInput;
89 aParserInput.aInputStream = xInputStream;
91 // connect model and filter
92 _rFilter.setTargetDocument( xModelComponent );
94 // finally, parser the stream
95 try
97 _rFilter.parseStream( aParserInput );
99 catch (const SAXParseException&)
101 #if OSL_DEBUG_LEVEL > 0
102 TOOLS_WARN_EXCEPTION("dbaccess", "SAX parse exception caught while importing");
103 #endif
104 return ErrCode(1);
106 catch (const SAXException&)
108 return ErrCode(1);
110 catch (const packages::zip::ZipIOException&)
112 return ERRCODE_IO_BROKENPACKAGE;
114 catch (const Exception&)
116 DBG_UNHANDLED_EXCEPTION("dbaccess");
119 // success!
120 return ERRCODE_NONE;
124 /// read a component (storage version)
125 static ErrCode ReadThroughComponent(
126 const uno::Reference< embed::XStorage >& xStorage,
127 const uno::Reference<XComponent>& xModelComponent,
128 const char* pStreamName,
129 const uno::Reference<XComponentContext> & rxContext,
130 ODBFilter& _rFilter)
132 OSL_ENSURE( xStorage.is(), "Need storage!");
133 OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!");
135 if ( xStorage.is() )
137 uno::Reference< io::XStream > xDocStream;
141 // open stream (and set parser input)
142 OUString sStreamName = OUString::createFromAscii(pStreamName);
143 if ( !xStorage->hasByName( sStreamName ) || !xStorage->isStreamElement( sStreamName ) )
145 // stream name not found! return immediately with OK signal
146 return ERRCODE_NONE;
149 // get input stream
150 xDocStream = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ );
152 catch (const packages::WrongPasswordException&)
154 return ERRCODE_SFX_WRONGPASSWORD;
156 catch (const uno::Exception&)
158 return ErrCode(1); // TODO/LATER: error handling
161 uno::Reference< XInputStream > xInputStream = xDocStream->getInputStream();
162 // read from the stream
163 return ReadThroughComponent( xInputStream
164 ,xModelComponent
165 ,rxContext
166 ,_rFilter );
169 // TODO/LATER: better error handling
170 return ErrCode(1);
174 ODBFilter::ODBFilter( const uno::Reference< XComponentContext >& _rxContext )
175 : SvXMLImport(_rxContext, getImplementationName_Static())
176 , m_bNewFormat(false)
179 GetMM100UnitConverter().SetCoreMeasureUnit(util::MeasureUnit::MM_10TH);
180 GetMM100UnitConverter().SetXMLMeasureUnit(util::MeasureUnit::CM);
181 GetNamespaceMap().Add( "_db",
182 GetXMLToken(XML_N_DB),
183 XML_NAMESPACE_DB );
185 GetNamespaceMap().Add( "__db",
186 GetXMLToken(XML_N_DB_OASIS),
187 XML_NAMESPACE_DB );
191 ODBFilter::~ODBFilter() throw()
197 OUString ODBFilter::getImplementationName_Static()
199 return "com.sun.star.comp.sdb.DBFilter";
203 namespace {
204 class FocusWindowWaitGuard
206 public:
207 FocusWindowWaitGuard()
209 SolarMutexGuard aGuard;
210 mpWindow.set(Application::GetFocusWindow());
211 if (mpWindow)
212 mpWindow->EnterWait();
214 ~FocusWindowWaitGuard()
216 if (mpWindow)
218 SolarMutexGuard aGuard;
219 mpWindow->LeaveWait();
222 private:
223 VclPtr<vcl::Window> mpWindow;
227 sal_Bool SAL_CALL ODBFilter::filter( const Sequence< PropertyValue >& rDescriptor )
229 FocusWindowWaitGuard aWindowFocusGuard;
230 bool bRet = false;
232 if ( GetModel().is() )
233 bRet = implImport( rDescriptor );
235 return bRet;
239 bool ODBFilter::implImport( const Sequence< PropertyValue >& rDescriptor )
241 OUString sFileName;
242 ::comphelper::NamedValueCollection aMediaDescriptor( rDescriptor );
244 uno::Reference<embed::XStorage> xStorage = GetSourceStorage();
246 bool bRet = true;
247 if (!xStorage.is())
249 if (aMediaDescriptor.has("URL"))
250 sFileName = aMediaDescriptor.getOrDefault("URL", OUString());
251 if (sFileName.isEmpty() && aMediaDescriptor.has("FileName"))
252 sFileName = aMediaDescriptor.getOrDefault("FileName", sFileName);
254 OSL_ENSURE(!sFileName.isEmpty(), "ODBFilter::implImport: no URL given!");
255 bRet = !sFileName.isEmpty();
258 if ( bRet )
261 tools::SvRef<SfxMedium> pMedium;
262 if (!xStorage.is())
264 OUString sStreamRelPath;
265 if (sFileName.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:"))
267 // In this case the authority contains the real path, and the path is the embedded stream name.
268 auto const uri = css::uri::UriReferenceFactory::create(GetComponentContext())
269 ->parse(sFileName);
270 if (uri.is() && uri->isAbsolute()
271 && uri->hasAuthority() && !uri->hasQuery() && !uri->hasFragment())
273 auto const auth = uri->getAuthority();
274 auto const decAuth = rtl::Uri::decode(
275 auth, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
276 auto path = uri->getPath();
277 if (!path.isEmpty()) {
278 assert(path[0] == '/');
279 path = path.copy(1);
281 auto const decPath = rtl::Uri::decode(
282 path, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
283 //TODO: really decode path?
284 if (auth.isEmpty() == decAuth.isEmpty() && path.isEmpty() == decPath.isEmpty())
286 // Decoding of auth and path to UTF-8 succeeded:
287 sFileName = decAuth;
288 sStreamRelPath = decPath;
289 } else {
290 SAL_WARN(
291 "dbaccess",
292 "<" << sFileName << "> cannot be parse as vnd.sun.star.pkg URL");
294 } else {
295 SAL_WARN(
296 "dbaccess",
297 "<" << sFileName << "> cannot be parse as vnd.sun.star.pkg URL");
301 pMedium = new SfxMedium(sFileName, (StreamMode::READ | StreamMode::NOCREATE));
304 xStorage.set(pMedium->GetStorage(false), UNO_SET_THROW);
306 if (!sStreamRelPath.isEmpty())
307 xStorage = xStorage->openStorageElement(sStreamRelPath, embed::ElementModes::READ);
309 catch (const RuntimeException&)
311 throw;
313 catch (const Exception&)
315 Any aError = ::cppu::getCaughtException();
316 throw lang::WrappedTargetRuntimeException(OUString(), *this, aError);
320 uno::Reference<sdb::XOfficeDatabaseDocument> xOfficeDoc(GetModel(),UNO_QUERY_THROW);
321 m_xDataSource.set(xOfficeDoc->getDataSource(),UNO_QUERY_THROW);
322 uno::Reference< XNumberFormatsSupplier > xNum(m_xDataSource->getPropertyValue(PROPERTY_NUMBERFORMATSSUPPLIER),UNO_QUERY);
323 SetNumberFormatsSupplier(xNum);
325 uno::Reference<XComponent> xModel(GetModel());
326 ErrCode nRet = ReadThroughComponent( xStorage
327 ,xModel
328 ,"settings.xml"
329 ,GetComponentContext()
330 ,*this
333 if ( nRet == ERRCODE_NONE )
334 nRet = ReadThroughComponent( xStorage
335 ,xModel
336 ,"content.xml"
337 ,GetComponentContext()
338 ,*this
341 bRet = nRet == ERRCODE_NONE;
343 if ( bRet )
345 uno::Reference< XModifiable > xModi(GetModel(),UNO_QUERY);
346 if ( xModi.is() )
347 xModi->setModified(false);
349 else
351 if ( nRet == ERRCODE_IO_BROKENPACKAGE )
352 ;// TODO/LATER: no way to transport the error outside from the filter!
353 else
355 // TODO/LATER: this is completely wrong! Filter code should never call ErrorHandler directly! But for now this is the only way!
356 ErrorHandler::HandleError( nRet );
357 if( nRet.IsWarning() )
358 bRet = true;
363 return bRet;
366 namespace {
368 class DBXMLDocumentSettingsContext : public SvXMLImportContext
370 public:
371 DBXMLDocumentSettingsContext(SvXMLImport & rImport)
372 : SvXMLImportContext(rImport)
376 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
377 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override
379 if (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS))
381 return new XMLDocumentSettingsContext(GetImport());
383 return nullptr;
387 class DBXMLDocumentStylesContext : public SvXMLImportContext
389 public:
390 DBXMLDocumentStylesContext(SvXMLImport & rImport)
391 : SvXMLImportContext(rImport)
395 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
396 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override
398 ODBFilter & rImport(static_cast<ODBFilter&>(GetImport()));
399 switch (nElement)
401 case XML_ELEMENT(OFFICE, XML_STYLES):
402 case XML_ELEMENT(OOO, XML_STYLES):
403 rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
404 return rImport.CreateStylesContext(false);
405 break;
406 case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES):
407 case XML_ELEMENT(OOO, XML_AUTOMATIC_STYLES):
408 rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
409 return rImport.CreateStylesContext(true);
410 break;
412 return nullptr;
416 class DBXMLDocumentBodyContext : public SvXMLImportContext
418 public:
419 DBXMLDocumentBodyContext(SvXMLImport & rImport)
420 : SvXMLImportContext(rImport)
424 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
425 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override
427 ODBFilter & rImport(static_cast<ODBFilter&>(GetImport()));
428 switch (nElement)
430 case XML_ELEMENT(OFFICE, XML_DATABASE):
431 case XML_ELEMENT(OOO, XML_DATABASE):
432 rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
433 return new OXMLDatabase(rImport);
434 default: break;
436 return nullptr;
440 class DBXMLDocumentContentContext : public SvXMLImportContext
442 public:
443 DBXMLDocumentContentContext(SvXMLImport & rImport)
444 : SvXMLImportContext(rImport)
448 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
449 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) override
451 ODBFilter & rImport(static_cast<ODBFilter&>(GetImport()));
452 switch (nElement)
454 case XML_ELEMENT(OFFICE, XML_BODY):
455 case XML_ELEMENT(OOO, XML_BODY):
456 return new DBXMLDocumentBodyContext(rImport);
457 break;
458 case XML_ELEMENT(OFFICE, XML_SCRIPTS):
459 return new XMLScriptContext(GetImport(), rImport.GetModel());
460 break;
461 case XML_ELEMENT(OFFICE, XML_AUTOMATIC_STYLES):
462 case XML_ELEMENT(OOO, XML_AUTOMATIC_STYLES):
463 rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
464 return rImport.CreateStylesContext(true);
465 break;
466 default: break;
468 return nullptr;
474 SvXMLImportContext* ODBFilter::CreateFastContext(sal_Int32 nElement,
475 const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
477 SvXMLImportContext *pContext = nullptr;
479 switch( nElement )
481 case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS):
482 case XML_ELEMENT(OOO, XML_DOCUMENT_SETTINGS):
483 GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
484 pContext = new DBXMLDocumentSettingsContext(*this);
485 break;
486 case XML_ELEMENT(OFFICE, XML_DOCUMENT_STYLES):
487 case XML_ELEMENT(OOO, XML_DOCUMENT_STYLES):
488 pContext = new DBXMLDocumentStylesContext(*this);
489 break;
490 case XML_ELEMENT(OFFICE, XML_DOCUMENT_CONTENT):
491 case XML_ELEMENT(OOO, XML_DOCUMENT_CONTENT):
492 pContext = new DBXMLDocumentContentContext(*this);
493 break;
496 return pContext;
500 void ODBFilter::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
502 const PropertyValue *pIter = aViewProps.getConstArray();
503 const PropertyValue *pEnd = pIter + aViewProps.getLength();
504 for (; pIter != pEnd; ++pIter)
506 if ( pIter->Name == "Queries" )
508 fillPropertyMap(pIter->Value,m_aQuerySettings);
510 else if ( pIter->Name == "Tables" )
512 fillPropertyMap(pIter->Value,m_aTablesSettings);
518 void ODBFilter::SetConfigurationSettings(const Sequence<PropertyValue>& aConfigProps)
520 const PropertyValue *pIter = aConfigProps.getConstArray();
521 const PropertyValue *pEnd = pIter + aConfigProps.getLength();
522 for (; pIter != pEnd; ++pIter)
524 if ( pIter->Name == "layout-settings" )
526 Sequence<PropertyValue> aWindows;
527 pIter->Value >>= aWindows;
528 uno::Reference<XPropertySet> xProp(getDataSource());
529 if ( xProp.is() )
530 xProp->setPropertyValue(PROPERTY_LAYOUTINFORMATION,makeAny(aWindows));
536 void ODBFilter::fillPropertyMap(const Any& _rValue,TPropertyNameMap& _rMap)
538 Sequence<PropertyValue> aWindows;
539 _rValue >>= aWindows;
540 const PropertyValue *pIter = aWindows.getConstArray();
541 const PropertyValue *pEnd = pIter + aWindows.getLength();
542 for (; pIter != pEnd; ++pIter)
544 Sequence<PropertyValue> aValue;
545 pIter->Value >>= aValue;
546 _rMap.emplace( pIter->Name,aValue );
551 SvXMLImportContext* ODBFilter::CreateStylesContext( bool bIsAutoStyle )
553 SvXMLImportContext *pContext = new OTableStylesContext(*this, bIsAutoStyle);
554 if (bIsAutoStyle)
555 SetAutoStyles(static_cast<SvXMLStylesContext*>(pContext));
556 else
557 SetStyles(static_cast<SvXMLStylesContext*>(pContext));
559 return pContext;
563 rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetTableStylesPropertySetMapper() const
565 if ( !m_xTableStylesPropertySetMapper.is() )
567 m_xTableStylesPropertySetMapper = OXMLHelper::GetTableStylesPropertySetMapper( false);
569 return m_xTableStylesPropertySetMapper;
573 rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetColumnStylesPropertySetMapper() const
575 if ( !m_xColumnStylesPropertySetMapper.is() )
577 m_xColumnStylesPropertySetMapper = OXMLHelper::GetColumnStylesPropertySetMapper( false);
579 return m_xColumnStylesPropertySetMapper;
583 rtl::Reference < XMLPropertySetMapper > const & ODBFilter::GetCellStylesPropertySetMapper() const
585 if ( !m_xCellStylesPropertySetMapper.is() )
587 m_xCellStylesPropertySetMapper = OXMLHelper::GetCellStylesPropertySetMapper( false);
589 return m_xCellStylesPropertySetMapper;
593 void ODBFilter::setPropertyInfo()
595 Reference<XPropertySet> xDataSource(getDataSource());
596 if ( !xDataSource.is() )
597 return;
599 ::connectivity::DriversConfig aDriverConfig(GetComponentContext());
600 const OUString sURL = ::comphelper::getString(xDataSource->getPropertyValue(PROPERTY_URL));
601 ::comphelper::NamedValueCollection aDataSourceSettings = aDriverConfig.getProperties( sURL );
603 Sequence<PropertyValue> aInfo;
604 if ( !m_aInfoSequence.empty() )
605 aInfo = comphelper::containerToSequence(m_aInfoSequence);
606 aDataSourceSettings.merge( ::comphelper::NamedValueCollection( aInfo ), true );
608 aDataSourceSettings >>= aInfo;
609 if ( aInfo.hasElements() )
613 xDataSource->setPropertyValue(PROPERTY_INFO,makeAny(aInfo));
615 catch (const Exception&)
617 DBG_UNHANDLED_EXCEPTION("dbaccess");
622 } // namespace dbaxml
624 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */