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/io/XActiveDataControl.hpp>
24 #include <com/sun/star/io/XActiveDataSource.hpp>
25 #include <com/sun/star/container/XNameContainer.hpp>
26 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
27 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
28 #include <com/sun/star/drawing/LineDash.hpp>
29 #include <com/sun/star/awt/Gradient.hpp>
30 #include <com/sun/star/awt/XBitmap.hpp>
31 #include <com/sun/star/drawing/Hatch.hpp>
32 #include <com/sun/star/io/XOutputStream.hpp>
33 #include <com/sun/star/io/XSeekable.hpp>
36 #include <unotools/streamwrap.hxx>
37 #include <rtl/ustrbuf.hxx>
38 #include <sax/tools/converter.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <xmloff/xmlnmspe.hxx>
41 #include <xmloff/nmspmap.hxx>
42 
43 #include <xmloff/xmltoken.hxx>
44 #include <xmloff/xmlmetae.hxx>
45 #include <xmloff/DashStyle.hxx>
46 #include <xmloff/GradientStyle.hxx>
47 #include <xmloff/HatchStyle.hxx>
48 #include <xmloff/ImageStyle.hxx>
49 #include <xmloff/MarkerStyle.hxx>
50 #include <xmloff/xmlictxt.hxx>
51 #include <svx/xmlgrhlp.hxx>
52 #include <xmloff/attrlist.hxx>
53 
54 #include <xmlxtimp.hxx>
55 
56 #include <cstdio>
57 
58 using namespace com::sun::star;
59 using namespace com::sun::star::container;
60 using namespace com::sun::star::document;
61 using namespace com::sun::star::uno;
62 using namespace com::sun::star::awt;
63 using namespace com::sun::star::lang;
64 using namespace com::sun::star::xml::sax;
65 using namespace ::xmloff::token;
66 using namespace cppu;
67 
68 namespace {
69 
71 
72 class SvxXMLTableImportContext : public SvXMLImportContext
73 {
74 public:
75  SvxXMLTableImportContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, SvxXMLTableImportContextEnum eContext, const uno::Reference< XNameContainer >& xTable,
76  bool bOOoFormat );
77 
78  virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< XAttributeList >& xAttrList ) override;
79 
80 protected:
81  void importColor( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
82  void importMarker( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
83  void importDash( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
84  void importHatch( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
85  void importGradient( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
86  void importBitmap( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName );
87 
88 private:
89  uno::Reference< XNameContainer > mxTable;
90  SvxXMLTableImportContextEnum const meContext;
91  bool const mbOOoFormat;
92 };
93 
94 }
95 
96 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, SvxXMLTableImportContextEnum eContext, const uno::Reference< XNameContainer >& xTable, bool bOOoFormat )
97 : SvXMLImportContext( rImport, nPrfx, rLName ), mxTable( xTable ), meContext( eContext ),
98  mbOOoFormat( bOOoFormat )
99 {
100 }
101 
102 SvXMLImportContextRef SvxXMLTableImportContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< XAttributeList >& rAttrList )
103 {
104  if( XML_NAMESPACE_DRAW == nPrefix )
105  {
106  uno::Reference< XAttributeList > xAttrList( rAttrList );
107  if( mbOOoFormat &&
108  (SvxXMLTableImportContextEnum::Dash == meContext || SvxXMLTableImportContextEnum::Hatch == meContext ||
109  SvxXMLTableImportContextEnum::Bitmap == meContext) )
110  {
111  SvXMLAttributeList *pAttrList = new SvXMLAttributeList( rAttrList );
112  xAttrList = pAttrList;
113  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
114  for( sal_Int16 i=0; i < nAttrCount; i++ )
115  {
116  const OUString& rAttrName = xAttrList->getNameByIndex( i );
117  OUString aLocalName;
118  sal_uInt16 nPrefix_ =
119  GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
120  &aLocalName );
121  if( XML_NAMESPACE_XLINK == nPrefix_ &&
122  SvxXMLTableImportContextEnum::Bitmap == meContext &&
123  IsXMLToken( aLocalName, XML_HREF ) )
124  {
125  const OUString rValue = xAttrList->getValueByIndex( i );
126  if( !rValue.isEmpty() && '#' == rValue[0] )
127  pAttrList->SetValueByIndex( i, rValue.copy( 1 ) );
128  }
129  else if( XML_NAMESPACE_DRAW == nPrefix_ &&
130  ( ( SvxXMLTableImportContextEnum::Dash == meContext &&
131  (IsXMLToken( aLocalName, XML_DOTS1_LENGTH ) ||
132  IsXMLToken( aLocalName, XML_DOTS2_LENGTH ) ||
133  IsXMLToken( aLocalName, XML_DISTANCE )) ) ||
134  ( SvxXMLTableImportContextEnum::Hatch == meContext &&
135  IsXMLToken( aLocalName, XML_HATCH_DISTANCE ) ) ) )
136  {
137  const OUString rValue = xAttrList->getValueByIndex( i );
138  sal_Int32 nPos = rValue.getLength();
139  while( nPos && rValue[nPos-1] <= ' ' )
140  --nPos;
141  if( nPos > 2 &&
142  ('c'==rValue[nPos-2] || 'C'==rValue[nPos-2]) &&
143  ('h'==rValue[nPos-1] || 'H'==rValue[nPos-1]) )
144  {
145  pAttrList->SetValueByIndex( i, rValue.copy( 0, nPos-2 ) );
146  }
147  }
148  }
149  }
150  try
151  {
152  Any aAny;
153  OUString aName;
154 
155  switch( meContext )
156  {
157  case SvxXMLTableImportContextEnum::Color:
158  importColor( xAttrList, aAny, aName );
159  break;
160  case SvxXMLTableImportContextEnum::Marker:
161  importMarker( xAttrList, aAny, aName );
162  break;
163  case SvxXMLTableImportContextEnum::Dash:
164  importDash( xAttrList, aAny, aName );
165  break;
166  case SvxXMLTableImportContextEnum::Hatch:
167  importHatch( xAttrList, aAny, aName );
168  break;
169  case SvxXMLTableImportContextEnum::Gradient:
170  importGradient( xAttrList, aAny, aName );
171  break;
172  case SvxXMLTableImportContextEnum::Bitmap:
173  importBitmap( xAttrList, 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  {
191  }
192  }
193 
194  return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
195 }
196 
197 void SvxXMLTableImportContext::importColor( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
198 {
199  const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
200  for( sal_Int16 i=0; i < nAttrCount; i++ )
201  {
202  const OUString& rFullAttrName = xAttrList->getNameByIndex( i );
203  OUString aLocalName;
204  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rFullAttrName, &aLocalName );
205 
206 
207  if( XML_NAMESPACE_DRAW == nPrefix )
208  {
209  if( aLocalName == GetXMLToken(XML_NAME) )
210  {
211  rName = xAttrList->getValueByIndex( i );
212  }
213  else if( aLocalName == GetXMLToken(XML_COLOR) )
214  {
215  sal_Int32 nColor(0);
217  xAttrList->getValueByIndex( i ));
218  rAny <<= nColor;
219  }
220  }
221  }
222 }
223 
224 void SvxXMLTableImportContext::importMarker( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
225 {
226  try
227  {
228  XMLMarkerStyleImport aMarkerStyle( GetImport() );
229  aMarkerStyle.importXML( xAttrList, rAny, rName );
230  }
231  catch (const Exception&)
232  {
233  OSL_FAIL("SvxXMLTableImportContext::importMarker(), exception caught!");
234  }
235 }
236 
237 void SvxXMLTableImportContext::importDash( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
238 {
239  try
240  {
241  XMLDashStyleImport aDashStyle( GetImport() );
242  aDashStyle.importXML( xAttrList, rAny, rName );
243  }
244  catch (const Exception&)
245  {
246  OSL_FAIL("SvxXMLTableImportContext::importDash(), exception caught!");
247  }
248 }
249 
250 void SvxXMLTableImportContext::importHatch( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
251 {
252  try
253  {
254  XMLHatchStyleImport aHatchStyle( GetImport() );
255  aHatchStyle.importXML( xAttrList, rAny, rName );
256  }
257  catch (const Exception&)
258  {
259  OSL_FAIL("SvxXMLTableImportContext::importHatch(), exception caught!");
260  }
261 }
262 
263 void SvxXMLTableImportContext::importGradient( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
264 {
265  try
266  {
267  XMLGradientStyleImport aGradientStyle( GetImport() );
268  aGradientStyle.importXML( xAttrList, rAny, rName );
269  }
270  catch (const Exception&)
271  {
272  OSL_FAIL("SvxXMLTableImportContext::importGradient(), exception caught!");
273  }
274 }
275 
276 void SvxXMLTableImportContext::importBitmap( const uno::Reference< XAttributeList >& xAttrList, Any& rAny, OUString& rName )
277 {
278  try
279  {
280  uno::Any aGraphicAny;
281  XMLImageStyle::importXML(xAttrList, aGraphicAny, rName, GetImport());
282  if (aGraphicAny.has<uno::Reference<graphic::XGraphic>>())
283  {
284  auto xGraphic = aGraphicAny.get<uno::Reference<graphic::XGraphic>>();
285  uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
286  if (xBitmap.is())
287  rAny <<= xBitmap;
288  }
289  }
290  catch (const Exception&)
291  {
292  OSL_FAIL("SvxXMLTableImportContext::importBitmap(), exception caught!");
293  }
294 }
295 
296 
298  const css::uno::Reference< css::uno::XComponentContext >& rContext,
299  const uno::Reference< XNameContainer > & rTable,
300  uno::Reference<XGraphicStorageHandler> const & xGraphicStorageHandler)
301 : SvXMLImport(rContext, "", SvXMLImportFlags::NONE),
302  mrTable( rTable )
303 {
304  SetGraphicStorageHandler(xGraphicStorageHandler);
305 
307  GetNamespaceMap().Add( "__office", GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE );
308  GetNamespaceMap().Add( "__draw", GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW );
309  GetNamespaceMap().Add( "__xlink", GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
310 
311  // OOo namespaces for reading OOo 1.1 files
312  GetNamespaceMap().Add( "___office",
314  XML_NAMESPACE_OFFICE );
315  GetNamespaceMap().Add( "___draw",
317  XML_NAMESPACE_DRAW );
318 }
319 
321 {
322 }
323 
324 static void openStorageStream( xml::sax::InputSource *pParserInput,
325  rtl::Reference<SvXMLGraphicHelper>& rxGraphicHelper,
326  const uno::Reference < embed::XStorage >& xStorage )
327 {
328  uno::Reference < io::XStream > xIStm( xStorage->openStreamElement( "Content.xml", embed::ElementModes::READ ), uno::UNO_SET_THROW );
329  pParserInput->aInputStream = xIStm->getInputStream();
330  rxGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Read );
331 }
332 
333 bool SvxXMLXTableImport::load( const OUString &rPath, const OUString &rReferer,
334  const uno::Reference < embed::XStorage > &xStorage,
335  const uno::Reference< XNameContainer >& xTable,
336  bool *bOptLoadedFromStorage ) throw()
337 {
338  bool bRet = true;
339  rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
340 
341  INetURLObject aURLObj( rPath );
342  bool bUseStorage = aURLObj.GetProtocol() == INetProtocol::NotValid; // a relative path
343 
344  try
345  {
346  uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
347 
348  xml::sax::InputSource aParserInput;
350 
351  if( !bUseStorage || !xStorage.is() )
352  {
353  SfxMedium aMedium( rPath, rReferer, StreamMode::READ | StreamMode::NOCREATE );
354  aParserInput.sSystemId = aMedium.GetName();
355 
356  if( aMedium.IsStorage() )
357  {
358  uno::Reference < embed::XStorage > xMediumStorage( aMedium.GetStorage( false ), uno::UNO_SET_THROW );
359  openStorageStream( &aParserInput, xGraphicHelper, xMediumStorage );
360  }
361  else
362  aParserInput.aInputStream = aMedium.GetInputStream();
363  }
364  else // relative URL into a storage
365  {
366  uno::Reference< embed::XStorage > xSubStorage;
367  try
368  {
370  xStorage, rPath, embed::ElementModes::READ, aNasty );
371  }
372  catch (const uno::Exception&)
373  {
374  }
375  if( xSubStorage.is() )
376  openStorageStream( &aParserInput, xGraphicHelper, xSubStorage );
377  else
378  {
379  css::uno::Reference< css::io::XStream > xStream = comphelper::OStorageHelper::GetStreamAtPath(
380  xStorage, rPath, embed::ElementModes::READ, aNasty );
381  if( !xStream.is() )
382  return false;
383  aParserInput.aInputStream = xStream->getInputStream();
384  }
385  if( bOptLoadedFromStorage )
386  *bOptLoadedFromStorage = true;
387  }
388 
389  uno::Reference<XGraphicStorageHandler> xGraphicStorageHandler;
390  if (xGraphicHelper.is())
391  xGraphicStorageHandler = xGraphicHelper.get();
392 
393  try
394  {
395  uno::Reference< io::XSeekable > xSeek( aParserInput.aInputStream, uno::UNO_QUERY_THROW );
396  xSeek->seek( 0 );
397  }
398  catch (const uno::Exception&)
399  {
400  }
401 
402  rtl::Reference<SvxXMLXTableImport> xImport(new SvxXMLXTableImport(xContext, xTable, xGraphicStorageHandler));
403  xImport->parseStream( aParserInput );
404 
405  if( xGraphicHelper )
406  xGraphicHelper->dispose();
407  }
408  catch (...)
409  {
410 // thrown each time you load a document with property tables that are not
411 // on the current machine. FIXME: would be better to check a file exists
412 // before importing ...
413  bRet = false;
414  }
415 
416  return bRet;
417 }
418 
420  sal_uInt16 const nPrefix, const OUString& rLocalName,
421  const uno::Reference< XAttributeList >& /*xAttrList*/)
422 {
423  if( XML_NAMESPACE_OOO == nPrefix ||
424  XML_NAMESPACE_OFFICE == nPrefix )
425  {
426  bool bOOoFormat = (XML_NAMESPACE_OFFICE == nPrefix);
427  Type aType = mrTable->getElementType();
428 
429  if ( rLocalName == "color-table" )
430  {
431  if( aType == ::cppu::UnoType<sal_Int32>::get() )
432  return new SvxXMLTableImportContext( *this, nPrefix, rLocalName, SvxXMLTableImportContextEnum::Color, mrTable, bOOoFormat );
433  }
434  else if ( rLocalName == "marker-table" )
435  {
437  return new SvxXMLTableImportContext( *this, nPrefix, rLocalName, SvxXMLTableImportContextEnum::Marker, mrTable, bOOoFormat );
438  }
439  else if ( rLocalName == "dash-table" )
440  {
442  return new SvxXMLTableImportContext( *this, nPrefix, rLocalName, SvxXMLTableImportContextEnum::Dash, mrTable, bOOoFormat );
443  }
444  else if ( rLocalName == "hatch-table" )
445  {
446  if( aType == cppu::UnoType<drawing::Hatch>::get())
447  return new SvxXMLTableImportContext( *this, nPrefix, rLocalName, SvxXMLTableImportContextEnum::Hatch, mrTable, bOOoFormat );
448  }
449  else if ( rLocalName == "gradient-table" )
450  {
451  if( aType == cppu::UnoType<awt::Gradient>::get())
452  return new SvxXMLTableImportContext( *this, nPrefix, rLocalName, SvxXMLTableImportContextEnum::Gradient, mrTable, bOOoFormat );
453  }
454  else if ( rLocalName == "bitmap-table" )
455  {
456  if( aType == ::cppu::UnoType<awt::XBitmap>::get())
457  return new SvxXMLTableImportContext( *this, nPrefix, rLocalName, SvxXMLTableImportContextEnum::Bitmap, mrTable, bOOoFormat );
458  }
459  }
460 
461  return new SvXMLImportContext( *this, nPrefix, rLocalName );
462 }
463 
464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
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:333
NONE
bool IsStorage()
Reference< XInputStream > xStream
virtual ~SvxXMLXTableImport() override
Definition: xmlxtimp.cxx:320
SvXMLImportFlags
XML_N_DRAW_OOO
SvxXMLTableImportContextEnum
Definition: xmlxtimp.cxx:70
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:297
void SetGraphicStorageHandler(css::uno::Reference< css::document::XGraphicStorageHandler > const &rxGraphicStorageHandler)
XML_N_OFFICE
XMLOFF_DLLPUBLIC bool importXML(css::uno::Reference< css::xml::sax::XAttributeList > const &xAttrList, css::uno::Any &rValue, OUString &rStrName, SvXMLImport &rImport)
#define XML_NAMESPACE_OOO(prefix, index)
XML_N_DRAW
virtual SvXMLImportContext * CreateDocumentContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Definition: xmlxtimp.cxx:419
int i
virtual sal_Int16 SAL_CALL getLength() override
friend friend class SvXMLImportContext
XML_N_OFFICE_OOO
css::uno::Reference< css::io::XInputStream > const & GetInputStream()
const css::uno::Reference< css::container::XNameContainer > & mrTable
Definition: xmlxtimp.hxx:53
static void openStorageStream(xml::sax::InputSource *pParserInput, rtl::Reference< SvXMLGraphicHelper > &rxGraphicHelper, const uno::Reference< embed::XStorage > &xStorage)
Definition: xmlxtimp.cxx:324
css::uno::Reference< css::embed::XStorage > GetStorage(bool bCreateTempFile=true)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
static bool convertColor(sal_Int32 &rColor, const OUString &rValue)
XML_N_XLINK
OUString aName
INetProtocol GetProtocol() const
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)
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)
sal_uInt16 nPos