1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <tools/urlobj.hxx>
21 #include <com/sun/star/document/XGraphicStorageHandler.hpp>
22 #include <com/sun/star/embed/ElementModes.hpp>
23 #include <com/sun/star/container/XNameContainer.hpp>
24 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
25 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
26 #include <com/sun/star/drawing/LineDash.hpp>
27 #include <com/sun/star/awt/Gradient.hpp>
28 #include <com/sun/star/awt/XBitmap.hpp>
29 #include <com/sun/star/drawing/Hatch.hpp>
30 #include <com/sun/star/io/XSeekable.hpp>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/storagehelper.hxx>
33 #include <sax/tools/converter.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <xmloff/xmlnamespace.hxx>
36 #include <xmloff/namespacemap.hxx>
38 #include <xmloff/xmltoken.hxx>
39 #include <xmloff/DashStyle.hxx>
40 #include <xmloff/GradientStyle.hxx>
41 #include <xmloff/HatchStyle.hxx>
42 #include <xmloff/ImageStyle.hxx>
43 #include <xmloff/MarkerStyle.hxx>
44 #include <xmloff/xmlictxt.hxx>
45 #include <svx/xmlgrhlp.hxx>
47 #include <xmlxtimp.hxx>
48 #include <tools/diagnose_ex.h>
50 using namespace com::sun::star
;
51 using namespace com::sun::star::container
;
52 using namespace com::sun::star::document
;
53 using namespace com::sun::star::uno
;
54 using namespace com::sun::star::awt
;
55 using namespace com::sun::star::lang
;
56 using namespace com::sun::star::xml::sax
;
57 using namespace ::xmloff::token
;
62 enum class SvxXMLTableImportContextEnum
{ Color
, Marker
, Dash
, Hatch
, Gradient
, Bitmap
};
64 class SvxXMLTableImportContext
: public SvXMLImportContext
67 SvxXMLTableImportContext( SvXMLImport
& rImport
, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
,
70 virtual css::uno::Reference
< css::xml::sax::XFastContextHandler
> SAL_CALL
71 createFastChildContext(sal_Int32 Element
,
72 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & Attribs
) override
;
75 static void importColor( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
76 void importMarker( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
77 void importDash( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
78 void importHatch( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
79 void importGradient( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
80 void importBitmap( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
83 uno::Reference
< XNameContainer
> mxTable
;
84 SvxXMLTableImportContextEnum meContext
;
90 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport
& rImport
, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
, bool bOOoFormat
)
91 : SvXMLImportContext( rImport
), mxTable( xTable
), meContext( eContext
),
92 mbOOoFormat( bOOoFormat
)
96 css::uno::Reference
< css::xml::sax::XFastContextHandler
>
97 SvxXMLTableImportContext::createFastChildContext(sal_Int32 nElement
,
98 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & rAttrList
)
100 if( !(IsTokenInNamespace(nElement
, XML_NAMESPACE_DRAW
) ||
101 IsTokenInNamespace(nElement
, XML_NAMESPACE_DRAW_OOO
) ))
104 std::vector
<std::pair
<sal_Int32
, OString
>> aTmpAttrList
;
105 for (auto& aIter
: sax_fastparser::castToFastAttributeList( rAttrList
))
106 aTmpAttrList
.push_back({aIter
.getToken(), OString(aIter
.toCString())});
108 (SvxXMLTableImportContextEnum::Dash
== meContext
|| SvxXMLTableImportContextEnum::Hatch
== meContext
||
109 SvxXMLTableImportContextEnum::Bitmap
== meContext
) )
111 for( auto & aIter
: aTmpAttrList
)
113 sal_Int32 aLocalAttr
= aIter
.first
& TOKEN_MASK
;
114 if( aIter
.first
== XML_ELEMENT(XLINK
, XML_HREF
) &&
115 SvxXMLTableImportContextEnum::Bitmap
== meContext
)
117 OString rValue
= aIter
.second
;
118 if( !rValue
.isEmpty() && '#' == rValue
[0] )
119 rValue
= rValue
.copy( 1 );
121 else if( (IsTokenInNamespace(aIter
.first
, XML_NAMESPACE_DRAW
) || IsTokenInNamespace(aIter
.first
, XML_NAMESPACE_DRAW_OOO
)) &&
122 ( ( SvxXMLTableImportContextEnum::Dash
== meContext
&&
123 ( aLocalAttr
== XML_DOTS1_LENGTH
||
124 aLocalAttr
== XML_DOTS2_LENGTH
||
125 aLocalAttr
== XML_DISTANCE
) ) ||
126 ( SvxXMLTableImportContextEnum::Hatch
== meContext
&&
127 ( aLocalAttr
== XML_DISTANCE
) ) ) )
129 OString
& rValue
= aIter
.second
;
130 sal_Int32 nPos
= rValue
.getLength();
131 while( nPos
&& rValue
[nPos
-1] <= ' ' )
134 ('c'==rValue
[nPos
-2] || 'C'==rValue
[nPos
-2]) &&
135 ('h'==rValue
[nPos
-1] || 'H'==rValue
[nPos
-1]) )
137 rValue
= rValue
.copy( 0, nPos
-2 );
144 rtl::Reference
<sax_fastparser::FastAttributeList
> xFastList
= new sax_fastparser::FastAttributeList(nullptr);
145 for (auto& aIter
: aTmpAttrList
)
146 xFastList
->add(aIter
.first
, aIter
.second
);
153 case SvxXMLTableImportContextEnum::Color
:
154 importColor( xFastList
, aAny
, aName
);
156 case SvxXMLTableImportContextEnum::Marker
:
157 importMarker( xFastList
, aAny
, aName
);
159 case SvxXMLTableImportContextEnum::Dash
:
160 importDash( xFastList
, aAny
, aName
);
162 case SvxXMLTableImportContextEnum::Hatch
:
163 importHatch( xFastList
, aAny
, aName
);
165 case SvxXMLTableImportContextEnum::Gradient
:
166 importGradient( xFastList
, aAny
, aName
);
168 case SvxXMLTableImportContextEnum::Bitmap
:
169 importBitmap( xFastList
, aAny
, aName
);
173 if( !aName
.isEmpty() && aAny
.hasValue() )
175 if( mxTable
->hasByName( aName
) )
177 mxTable
->replaceByName( aName
, aAny
);
181 mxTable
->insertByName( aName
, aAny
);
185 catch (const uno::Exception
&)
187 DBG_UNHANDLED_EXCEPTION("svx");
189 return new SvXMLImportContext( GetImport() );
192 void SvxXMLTableImportContext::importColor( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
194 for (auto& aIter
: sax_fastparser::castToFastAttributeList( xAttrList
))
196 switch (aIter
.getToken())
198 case XML_ELEMENT(DRAW
, XML_NAME
):
199 case XML_ELEMENT(DRAW_OOO
, XML_NAME
):
200 rName
= aIter
.toString();
202 case XML_ELEMENT(DRAW
, XML_COLOR
):
203 case XML_ELEMENT(DRAW_OOO
, XML_COLOR
):
206 ::sax::Converter::convertColor(nColor
, aIter
.toString());
211 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
216 void SvxXMLTableImportContext::importMarker( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
220 XMLMarkerStyleImport
aMarkerStyle( GetImport() );
221 aMarkerStyle
.importXML( xAttrList
, rAny
, rName
);
223 catch (const Exception
&)
225 TOOLS_WARN_EXCEPTION("svx", "");
229 void SvxXMLTableImportContext::importDash( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
233 XMLDashStyleImport
aDashStyle( GetImport() );
234 aDashStyle
.importXML( xAttrList
, rAny
, rName
);
236 catch (const Exception
&)
238 TOOLS_WARN_EXCEPTION("svx", "");
242 void SvxXMLTableImportContext::importHatch( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
246 XMLHatchStyleImport
aHatchStyle( GetImport() );
247 aHatchStyle
.importXML( xAttrList
, rAny
, rName
);
249 catch (const Exception
&)
251 TOOLS_WARN_EXCEPTION("svx", "");
255 void SvxXMLTableImportContext::importGradient( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
259 XMLGradientStyleImport
aGradientStyle( GetImport() );
260 aGradientStyle
.importXML( xAttrList
, rAny
, rName
);
262 catch (const Exception
&)
264 TOOLS_WARN_EXCEPTION("svx", "");
268 void SvxXMLTableImportContext::importBitmap( const uno::Reference
< XFastAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
272 uno::Any aGraphicAny
;
273 XMLImageStyle::importXML(xAttrList
, aGraphicAny
, rName
, GetImport());
274 if (aGraphicAny
.has
<uno::Reference
<graphic::XGraphic
>>())
276 auto xGraphic
= aGraphicAny
.get
<uno::Reference
<graphic::XGraphic
>>();
277 uno::Reference
<awt::XBitmap
> xBitmap(xGraphic
, uno::UNO_QUERY
);
282 catch (const Exception
&)
284 TOOLS_WARN_EXCEPTION("svx", "");
289 SvxXMLXTableImport::SvxXMLXTableImport(
290 const css::uno::Reference
< css::uno::XComponentContext
>& rContext
,
291 const uno::Reference
< XNameContainer
> & rTable
,
292 uno::Reference
<XGraphicStorageHandler
> const & xGraphicStorageHandler
)
293 : SvXMLImport(rContext
, "", SvXMLImportFlags::NONE
),
296 SetGraphicStorageHandler(xGraphicStorageHandler
);
298 GetNamespaceMap().Add( GetXMLToken(XML_NP_OOO
), GetXMLToken(XML_N_OOO
), XML_NAMESPACE_OOO
);
299 GetNamespaceMap().Add( GetXMLToken(XML_NP_OFFICE
), GetXMLToken(XML_N_OFFICE
), XML_NAMESPACE_OFFICE
);
300 GetNamespaceMap().Add( GetXMLToken(XML_NP_DRAW
), GetXMLToken(XML_N_DRAW
), XML_NAMESPACE_DRAW
);
301 GetNamespaceMap().Add( GetXMLToken(XML_NP_XLINK
), GetXMLToken(XML_N_XLINK
), XML_NAMESPACE_XLINK
);
303 GetNamespaceMap().Add( "__ooo", GetXMLToken(XML_N_OOO
), XML_NAMESPACE_OOO
);
304 GetNamespaceMap().Add( "__xlink", GetXMLToken(XML_N_XLINK
), XML_NAMESPACE_XLINK
);
306 // OOo namespaces for reading OOo 1.1 files
307 GetNamespaceMap().Add( "___office",
308 GetXMLToken(XML_N_OFFICE_OOO
),
309 XML_NAMESPACE_OFFICE
);
310 GetNamespaceMap().Add( "___draw",
311 GetXMLToken(XML_N_DRAW_OOO
),
312 XML_NAMESPACE_DRAW
);
315 SvxXMLXTableImport::~SvxXMLXTableImport() noexcept
319 static void openStorageStream( xml::sax::InputSource
*pParserInput
,
320 rtl::Reference
<SvXMLGraphicHelper
>& rxGraphicHelper
,
321 const uno::Reference
< embed::XStorage
>& xStorage
)
323 uno::Reference
< io::XStream
> xIStm( xStorage
->openStreamElement( "Content.xml", embed::ElementModes::READ
), uno::UNO_SET_THROW
);
324 pParserInput
->aInputStream
= xIStm
->getInputStream();
325 rxGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, SvXMLGraphicHelperMode::Read
);
328 bool SvxXMLXTableImport::load( const OUString
&rPath
, const OUString
&rReferer
,
329 const uno::Reference
< embed::XStorage
> &xStorage
,
330 const uno::Reference
< XNameContainer
>& xTable
,
331 bool *bOptLoadedFromStorage
) noexcept
334 rtl::Reference
<SvXMLGraphicHelper
> xGraphicHelper
;
336 INetURLObject
aURLObj( rPath
);
337 bool bUseStorage
= aURLObj
.GetProtocol() == INetProtocol::NotValid
; // a relative path
341 uno::Reference
<uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
343 xml::sax::InputSource aParserInput
;
344 comphelper::LifecycleProxy aNasty
;
346 if( !bUseStorage
|| !xStorage
.is() )
348 SfxMedium
aMedium( rPath
, rReferer
, StreamMode::READ
| StreamMode::NOCREATE
);
349 aParserInput
.sSystemId
= aMedium
.GetName();
351 if( aMedium
.IsStorage() )
353 uno::Reference
< embed::XStorage
> xMediumStorage( aMedium
.GetStorage( false ), uno::UNO_SET_THROW
);
354 openStorageStream( &aParserInput
, xGraphicHelper
, xMediumStorage
);
357 aParserInput
.aInputStream
= aMedium
.GetInputStream();
359 else // relative URL into a storage
361 uno::Reference
< embed::XStorage
> xSubStorage
;
364 xSubStorage
= comphelper::OStorageHelper::GetStorageAtPath(
365 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
367 catch (const uno::Exception
&)
370 if( xSubStorage
.is() )
371 openStorageStream( &aParserInput
, xGraphicHelper
, xSubStorage
);
374 css::uno::Reference
< css::io::XStream
> xStream
= comphelper::OStorageHelper::GetStreamAtPath(
375 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
378 aParserInput
.aInputStream
= xStream
->getInputStream();
380 if( bOptLoadedFromStorage
)
381 *bOptLoadedFromStorage
= true;
384 uno::Reference
<XGraphicStorageHandler
> xGraphicStorageHandler
;
385 if (xGraphicHelper
.is())
386 xGraphicStorageHandler
= xGraphicHelper
.get();
390 uno::Reference
< io::XSeekable
> xSeek( aParserInput
.aInputStream
, uno::UNO_QUERY_THROW
);
393 catch (const uno::Exception
&)
397 rtl::Reference
<SvxXMLXTableImport
> xImport(new SvxXMLXTableImport(xContext
, xTable
, xGraphicStorageHandler
));
398 xImport
->parseStream( aParserInput
);
401 xGraphicHelper
->dispose();
405 // thrown each time you load a document with property tables that are not
406 // on the current machine. FIXME: would be better to check a file exists
407 // before importing ...
414 SvXMLImportContext
*SvxXMLXTableImport::CreateFastContext( sal_Int32 nElement
,
415 const ::css::uno::Reference
< ::css::xml::sax::XFastAttributeList
>& /*xAttrList*/ )
417 if( IsTokenInNamespace(nElement
, XML_NAMESPACE_OOO
) ||
418 IsTokenInNamespace(nElement
, XML_NAMESPACE_OFFICE
) ||
419 IsTokenInNamespace(nElement
, XML_NAMESPACE_OFFICE_OOO
) )
421 bool bOOoFormat
= IsTokenInNamespace(nElement
, XML_NAMESPACE_OFFICE
) ||
422 IsTokenInNamespace(nElement
, XML_NAMESPACE_OFFICE_OOO
);
423 Type aType
= mrTable
->getElementType();
424 sal_Int32 nToken
= nElement
& TOKEN_MASK
;
426 if ( nToken
== XML_COLOR_TABLE
)
428 if( aType
== ::cppu::UnoType
<sal_Int32
>::get() )
429 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Color
, mrTable
, bOOoFormat
);
431 else if ( nToken
== XML_MARKER_TABLE
)
433 if( aType
== cppu::UnoType
<drawing::PolyPolygonBezierCoords
>::get())
434 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Marker
, mrTable
, bOOoFormat
);
436 else if ( nToken
== XML_DASH_TABLE
)
438 if( aType
== cppu::UnoType
<drawing::LineDash
>::get())
439 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Dash
, mrTable
, bOOoFormat
);
441 else if ( nToken
== XML_HATCH_TABLE
)
443 if( aType
== cppu::UnoType
<drawing::Hatch
>::get())
444 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Hatch
, mrTable
, bOOoFormat
);
446 else if ( nToken
== XML_GRADIENT_TABLE
)
448 if( aType
== cppu::UnoType
<awt::Gradient
>::get())
449 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Gradient
, mrTable
, bOOoFormat
);
451 else if ( nToken
== XML_BITMAP_TABLE
)
453 if( aType
== ::cppu::UnoType
<awt::XBitmap
>::get())
454 return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Bitmap
, mrTable
, bOOoFormat
);
461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */