LibreOffice Module svx (master)  1
xmlxtimp.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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>
33 #include <sax/tools/converter.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <xmloff/xmlnamespace.hxx>
36 #include <xmloff/namespacemap.hxx>
37 
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>
46 
47 #include <xmlxtimp.hxx>
48 #include <tools/diagnose_ex.h>
49 
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;
58 using namespace cppu;
59 
60 namespace {
61 
63 
64 class SvxXMLTableImportContext : public SvXMLImportContext
65 {
66 public:
67  SvxXMLTableImportContext( SvXMLImport& rImport, SvxXMLTableImportContextEnum eContext, const uno::Reference< XNameContainer >& xTable,
68  bool bOOoFormat );
69 
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;
73 
74 protected:
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 );
81 
82 private:
83  uno::Reference< XNameContainer > mxTable;
85  bool mbOOoFormat;
86 };
87 
88 }
89 
90 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport& rImport, SvxXMLTableImportContextEnum eContext, const uno::Reference< XNameContainer >& xTable, bool bOOoFormat )
91 : SvXMLImportContext( rImport ), mxTable( xTable ), meContext( eContext ),
92  mbOOoFormat( bOOoFormat )
93 {
94 }
95 
96 css::uno::Reference< css::xml::sax::XFastContextHandler >
97  SvxXMLTableImportContext::createFastChildContext(sal_Int32 nElement,
98  const css::uno::Reference< css::xml::sax::XFastAttributeList > & rAttrList)
99 {
100  if( !(IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) ||
101  IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW_OOO) ))
102  return nullptr;
103 
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())});
107  if( mbOOoFormat &&
108  (SvxXMLTableImportContextEnum::Dash == meContext || SvxXMLTableImportContextEnum::Hatch == meContext ||
109  SvxXMLTableImportContextEnum::Bitmap == meContext) )
110  {
111  for( auto & aIter : aTmpAttrList )
112  {
113  sal_Int32 aLocalAttr = aIter.first & TOKEN_MASK;
114  if( aIter.first == XML_ELEMENT(XLINK, XML_HREF) &&
115  SvxXMLTableImportContextEnum::Bitmap == meContext )
116  {
117  OString rValue = aIter.second;
118  if( !rValue.isEmpty() && '#' == rValue[0] )
119  rValue = rValue.copy( 1 );
120  }
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 ) ) ) )
128  {
129  OString& rValue = aIter.second;
130  sal_Int32 nPos = rValue.getLength();
131  while( nPos && rValue[nPos-1] <= ' ' )
132  --nPos;
133  if( nPos > 2 &&
134  ('c'==rValue[nPos-2] || 'C'==rValue[nPos-2]) &&
135  ('h'==rValue[nPos-1] || 'H'==rValue[nPos-1]) )
136  {
137  rValue = rValue.copy( 0, nPos-2 );
138  }
139  }
140  }
141  }
142  try
143  {
145  for (const auto& aIter : aTmpAttrList)
146  xFastList->add(aIter.first, aIter.second);
147 
148  Any aAny;
149  OUString aName;
150 
151  switch( meContext )
152  {
153  case SvxXMLTableImportContextEnum::Color:
154  importColor( xFastList, aAny, aName );
155  break;
156  case SvxXMLTableImportContextEnum::Marker:
157  importMarker( xFastList, aAny, aName );
158  break;
159  case SvxXMLTableImportContextEnum::Dash:
160  importDash( xFastList, aAny, aName );
161  break;
162  case SvxXMLTableImportContextEnum::Hatch:
163  importHatch( xFastList, aAny, aName );
164  break;
165  case SvxXMLTableImportContextEnum::Gradient:
166  importGradient( xFastList, aAny, aName );
167  break;
168  case SvxXMLTableImportContextEnum::Bitmap:
169  importBitmap( xFastList, aAny, aName );
170  break;
171  }
172 
173  if( !aName.isEmpty() && aAny.hasValue() )
174  {
175  if( mxTable->hasByName( aName ) )
176  {
177  mxTable->replaceByName( aName, aAny );
178  }
179  else
180  {
181  mxTable->insertByName( aName, aAny );
182  }
183  }
184  }
185  catch (const uno::Exception&)
186  {
188  }
189  return new SvXMLImportContext( GetImport() );
190 }
191 
192 void SvxXMLTableImportContext::importColor( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
193 {
194  for (auto& aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
195  {
196  switch (aIter.getToken())
197  {
198  case XML_ELEMENT(DRAW, XML_NAME):
199  case XML_ELEMENT(DRAW_OOO, XML_NAME):
200  rName = aIter.toString();
201  break;
202  case XML_ELEMENT(DRAW, XML_COLOR):
203  case XML_ELEMENT(DRAW_OOO, XML_COLOR):
204  {
205  sal_Int32 nColor(0);
206  ::sax::Converter::convertColor(nColor, aIter.toString());
207  rAny <<= nColor;
208  break;
209  }
210  default:
211  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
212  }
213  }
214 }
215 
216 void SvxXMLTableImportContext::importMarker( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
217 {
218  try
219  {
220  XMLMarkerStyleImport aMarkerStyle( GetImport() );
221  aMarkerStyle.importXML( xAttrList, rAny, rName );
222  }
223  catch (const Exception&)
224  {
225  TOOLS_WARN_EXCEPTION("svx", "");
226  }
227 }
228 
229 void SvxXMLTableImportContext::importDash( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
230 {
231  try
232  {
233  XMLDashStyleImport aDashStyle( GetImport() );
234  aDashStyle.importXML( xAttrList, rAny, rName );
235  }
236  catch (const Exception&)
237  {
238  TOOLS_WARN_EXCEPTION("svx", "");
239  }
240 }
241 
242 void SvxXMLTableImportContext::importHatch( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
243 {
244  try
245  {
246  XMLHatchStyleImport aHatchStyle( GetImport() );
247  aHatchStyle.importXML( xAttrList, rAny, rName );
248  }
249  catch (const Exception&)
250  {
251  TOOLS_WARN_EXCEPTION("svx", "");
252  }
253 }
254 
255 void SvxXMLTableImportContext::importGradient( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
256 {
257  try
258  {
259  XMLGradientStyleImport aGradientStyle( GetImport() );
260  aGradientStyle.importXML( xAttrList, rAny, rName );
261  }
262  catch (const Exception&)
263  {
264  TOOLS_WARN_EXCEPTION("svx", "");
265  }
266 }
267 
268 void SvxXMLTableImportContext::importBitmap( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
269 {
270  try
271  {
272  uno::Any aGraphicAny;
273  XMLImageStyle::importXML(xAttrList, aGraphicAny, rName, GetImport());
274  if (aGraphicAny.has<uno::Reference<graphic::XGraphic>>())
275  {
276  auto xGraphic = aGraphicAny.get<uno::Reference<graphic::XGraphic>>();
277  uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
278  if (xBitmap.is())
279  rAny <<= xBitmap;
280  }
281  }
282  catch (const Exception&)
283  {
284  TOOLS_WARN_EXCEPTION("svx", "");
285  }
286 }
287 
288 
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),
294  mrTable( rTable )
295 {
296  SetGraphicStorageHandler(xGraphicStorageHandler);
297 
302 
305 
306  // OOo namespaces for reading OOo 1.1 files
307  GetNamespaceMap().Add( "___office",
310  GetNamespaceMap().Add( "___draw",
313 }
314 
316 {
317 }
318 
319 static void openStorageStream( xml::sax::InputSource *pParserInput,
320  rtl::Reference<SvXMLGraphicHelper>& rxGraphicHelper,
321  const uno::Reference < embed::XStorage >& xStorage )
322 {
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 );
326 }
327 
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
332 {
333  bool bRet = true;
334  rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
335 
336  INetURLObject aURLObj( rPath );
337  bool bUseStorage = aURLObj.GetProtocol() == INetProtocol::NotValid; // a relative path
338 
339  try
340  {
341  uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
342 
343  xml::sax::InputSource aParserInput;
345 
346  if( !bUseStorage || !xStorage.is() )
347  {
348  SfxMedium aMedium( rPath, rReferer, StreamMode::READ | StreamMode::NOCREATE );
349  aParserInput.sSystemId = aMedium.GetName();
350 
351  if( aMedium.IsStorage() )
352  {
353  uno::Reference < embed::XStorage > xMediumStorage( aMedium.GetStorage( false ), uno::UNO_SET_THROW );
354  openStorageStream( &aParserInput, xGraphicHelper, xMediumStorage );
355  }
356  else
357  aParserInput.aInputStream = aMedium.GetInputStream();
358  }
359  else // relative URL into a storage
360  {
361  uno::Reference< embed::XStorage > xSubStorage;
362  try
363  {
365  xStorage, rPath, embed::ElementModes::READ, aNasty );
366  }
367  catch (const uno::Exception&)
368  {
369  }
370  if( xSubStorage.is() )
371  openStorageStream( &aParserInput, xGraphicHelper, xSubStorage );
372  else
373  {
374  css::uno::Reference< css::io::XStream > xStream = comphelper::OStorageHelper::GetStreamAtPath(
375  xStorage, rPath, embed::ElementModes::READ, aNasty );
376  if( !xStream.is() )
377  return false;
378  aParserInput.aInputStream = xStream->getInputStream();
379  }
380  if( bOptLoadedFromStorage )
381  *bOptLoadedFromStorage = true;
382  }
383 
384  uno::Reference<XGraphicStorageHandler> xGraphicStorageHandler;
385  if (xGraphicHelper.is())
386  xGraphicStorageHandler = xGraphicHelper.get();
387 
388  try
389  {
390  uno::Reference< io::XSeekable > xSeek( aParserInput.aInputStream, uno::UNO_QUERY_THROW );
391  xSeek->seek( 0 );
392  }
393  catch (const uno::Exception&)
394  {
395  }
396 
397  rtl::Reference<SvxXMLXTableImport> xImport(new SvxXMLXTableImport(xContext, xTable, xGraphicStorageHandler));
398  xImport->parseStream( aParserInput );
399 
400  if( xGraphicHelper )
401  xGraphicHelper->dispose();
402  }
403  catch (...)
404  {
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 ...
408  bRet = false;
409  }
410 
411  return bRet;
412 }
413 
415  const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
416 {
417  if( IsTokenInNamespace(nElement, XML_NAMESPACE_OOO) ||
420  {
421  bool bOOoFormat = IsTokenInNamespace(nElement, XML_NAMESPACE_OFFICE) ||
423  Type aType = mrTable->getElementType();
424  sal_Int32 nToken = nElement & TOKEN_MASK;
425 
426  if ( nToken == XML_COLOR_TABLE )
427  {
428  if( aType == ::cppu::UnoType<sal_Int32>::get() )
429  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Color, mrTable, bOOoFormat );
430  }
431  else if ( nToken == XML_MARKER_TABLE )
432  {
434  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Marker, mrTable, bOOoFormat );
435  }
436  else if ( nToken == XML_DASH_TABLE )
437  {
439  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Dash, mrTable, bOOoFormat );
440  }
441  else if ( nToken == XML_HATCH_TABLE )
442  {
443  if( aType == cppu::UnoType<drawing::Hatch>::get())
444  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Hatch, mrTable, bOOoFormat );
445  }
446  else if ( nToken == XML_GRADIENT_TABLE )
447  {
448  if( aType == cppu::UnoType<awt::Gradient>::get())
449  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Gradient, mrTable, bOOoFormat );
450  }
451  else if ( nToken == XML_BITMAP_TABLE )
452  {
453  if( aType == ::cppu::UnoType<awt::XBitmap>::get())
454  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Bitmap, mrTable, bOOoFormat );
455  }
456  }
457 
458  return nullptr;
459 }
460 
461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
XML_HATCH_TABLE
constexpr sal_uInt16 XML_NAMESPACE_OFFICE_OOO
XML_NP_DRAW
XML_N_OOO
XML_N_DRAW
const OUString & GetName() const
constexpr sal_uInt16 XML_NAMESPACE_XLINK
constexpr sal_uInt16 XML_NAMESPACE_OOO
SvXMLNamespaceMap & GetNamespaceMap()
XML_MARKER_TABLE
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
XML_N_OFFICE_OOO
NONE
bool IsStorage()
Reference< XInputStream > xStream
XML_COLOR
SvXMLImportFlags
XML_NP_OOO
SvxXMLTableImportContextEnum
Definition: xmlxtimp.cxx:62
#define XMLOFF_WARN_UNKNOWN(area, rIter)
SvxXMLXTableImport(const css::uno::Reference< css::uno::XComponentContext > &rContext, const css::uno::Reference< css::container::XNameContainer > &rTable, css::uno::Reference< css::document::XGraphicStorageHandler > const &rxGraphicStorageHandler)
Definition: xmlxtimp.cxx:289
constexpr sal_uInt16 XML_NAMESPACE_DRAW
void SetGraphicStorageHandler(css::uno::Reference< css::document::XGraphicStorageHandler > const &rxGraphicStorageHandler)
#define DBG_UNHANDLED_EXCEPTION(...)
#define TOOLS_WARN_EXCEPTION(area, stream)
XML_N_XLINK
XML_NP_XLINK
XML_N_OFFICE
static bool convertColor(sal_Int32 &rColor, std::u16string_view rValue)
css::uno::Reference< css::io::XInputStream > const & GetInputStream()
const css::uno::Reference< css::container::XNameContainer > & mrTable
Definition: xmlxtimp.hxx:50
XMLOFF_DLLPUBLIC bool importXML(css::uno::Reference< css::xml::sax::XFastAttributeList > const &xAttrList, css::uno::Any &rValue, OUString &rStrName, SvXMLImport &rImport)
XML_N_DRAW_OOO
virtual ~SvxXMLXTableImport() noexcept override
Definition: xmlxtimp.cxx:315
static bool load(const OUString &rPath, const OUString &rReferer, const css::uno::Reference< css::embed::XStorage > &xStorage, const css::uno::Reference< css::container::XNameContainer > &xTable, bool *bOptLoadedFromStorage) noexcept
Definition: xmlxtimp.cxx:328
DefTokenId nToken
static void openStorageStream(xml::sax::InputSource *pParserInput, rtl::Reference< SvXMLGraphicHelper > &rxGraphicHelper, const uno::Reference< embed::XStorage > &xStorage)
Definition: xmlxtimp.cxx:319
css::uno::Reference< css::embed::XStorage > GetStorage(bool bCreateTempFile=true)
constexpr bool IsTokenInNamespace(sal_Int32 nToken, sal_uInt16 nNamespacePrefix)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
XML_DASH_TABLE
OUString aName
XML_GRADIENT_TABLE
INetProtocol GetProtocol() const
#define XML_ELEMENT(prefix, name)
sal_uInt16 Add(const OUString &rPrefix, const OUString &rName, sal_uInt16 nKey=XML_NAMESPACE_UNKNOWN)
Reference< XComponentContext > getProcessComponentContext()
XML_BITMAP_TABLE
constexpr sal_Int32 TOKEN_MASK
static rtl::Reference< SvXMLGraphicHelper > Create(const css::uno::Reference< css::embed::XStorage > &rXMLStorage, SvXMLGraphicHelperMode eCreateMode)
static css::uno::Reference< css::embed::XStorage > GetStorageAtPath(const css::uno::Reference< css::embed::XStorage > &xStorage, const OUString &aPath, sal_uInt32 nOpenMode, LifecycleProxy const &rNastiness)
XML_NP_OFFICE
XML_COLOR_TABLE
static css::uno::Reference< css::io::XStream > GetStreamAtPath(const css::uno::Reference< css::embed::XStorage > &xStorage, const OUString &aPath, sal_uInt32 nOpenMode, LifecycleProxy const &rNastiness)
sal_uInt16 nPos
OUString toString(OptionInfo const *info)
XML_NAME
virtual SvXMLImportContext * CreateFastContext(sal_Int32 Element, const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList > &xAttrList) override
Definition: xmlxtimp.cxx:414