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 #include <xmloff/attrlist.hxx>
47 
48 #include <xmlxtimp.hxx>
49 #include <tools/diagnose_ex.h>
50 
51 using namespace com::sun::star;
52 using namespace com::sun::star::container;
53 using namespace com::sun::star::document;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::awt;
56 using namespace com::sun::star::lang;
57 using namespace com::sun::star::xml::sax;
58 using namespace ::xmloff::token;
59 using namespace cppu;
60 
61 namespace {
62 
64 
65 class SvxXMLTableImportContext : public SvXMLImportContext
66 {
67 public:
68  SvxXMLTableImportContext( SvXMLImport& rImport, SvxXMLTableImportContextEnum eContext, const uno::Reference< XNameContainer >& xTable,
69  bool bOOoFormat );
70 
71  virtual void SAL_CALL startFastElement( sal_Int32 /*nElement*/,
72  const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) override {}
73 
74  virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
75  createFastChildContext(sal_Int32 Element,
76  const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) override;
77 
78 protected:
79  static void importColor( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName );
80  void importMarker( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName );
81  void importDash( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName );
82  void importHatch( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName );
83  void importGradient( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName );
84  void importBitmap( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName );
85 
86 private:
87  uno::Reference< XNameContainer > mxTable;
89  bool mbOOoFormat;
90 };
91 
92 }
93 
94 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport& rImport, SvxXMLTableImportContextEnum eContext, const uno::Reference< XNameContainer >& xTable, bool bOOoFormat )
95 : SvXMLImportContext( rImport ), mxTable( xTable ), meContext( eContext ),
96  mbOOoFormat( bOOoFormat )
97 {
98 }
99 
100 css::uno::Reference< css::xml::sax::XFastContextHandler >
101  SvxXMLTableImportContext::createFastChildContext(sal_Int32 nElement,
102  const css::uno::Reference< css::xml::sax::XFastAttributeList > & rAttrList)
103 {
104  if( !(IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) ||
105  IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW_OOO) ))
106  return nullptr;
107 
108  std::vector<std::pair<sal_Int32, OString>> aTmpAttrList;
109  for (auto& aIter : sax_fastparser::castToFastAttributeList( rAttrList ))
110  aTmpAttrList.push_back({aIter.getToken(), OString(aIter.toCString())});
111  if( mbOOoFormat &&
112  (SvxXMLTableImportContextEnum::Dash == meContext || SvxXMLTableImportContextEnum::Hatch == meContext ||
113  SvxXMLTableImportContextEnum::Bitmap == meContext) )
114  {
115  for( auto & aIter : aTmpAttrList )
116  {
117  sal_Int32 aLocalAttr = aIter.first & TOKEN_MASK;
118  if( aIter.first == XML_ELEMENT(XLINK, XML_HREF) &&
119  SvxXMLTableImportContextEnum::Bitmap == meContext )
120  {
121  OString rValue = aIter.second;
122  if( !rValue.isEmpty() && '#' == rValue[0] )
123  rValue = rValue.copy( 1 );
124  }
125  else if( (IsTokenInNamespace(aIter.first, XML_NAMESPACE_DRAW) || IsTokenInNamespace(aIter.first, XML_NAMESPACE_DRAW_OOO)) &&
126  ( ( SvxXMLTableImportContextEnum::Dash == meContext &&
127  ( aLocalAttr == XML_DOTS1_LENGTH ||
128  aLocalAttr == XML_DOTS2_LENGTH ||
129  aLocalAttr == XML_DISTANCE ) ) ||
130  ( SvxXMLTableImportContextEnum::Hatch == meContext &&
131  ( aLocalAttr == XML_DISTANCE ) ) ) )
132  {
133  OString& rValue = aIter.second;
134  sal_Int32 nPos = rValue.getLength();
135  while( nPos && rValue[nPos-1] <= ' ' )
136  --nPos;
137  if( nPos > 2 &&
138  ('c'==rValue[nPos-2] || 'C'==rValue[nPos-2]) &&
139  ('h'==rValue[nPos-1] || 'H'==rValue[nPos-1]) )
140  {
141  rValue = rValue.copy( 0, nPos-2 );
142  }
143  }
144  }
145  }
146  try
147  {
149  for (auto& aIter : aTmpAttrList)
150  xFastList->add(aIter.first, aIter.second);
151 
152  Any aAny;
153  OUString aName;
154 
155  switch( meContext )
156  {
157  case SvxXMLTableImportContextEnum::Color:
158  importColor( xFastList.get(), aAny, aName );
159  break;
160  case SvxXMLTableImportContextEnum::Marker:
161  importMarker( xFastList.get(), aAny, aName );
162  break;
163  case SvxXMLTableImportContextEnum::Dash:
164  importDash( xFastList.get(), aAny, aName );
165  break;
166  case SvxXMLTableImportContextEnum::Hatch:
167  importHatch( xFastList.get(), aAny, aName );
168  break;
169  case SvxXMLTableImportContextEnum::Gradient:
170  importGradient( xFastList.get(), aAny, aName );
171  break;
172  case SvxXMLTableImportContextEnum::Bitmap:
173  importBitmap( xFastList.get(), aAny, aName );
174  break;
175  }
176 
177  if( !aName.isEmpty() && aAny.hasValue() )
178  {
179  if( mxTable->hasByName( aName ) )
180  {
181  mxTable->replaceByName( aName, aAny );
182  }
183  else
184  {
185  mxTable->insertByName( aName, aAny );
186  }
187  }
188  }
189  catch (const uno::Exception&)
190  {
192  }
193  return new SvXMLImportContext( GetImport() );
194 }
195 
196 void SvxXMLTableImportContext::importColor( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
197 {
198  for (auto& aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
199  {
200  switch (aIter.getToken())
201  {
202  case XML_ELEMENT(DRAW, XML_NAME):
203  case XML_ELEMENT(DRAW_OOO, XML_NAME):
204  rName = aIter.toString();
205  break;
206  case XML_ELEMENT(DRAW, XML_COLOR):
207  case XML_ELEMENT(DRAW_OOO, XML_COLOR):
208  {
209  sal_Int32 nColor(0);
210  ::sax::Converter::convertColor(nColor, aIter.toString());
211  rAny <<= nColor;
212  break;
213  }
214  default:
215  SAL_WARN("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << "=" << aIter.toString());
216  }
217  }
218 }
219 
220 void SvxXMLTableImportContext::importMarker( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
221 {
222  try
223  {
224  XMLMarkerStyleImport aMarkerStyle( GetImport() );
225  aMarkerStyle.importXML( xAttrList, rAny, rName );
226  }
227  catch (const Exception&)
228  {
229  OSL_FAIL("SvxXMLTableImportContext::importMarker(), exception caught!");
230  }
231 }
232 
233 void SvxXMLTableImportContext::importDash( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
234 {
235  try
236  {
237  XMLDashStyleImport aDashStyle( GetImport() );
238  aDashStyle.importXML( xAttrList, rAny, rName );
239  }
240  catch (const Exception&)
241  {
242  OSL_FAIL("SvxXMLTableImportContext::importDash(), exception caught!");
243  }
244 }
245 
246 void SvxXMLTableImportContext::importHatch( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
247 {
248  try
249  {
250  XMLHatchStyleImport aHatchStyle( GetImport() );
251  aHatchStyle.importXML( xAttrList, rAny, rName );
252  }
253  catch (const Exception&)
254  {
255  OSL_FAIL("SvxXMLTableImportContext::importHatch(), exception caught!");
256  }
257 }
258 
259 void SvxXMLTableImportContext::importGradient( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
260 {
261  try
262  {
263  XMLGradientStyleImport aGradientStyle( GetImport() );
264  aGradientStyle.importXML( xAttrList, rAny, rName );
265  }
266  catch (const Exception&)
267  {
268  OSL_FAIL("SvxXMLTableImportContext::importGradient(), exception caught!");
269  }
270 }
271 
272 void SvxXMLTableImportContext::importBitmap( const uno::Reference< XFastAttributeList >& xAttrList, Any& rAny, OUString& rName )
273 {
274  try
275  {
276  uno::Any aGraphicAny;
277  XMLImageStyle::importXML(xAttrList, aGraphicAny, rName, GetImport());
278  if (aGraphicAny.has<uno::Reference<graphic::XGraphic>>())
279  {
280  auto xGraphic = aGraphicAny.get<uno::Reference<graphic::XGraphic>>();
281  uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
282  if (xBitmap.is())
283  rAny <<= xBitmap;
284  }
285  }
286  catch (const Exception&)
287  {
288  OSL_FAIL("SvxXMLTableImportContext::importBitmap(), exception caught!");
289  }
290 }
291 
292 
294  const css::uno::Reference< css::uno::XComponentContext >& rContext,
295  const uno::Reference< XNameContainer > & rTable,
296  uno::Reference<XGraphicStorageHandler> const & xGraphicStorageHandler)
297 : SvXMLImport(rContext, "", SvXMLImportFlags::NONE),
298  mrTable( rTable )
299 {
300  SetGraphicStorageHandler(xGraphicStorageHandler);
301 
306 
309 
310  // OOo namespaces for reading OOo 1.1 files
311  GetNamespaceMap().Add( "___office",
314  GetNamespaceMap().Add( "___draw",
317 }
318 
320 {
321 }
322 
323 static void openStorageStream( xml::sax::InputSource *pParserInput,
324  rtl::Reference<SvXMLGraphicHelper>& rxGraphicHelper,
325  const uno::Reference < embed::XStorage >& xStorage )
326 {
327  uno::Reference < io::XStream > xIStm( xStorage->openStreamElement( "Content.xml", embed::ElementModes::READ ), uno::UNO_SET_THROW );
328  pParserInput->aInputStream = xIStm->getInputStream();
329  rxGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Read );
330 }
331 
332 bool SvxXMLXTableImport::load( const OUString &rPath, const OUString &rReferer,
333  const uno::Reference < embed::XStorage > &xStorage,
334  const uno::Reference< XNameContainer >& xTable,
335  bool *bOptLoadedFromStorage ) throw()
336 {
337  bool bRet = true;
338  rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
339 
340  INetURLObject aURLObj( rPath );
341  bool bUseStorage = aURLObj.GetProtocol() == INetProtocol::NotValid; // a relative path
342 
343  try
344  {
345  uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
346 
347  xml::sax::InputSource aParserInput;
349 
350  if( !bUseStorage || !xStorage.is() )
351  {
352  SfxMedium aMedium( rPath, rReferer, StreamMode::READ | StreamMode::NOCREATE );
353  aParserInput.sSystemId = aMedium.GetName();
354 
355  if( aMedium.IsStorage() )
356  {
357  uno::Reference < embed::XStorage > xMediumStorage( aMedium.GetStorage( false ), uno::UNO_SET_THROW );
358  openStorageStream( &aParserInput, xGraphicHelper, xMediumStorage );
359  }
360  else
361  aParserInput.aInputStream = aMedium.GetInputStream();
362  }
363  else // relative URL into a storage
364  {
365  uno::Reference< embed::XStorage > xSubStorage;
366  try
367  {
369  xStorage, rPath, embed::ElementModes::READ, aNasty );
370  }
371  catch (const uno::Exception&)
372  {
373  }
374  if( xSubStorage.is() )
375  openStorageStream( &aParserInput, xGraphicHelper, xSubStorage );
376  else
377  {
378  css::uno::Reference< css::io::XStream > xStream = comphelper::OStorageHelper::GetStreamAtPath(
379  xStorage, rPath, embed::ElementModes::READ, aNasty );
380  if( !xStream.is() )
381  return false;
382  aParserInput.aInputStream = xStream->getInputStream();
383  }
384  if( bOptLoadedFromStorage )
385  *bOptLoadedFromStorage = true;
386  }
387 
388  uno::Reference<XGraphicStorageHandler> xGraphicStorageHandler;
389  if (xGraphicHelper.is())
390  xGraphicStorageHandler = xGraphicHelper.get();
391 
392  try
393  {
394  uno::Reference< io::XSeekable > xSeek( aParserInput.aInputStream, uno::UNO_QUERY_THROW );
395  xSeek->seek( 0 );
396  }
397  catch (const uno::Exception&)
398  {
399  }
400 
401  rtl::Reference<SvxXMLXTableImport> xImport(new SvxXMLXTableImport(xContext, xTable, xGraphicStorageHandler));
402  xImport->parseStream( aParserInput );
403 
404  if( xGraphicHelper )
405  xGraphicHelper->dispose();
406  }
407  catch (...)
408  {
409 // thrown each time you load a document with property tables that are not
410 // on the current machine. FIXME: would be better to check a file exists
411 // before importing ...
412  bRet = false;
413  }
414 
415  return bRet;
416 }
417 
419  const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
420 {
421  if( IsTokenInNamespace(nElement, XML_NAMESPACE_OOO) ||
424  {
425  bool bOOoFormat = IsTokenInNamespace(nElement, XML_NAMESPACE_OFFICE) ||
427  Type aType = mrTable->getElementType();
428  sal_Int32 nToken = nElement & TOKEN_MASK;
429 
430  if ( nToken == XML_COLOR_TABLE )
431  {
432  if( aType == ::cppu::UnoType<sal_Int32>::get() )
433  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Color, mrTable, bOOoFormat );
434  }
435  else if ( nToken == XML_MARKER_TABLE )
436  {
438  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Marker, mrTable, bOOoFormat );
439  }
440  else if ( nToken == XML_DASH_TABLE )
441  {
443  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Dash, mrTable, bOOoFormat );
444  }
445  else if ( nToken == XML_HATCH_TABLE )
446  {
447  if( aType == cppu::UnoType<drawing::Hatch>::get())
448  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Hatch, mrTable, bOOoFormat );
449  }
450  else if ( nToken == XML_GRADIENT_TABLE )
451  {
452  if( aType == cppu::UnoType<awt::Gradient>::get())
453  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Gradient, mrTable, bOOoFormat );
454  }
455  else if ( nToken == XML_BITMAP_TABLE )
456  {
457  if( aType == ::cppu::UnoType<awt::XBitmap>::get())
458  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Bitmap, mrTable, bOOoFormat );
459  }
460  }
461 
462  return nullptr;
463 }
464 
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
constexpr sal_uInt16 XML_NAMESPACE_OFFICE_OOO
XML_NAME
XML_DASH_TABLE
const OUString & GetName() const
constexpr sal_uInt16 XML_NAMESPACE_XLINK
constexpr sal_uInt16 XML_NAMESPACE_OOO
SvXMLNamespaceMap & GetNamespaceMap()
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
XML_N_OOO
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)
Definition: xmlxtimp.cxx:332
XML_HATCH_TABLE
NONE
css::uno::Any const & rValue
bool IsStorage()
Reference< XInputStream > xStream
virtual ~SvxXMLXTableImport() override
Definition: xmlxtimp.cxx:319
SvXMLImportFlags
XML_N_DRAW_OOO
SvxXMLTableImportContextEnum
Definition: xmlxtimp.cxx:63
XML_NP_XLINK
XML_NP_OFFICE
static OUString getPrefixAndNameFromToken(sal_Int32 nToken)
XML_BITMAP_TABLE
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:293
constexpr sal_uInt16 XML_NAMESPACE_DRAW
void SetGraphicStorageHandler(css::uno::Reference< css::document::XGraphicStorageHandler > const &rxGraphicStorageHandler)
XML_N_OFFICE
#define DBG_UNHANDLED_EXCEPTION(...)
XML_N_DRAW
XML_NP_DRAW
XML_MARKER_TABLE
XML_GRADIENT_TABLE
XML_N_OFFICE_OOO
css::uno::Reference< css::io::XInputStream > const & GetInputStream()
const css::uno::Reference< css::container::XNameContainer > & mrTable
Definition: xmlxtimp.hxx:51
XML_COLOR_TABLE
DefTokenId nToken
static void openStorageStream(xml::sax::InputSource *pParserInput, rtl::Reference< SvXMLGraphicHelper > &rxGraphicHelper, const uno::Reference< embed::XStorage > &xStorage)
Definition: xmlxtimp.cxx:323
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)
static bool convertColor(sal_Int32 &rColor, const OUString &rValue)
XML_N_XLINK
OUString aName
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()
#define SAL_WARN(area, stream)
constexpr sal_Int32 TOKEN_MASK
static rtl::Reference< SvXMLGraphicHelper > Create(const css::uno::Reference< css::embed::XStorage > &rXMLStorage, SvXMLGraphicHelperMode eCreateMode)
XML_COLOR
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)
Reference< XGraphic > xGraphic
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)
XML_NP_OOO
sal_uInt16 nPos
OUString toString(OptionInfo const *info)
virtual SvXMLImportContext * CreateFastContext(sal_Int32 Element, const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList > &xAttrList) override
Definition: xmlxtimp.cxx:418