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/xmlnmspe.hxx>
36 #include <xmloff/nmspmap.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  void importColor( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
80  void importMarker( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
81  void importDash( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
82  void importHatch( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
83  void importGradient( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
84  void importBitmap( const uno::Reference< XAttributeList >& 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  sal_Int32 nNamespace = nElement & NMSP_MASK;
105  if( NAMESPACE_TOKEN(XML_NAMESPACE_DRAW) == nNamespace ||
106  NAMESPACE_TOKEN(XML_NAMESPACE_DRAW_OOO) == nNamespace )
107  {
108  sax_fastparser::FastAttributeList *pFastAttribList =
110  SvXMLAttributeList *pAttrList = new SvXMLAttributeList;
111  for (auto& aIter : *pFastAttribList)
112  pAttrList->AddAttribute(
113  SvXMLImport::getNamespacePrefixFromToken(aIter.getToken(), nullptr) + ":" +
114  GetXMLToken(static_cast<XMLTokenEnum>(aIter.getToken() & TOKEN_MASK)),
115  aIter.toString());
116  if( mbOOoFormat &&
117  (SvxXMLTableImportContextEnum::Dash == meContext || SvxXMLTableImportContextEnum::Hatch == meContext ||
118  SvxXMLTableImportContextEnum::Bitmap == meContext) )
119  {
120  sal_Int16 nAttrCount = pAttrList->getLength();
121  for( sal_Int16 i=0; i < nAttrCount; i++ )
122  {
123  const OUString& rAttrName = pAttrList->getNameByIndex( i );
124  OUString aLocalName;
125  sal_uInt16 nPrefix_ =
126  GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
127  &aLocalName );
128  if( XML_NAMESPACE_XLINK == nPrefix_ &&
129  SvxXMLTableImportContextEnum::Bitmap == meContext &&
130  IsXMLToken( aLocalName, XML_HREF ) )
131  {
132  const OUString rValue = pAttrList->getValueByIndex( i );
133  if( !rValue.isEmpty() && '#' == rValue[0] )
134  pAttrList->SetValueByIndex( i, rValue.copy( 1 ) );
135  }
136  else if( (XML_NAMESPACE_DRAW == nPrefix_ || XML_NAMESPACE_DRAW_OOO == nPrefix_) &&
137  ( ( SvxXMLTableImportContextEnum::Dash == meContext &&
138  (IsXMLToken( aLocalName, XML_DOTS1_LENGTH ) ||
139  IsXMLToken( aLocalName, XML_DOTS2_LENGTH ) ||
140  IsXMLToken( aLocalName, XML_DISTANCE )) ) ||
141  ( SvxXMLTableImportContextEnum::Hatch == meContext &&
142  IsXMLToken( aLocalName, XML_DISTANCE ) ) ) )
143  {
144  const OUString rValue = pAttrList->getValueByIndex( i );
145  sal_Int32 nPos = rValue.getLength();
146  while( nPos && rValue[nPos-1] <= ' ' )
147  --nPos;
148  if( nPos > 2 &&
149  ('c'==rValue[nPos-2] || 'C'==rValue[nPos-2]) &&
150  ('h'==rValue[nPos-1] || 'H'==rValue[nPos-1]) )
151  {
152  pAttrList->SetValueByIndex( i, rValue.copy( 0, nPos-2 ) );
153  }
154  }
155  }
156  }
157  try
158  {
159  Any aAny;
160  OUString aName;
161 
162  switch( meContext )
163  {
164  case SvxXMLTableImportContextEnum::Color:
165  importColor( pAttrList, aAny, aName );
166  break;
167  case SvxXMLTableImportContextEnum::Marker:
168  importMarker( pAttrList, aAny, aName );
169  break;
170  case SvxXMLTableImportContextEnum::Dash:
171  importDash( pAttrList, aAny, aName );
172  break;
173  case SvxXMLTableImportContextEnum::Hatch:
174  importHatch( pAttrList, aAny, aName );
175  break;
176  case SvxXMLTableImportContextEnum::Gradient:
177  importGradient( pAttrList, aAny, aName );
178  break;
179  case SvxXMLTableImportContextEnum::Bitmap:
180  importBitmap( pAttrList, aAny, aName );
181  break;
182  }
183 
184  if( !aName.isEmpty() && aAny.hasValue() )
185  {
186  if( mxTable->hasByName( aName ) )
187  {
188  mxTable->replaceByName( aName, aAny );
189  }
190  else
191  {
192  mxTable->insertByName( aName, aAny );
193  }
194  }
195  }
196  catch (const uno::Exception&)
197  {
199  }
200  return new SvXMLImportContext( GetImport() );
201  }
202  return nullptr;
203 }
204 
205 void SvxXMLTableImportContext::importColor( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
206 {
207  const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
208  for( sal_Int16 i=0; i < nAttrCount; i++ )
209  {
210  const OUString& rFullAttrName = xAttrList->getNameByIndex( i );
211  OUString aLocalName;
212  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rFullAttrName, &aLocalName );
213 
214 
215  if( XML_NAMESPACE_DRAW == nPrefix || XML_NAMESPACE_DRAW_OOO == nPrefix )
216  {
217  if( aLocalName == GetXMLToken(XML_NAME) )
218  {
219  rName = xAttrList->getValueByIndex( i );
220  }
221  else if( aLocalName == GetXMLToken(XML_COLOR) )
222  {
223  sal_Int32 nColor(0);
225  xAttrList->getValueByIndex( i ));
226  rAny <<= nColor;
227  }
228  }
229  }
230 }
231 
232 void SvxXMLTableImportContext::importMarker( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
233 {
234  try
235  {
236  XMLMarkerStyleImport aMarkerStyle( GetImport() );
237  aMarkerStyle.importXML( xAttrList, rAny, rName );
238  }
239  catch (const Exception&)
240  {
241  OSL_FAIL("SvxXMLTableImportContext::importMarker(), exception caught!");
242  }
243 }
244 
245 void SvxXMLTableImportContext::importDash( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
246 {
247  try
248  {
249  XMLDashStyleImport aDashStyle( GetImport() );
250  aDashStyle.importXML( xAttrList, rAny, rName );
251  }
252  catch (const Exception&)
253  {
254  OSL_FAIL("SvxXMLTableImportContext::importDash(), exception caught!");
255  }
256 }
257 
258 void SvxXMLTableImportContext::importHatch( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
259 {
260  try
261  {
262  XMLHatchStyleImport aHatchStyle( GetImport() );
263  aHatchStyle.importXML( xAttrList, rAny, rName );
264  }
265  catch (const Exception&)
266  {
267  OSL_FAIL("SvxXMLTableImportContext::importHatch(), exception caught!");
268  }
269 }
270 
271 void SvxXMLTableImportContext::importGradient( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
272 {
273  try
274  {
275  XMLGradientStyleImport aGradientStyle( GetImport() );
276  aGradientStyle.importXML( xAttrList, rAny, rName );
277  }
278  catch (const Exception&)
279  {
280  OSL_FAIL("SvxXMLTableImportContext::importGradient(), exception caught!");
281  }
282 }
283 
284 void SvxXMLTableImportContext::importBitmap( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
285 {
286  try
287  {
288  uno::Any aGraphicAny;
289  XMLImageStyle::importXML(xAttrList, aGraphicAny, rName, GetImport());
290  if (aGraphicAny.has<uno::Reference<graphic::XGraphic>>())
291  {
292  auto xGraphic = aGraphicAny.get<uno::Reference<graphic::XGraphic>>();
293  uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
294  if (xBitmap.is())
295  rAny <<= xBitmap;
296  }
297  }
298  catch (const Exception&)
299  {
300  OSL_FAIL("SvxXMLTableImportContext::importBitmap(), exception caught!");
301  }
302 }
303 
304 
306  const css::uno::Reference< css::uno::XComponentContext >& rContext,
307  const uno::Reference< XNameContainer > & rTable,
308  uno::Reference<XGraphicStorageHandler> const & xGraphicStorageHandler)
309 : SvXMLImport(rContext, "", SvXMLImportFlags::NONE),
310  mrTable( rTable )
311 {
312  SetGraphicStorageHandler(xGraphicStorageHandler);
313 
318 
321 
322  // OOo namespaces for reading OOo 1.1 files
323  GetNamespaceMap().Add( "___office",
326  GetNamespaceMap().Add( "___draw",
329 }
330 
332 {
333 }
334 
335 static void openStorageStream( xml::sax::InputSource *pParserInput,
336  rtl::Reference<SvXMLGraphicHelper>& rxGraphicHelper,
337  const uno::Reference < embed::XStorage >& xStorage )
338 {
339  uno::Reference < io::XStream > xIStm( xStorage->openStreamElement( "Content.xml", embed::ElementModes::READ ), uno::UNO_SET_THROW );
340  pParserInput->aInputStream = xIStm->getInputStream();
341  rxGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Read );
342 }
343 
344 bool SvxXMLXTableImport::load( const OUString &rPath, const OUString &rReferer,
345  const uno::Reference < embed::XStorage > &xStorage,
346  const uno::Reference< XNameContainer >& xTable,
347  bool *bOptLoadedFromStorage ) throw()
348 {
349  bool bRet = true;
350  rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
351 
352  INetURLObject aURLObj( rPath );
353  bool bUseStorage = aURLObj.GetProtocol() == INetProtocol::NotValid; // a relative path
354 
355  try
356  {
357  uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
358 
359  xml::sax::InputSource aParserInput;
361 
362  if( !bUseStorage || !xStorage.is() )
363  {
364  SfxMedium aMedium( rPath, rReferer, StreamMode::READ | StreamMode::NOCREATE );
365  aParserInput.sSystemId = aMedium.GetName();
366 
367  if( aMedium.IsStorage() )
368  {
369  uno::Reference < embed::XStorage > xMediumStorage( aMedium.GetStorage( false ), uno::UNO_SET_THROW );
370  openStorageStream( &aParserInput, xGraphicHelper, xMediumStorage );
371  }
372  else
373  aParserInput.aInputStream = aMedium.GetInputStream();
374  }
375  else // relative URL into a storage
376  {
377  uno::Reference< embed::XStorage > xSubStorage;
378  try
379  {
381  xStorage, rPath, embed::ElementModes::READ, aNasty );
382  }
383  catch (const uno::Exception&)
384  {
385  }
386  if( xSubStorage.is() )
387  openStorageStream( &aParserInput, xGraphicHelper, xSubStorage );
388  else
389  {
390  css::uno::Reference< css::io::XStream > xStream = comphelper::OStorageHelper::GetStreamAtPath(
391  xStorage, rPath, embed::ElementModes::READ, aNasty );
392  if( !xStream.is() )
393  return false;
394  aParserInput.aInputStream = xStream->getInputStream();
395  }
396  if( bOptLoadedFromStorage )
397  *bOptLoadedFromStorage = true;
398  }
399 
400  uno::Reference<XGraphicStorageHandler> xGraphicStorageHandler;
401  if (xGraphicHelper.is())
402  xGraphicStorageHandler = xGraphicHelper.get();
403 
404  try
405  {
406  uno::Reference< io::XSeekable > xSeek( aParserInput.aInputStream, uno::UNO_QUERY_THROW );
407  xSeek->seek( 0 );
408  }
409  catch (const uno::Exception&)
410  {
411  }
412 
413  rtl::Reference<SvxXMLXTableImport> xImport(new SvxXMLXTableImport(xContext, xTable, xGraphicStorageHandler));
414  xImport->parseStream( aParserInput );
415 
416  if( xGraphicHelper )
417  xGraphicHelper->dispose();
418  }
419  catch (...)
420  {
421 // thrown each time you load a document with property tables that are not
422 // on the current machine. FIXME: would be better to check a file exists
423 // before importing ...
424  bRet = false;
425  }
426 
427  return bRet;
428 }
429 
431  const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
432 {
433  sal_Int32 nNamespace = nElement & NMSP_MASK;
434  if( NAMESPACE_TOKEN(XML_NAMESPACE_OOO) == nNamespace ||
435  NAMESPACE_TOKEN(XML_NAMESPACE_OFFICE) == nNamespace ||
437  {
438  bool bOOoFormat = (NAMESPACE_TOKEN(XML_NAMESPACE_OFFICE) == nNamespace) ||
439  (NAMESPACE_TOKEN(XML_NAMESPACE_OFFICE_OOO) == nNamespace);
440  Type aType = mrTable->getElementType();
441  sal_Int32 nToken = nElement & TOKEN_MASK;
442 
443  if ( nToken == XML_COLOR_TABLE )
444  {
445  if( aType == ::cppu::UnoType<sal_Int32>::get() )
446  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Color, mrTable, bOOoFormat );
447  }
448  else if ( nToken == XML_MARKER_TABLE )
449  {
451  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Marker, mrTable, bOOoFormat );
452  }
453  else if ( nToken == XML_DASH_TABLE )
454  {
456  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Dash, mrTable, bOOoFormat );
457  }
458  else if ( nToken == XML_HATCH_TABLE )
459  {
460  if( aType == cppu::UnoType<drawing::Hatch>::get())
461  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Hatch, mrTable, bOOoFormat );
462  }
463  else if ( nToken == XML_GRADIENT_TABLE )
464  {
465  if( aType == cppu::UnoType<awt::Gradient>::get())
466  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Gradient, mrTable, bOOoFormat );
467  }
468  else if ( nToken == XML_BITMAP_TABLE )
469  {
470  if( aType == ::cppu::UnoType<awt::XBitmap>::get())
471  return new SvxXMLTableImportContext( *this, SvxXMLTableImportContextEnum::Bitmap, mrTable, bOOoFormat );
472  }
473  }
474 
475  return nullptr;
476 }
477 
478 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
XML_DASH_TABLE
#define NAMESPACE_TOKEN(prefixToken)
const OUString & GetName() const
SvXMLNamespaceMap & GetNamespaceMap()
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:344
XML_HATCH_TABLE
NONE
css::uno::Any const & rValue
bool IsStorage()
Reference< XInputStream > xStream
virtual ~SvxXMLXTableImport() override
Definition: xmlxtimp.cxx:331
SvXMLImportFlags
XML_N_DRAW_OOO
SvxXMLTableImportContextEnum
Definition: xmlxtimp.cxx:63
XML_NP_XLINK
XML_NP_OFFICE
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:305
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
constexpr sal_uInt16 XML_NAMESPACE_OFFICE_OOO
int i
XML_NP_DRAW
XML_MARKER_TABLE
XML_GRADIENT_TABLE
virtual sal_Int16 SAL_CALL getLength() override
static FastAttributeList * castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
constexpr sal_uInt16 XML_NAMESPACE_OOO
static OUString getNamespacePrefixFromToken(sal_Int32 nToken, const SvXMLNamespaceMap *pMap)
XML_N_OFFICE_OOO
const sal_Int32 TOKEN_MASK
css::uno::Reference< css::io::XInputStream > const & GetInputStream()
const css::uno::Reference< css::container::XNameContainer > & mrTable
Definition: xmlxtimp.hxx:52
XML_COLOR_TABLE
constexpr sal_uInt16 XML_NAMESPACE_XLINK
DefTokenId nToken
static void openStorageStream(xml::sax::InputSource *pParserInput, rtl::Reference< SvXMLGraphicHelper > &rxGraphicHelper, const uno::Reference< embed::XStorage > &xStorage)
Definition: xmlxtimp.cxx:335
css::uno::Reference< css::embed::XStorage > GetStorage(bool bCreateTempFile=true)
const sal_Int32 NMSP_MASK
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
static bool convertColor(sal_Int32 &rColor, const OUString &rValue)
XML_N_XLINK
OUString aName
INetProtocol GetProtocol() const
OReadImagesDocumentHandler::Image_XML_Namespace nNamespace
sal_uInt16 Add(const OUString &rPrefix, const OUString &rName, sal_uInt16 nKey=XML_NAMESPACE_UNKNOWN)
Reference< XComponentContext > getProcessComponentContext()
void SetValueByIndex(sal_Int16 i, const OUString &rValue)
void AddAttribute(const OUString &sName, const OUString &sValue)
virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) override
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)
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
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
virtual SvXMLImportContext * CreateFastContext(sal_Int32 Element, const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList > &xAttrList) override
Definition: xmlxtimp.cxx:430
virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) override