LibreOffice Module sc (master)  1
orcusfiltersimpl.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 
10 #include <orcusfiltersimpl.hxx>
11 #include <orcusinterface.hxx>
12 #include <tokenarray.hxx>
13 
14 #include <memory>
15 
16 #include <osl/thread.hxx>
17 #include <sfx2/docfile.hxx>
18 #include <sfx2/frame.hxx>
19 #include <sfx2/sfxsids.hrc>
20 #include <svl/itemset.hxx>
21 #include <rtl/ustring.hxx>
22 #include <sal/log.hxx>
23 
24 #include <orcus/orcus_csv.hpp>
25 #include <orcus/orcus_gnumeric.hpp>
26 #include <orcus/orcus_xlsx.hpp>
27 #include <orcus/orcus_xls_xml.hpp>
28 #include <orcus/orcus_ods.hpp>
29 #include <orcus/orcus_import_ods.hpp>
30 #include <orcus/stream.hpp>
31 #include <com/sun/star/task/XStatusIndicator.hpp>
32 
33 #if defined _WIN32
34 #include <boost/filesystem/operations.hpp> // for boost::filesystem::filesystem_error
36 #include <prewin.h>
37 #include <postwin.h>
38 #endif
39 
40 using namespace com::sun::star;
41 
42 namespace
43 {
44 uno::Reference<task::XStatusIndicator> getStatusIndicator(const SfxMedium& rMedium)
45 {
46  uno::Reference<task::XStatusIndicator> xStatusIndicator;
47  SfxItemSet* pSet = rMedium.GetItemSet();
48  if (pSet)
49  {
50  const SfxUnoAnyItem* pItem = pSet->GetItem<SfxUnoAnyItem>(SID_PROGRESS_STATUSBAR_CONTROL);
51  if (pItem)
52  xStatusIndicator.set(pItem->GetValue(), uno::UNO_QUERY);
53  }
54  return xStatusIndicator;
55 }
56 
57 bool loadFileContent(SfxMedium& rMedium, orcus::iface::import_filter& filter)
58 {
59  SvStream* pStream = rMedium.GetInStream();
60  pStream->Seek(0);
61  static const size_t nReadBuffer = 1024 * 32;
62  OStringBuffer aBuffer((int(nReadBuffer)));
63  size_t nRead = 0;
64  do
65  {
66  char pData[nReadBuffer];
67  nRead = pStream->ReadBytes(pData, nReadBuffer);
68  aBuffer.append(pData, nRead);
69  } while (nRead == nReadBuffer);
70 
71  try
72  {
73  filter.read_stream(aBuffer.getStr(), aBuffer.getLength());
74  }
75  catch (const std::exception& e)
76  {
77  SAL_WARN("sc", "Unable to load file via orcus filter! " << e.what());
78  return false;
79  }
80 
81  return true;
82 }
83 }
84 
86 {
87  ScOrcusFactory aFactory(rDoc);
88  aFactory.setStatusIndicator(getStatusIndicator(rMedium));
89 
90  orcus::orcus_csv filter(&aFactory);
91  return loadFileContent(rMedium, filter);
92 }
93 
95 {
96  ScOrcusFactory aFactory(rDoc);
97  aFactory.setStatusIndicator(getStatusIndicator(rMedium));
98 
99  orcus::orcus_gnumeric filter(&aFactory);
100  return loadFileContent(rMedium, filter);
101 }
102 
104 {
105  ScOrcusFactory aFactory(rDoc);
106  aFactory.setStatusIndicator(getStatusIndicator(rMedium));
107 
108  orcus::orcus_xls_xml filter(&aFactory);
109  return loadFileContent(rMedium, filter);
110 }
111 
113 {
114  ScOrcusFactory aFactory(rDoc);
115  aFactory.setStatusIndicator(getStatusIndicator(rMedium));
116 
117  orcus::orcus_xlsx filter(&aFactory);
118  return loadFileContent(rMedium, filter);
119 }
120 
122 {
123  ScOrcusFactory aFactory(rDoc);
124  aFactory.setStatusIndicator(getStatusIndicator(rMedium));
125 
126  orcus::orcus_ods filter(&aFactory);
127  return loadFileContent(rMedium, filter);
128 }
129 
130 bool ScOrcusFiltersImpl::importODS_Styles(ScDocument& rDoc, OUString& aPath) const
131 {
132  OString aPath8 = OUStringToOString(aPath, osl_getThreadTextEncoding());
133 
134  try
135  {
136 #if defined _WIN32
137  std::unique_ptr<orcus::file_content> content;
138  try
139  {
140  content = std::make_unique<orcus::file_content>(aPath8.getStr());
141  }
142  catch (const boost::filesystem::filesystem_error&)
143  {
144  // Maybe the path contains characters not representable in ACP. It's not
145  // yet possible to pass Unicode path to orcus::file_content ctor - see
146  // https://gitlab.com/orcus/orcus/-/issues/30; try short path.
147  wchar_t buf[32767];
148  if (GetShortPathNameW(o3tl::toW(aPath.getStr()), buf, std::size(buf)) == 0)
149  throw;
150  aPath8 = OUStringToOString(o3tl::toU(buf), osl_getThreadTextEncoding());
151  content = std::make_unique<orcus::file_content>(aPath8.getStr());
152  }
153 #else
154  auto content = std::make_unique<orcus::file_content>(aPath8.getStr());
155 #endif
156  ScOrcusFactory aFactory(rDoc);
157  ScOrcusStyles aStyles(aFactory);
158  orcus::import_ods::read_styles(content->data(), content->size(), &aStyles);
159  }
160  catch (const std::exception& e)
161  {
162  SAL_WARN("sc", "Unable to load styles from xml file! " << e.what());
163  return false;
164  }
165 
166  return true;
167 }
168 
169 std::unique_ptr<ScOrcusXMLContext> ScOrcusFiltersImpl::createXMLContext(ScDocument& rDoc,
170  const OUString& rPath) const
171 {
172  return std::make_unique<ScOrcusXMLContextImpl>(rDoc, rPath);
173 }
174 
175 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< ContentProperties > pData
virtual std::unique_ptr< ScOrcusXMLContext > createXMLContext(ScDocument &rDoc, const OUString &rPath) const override
Create a context for XML file.
sal_uInt64 Seek(sal_uInt64 nPos)
const css::uno::Any & GetValue() const
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
virtual bool importXLSX(ScDocument &rDoc, SfxMedium &rMedium) const override
SfxItemSet * GetItemSet() const
virtual bool importODS(ScDocument &rDoc, SfxMedium &rMedium) const override
virtual bool importODS_Styles(ScDocument &rDoc, OUString &aFileName) const override
Used to import just the styles from an xml file.
virtual bool importExcel2003XML(ScDocument &rDoc, SfxMedium &rMedium) const override
std::size_t ReadBytes(void *pData, std::size_t nSize)
void setStatusIndicator(const css::uno::Reference< css::task::XStatusIndicator > &rIndicator)
Definition: interface.cxx:679
SvStream * GetInStream()
std::unique_ptr< char[]> aBuffer
virtual bool importGnumeric(ScDocument &rDoc, SfxMedium &rMedium) const override
#define SAL_WARN(area, stream)
virtual bool importCSV(ScDocument &rDoc, SfxMedium &rMedium) const override
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const