Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / writerperfect / source / impress / KeynoteImportFilter.cxx
blob1547d1d27222c61188a37760bb30abe18b7c3e76
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* KeynoteImportFilter: Sets up the filter, and calls OdpExporter
3 * to do the actual filtering
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 */
10 #include <memory>
11 #include <com/sun/star/beans/NamedValue.hpp>
12 #include <com/sun/star/beans/PropertyValue.hpp>
13 #include <com/sun/star/container/XChild.hpp>
14 #include <com/sun/star/io/XInputStream.hpp>
15 #include <com/sun/star/uno/Reference.h>
16 #include <com/sun/star/ucb/XContent.hpp>
17 #include <comphelper/processfactory.hxx>
18 #include <comphelper/types.hxx>
19 #include <cppuhelper/supportsservice.hxx>
21 #include <iostream>
22 #include <libetonyek/libetonyek.h>
23 #include <libodfgen/libodfgen.hxx>
24 #include <osl/diagnose.h>
25 #include <rtl/tencinfo.h>
26 #include <ucbhelper/content.hxx>
28 #include <DirectoryStream.hxx>
29 #include <DocumentHandler.hxx>
30 #include <WPXSvInputStream.hxx>
32 #include <xmloff/attrlist.hxx>
34 #include "KeynoteImportFilter.hxx"
36 using std::shared_ptr;
38 using com::sun::star::io::XInputStream;
39 using com::sun::star::uno::Reference;
40 using com::sun::star::uno::RuntimeException;
41 using com::sun::star::uno::Sequence;
42 using com::sun::star::uno::UNO_QUERY;
43 using com::sun::star::uno::XComponentContext;
44 using com::sun::star::uno::XInterface;
46 using writerperfect::DocumentHandler;
47 using writerperfect::WPXSvInputStream;
49 namespace beans = com::sun::star::beans;
50 namespace container = com::sun::star::container;
51 namespace ucb = com::sun::star::ucb;
53 bool KeynoteImportFilter::doImportDocument(librevenge::RVNGInputStream &rInput, OdpGenerator &rGenerator, utl::MediaDescriptor &)
55 return libetonyek::EtonyekDocument::parse(&rInput, &rGenerator);
58 bool KeynoteImportFilter::doDetectFormat(librevenge::RVNGInputStream &rInput, OUString &rTypeName)
60 if (libetonyek::EtonyekDocument::isSupported(&rInput))
62 rTypeName = "impress_Keynote_Document";
63 return true;
66 return false;
69 // XExtendedFilterDetection
70 OUString SAL_CALL KeynoteImportFilter::detect(css::uno::Sequence< css::beans::PropertyValue > &Descriptor)
71 throw(css::uno::RuntimeException, std::exception)
73 sal_Int32 nLength = Descriptor.getLength();
74 sal_Int32 nNewLength = nLength + 2;
75 sal_Int32 nComponentDataLocation = -1;
76 sal_Int32 nTypeNameLocation = -1;
77 sal_Int32 nUCBContentLocation = -1;
78 bool bIsPackage = false;
79 bool bUCBContentChanged = false;
80 const beans::PropertyValue *pValue = Descriptor.getConstArray();
81 Reference < XInputStream > xInputStream;
82 Reference < ucb::XContent > xContent;
83 Sequence < beans::NamedValue > lComponentDataNV;
84 Sequence < beans::PropertyValue > lComponentDataPV;
85 bool bComponentDataNV = true;
87 for (sal_Int32 i = 0 ; i < nLength; i++)
89 if (pValue[i].Name == "TypeName")
91 nTypeNameLocation = i;
92 --nNewLength;
94 if (pValue[i].Name == "ComponentData")
96 bComponentDataNV = pValue[i].Value >>= lComponentDataNV;
97 if (!bComponentDataNV)
98 pValue[i].Value >>= lComponentDataPV;
99 nComponentDataLocation = i;
100 --nNewLength;
102 else if (pValue[i].Name == "InputStream")
104 pValue[i].Value >>= xInputStream;
106 else if (pValue[i].Name == "UCBContent")
108 pValue[i].Value >>= xContent;
109 nUCBContentLocation = i;
113 assert(nNewLength >= nLength);
115 if (!xInputStream.is())
116 return OUString();
118 shared_ptr< librevenge::RVNGInputStream > input(new WPXSvInputStream(xInputStream));
120 /* Apple Keynote documents come in two variants:
121 * * actual files (zip), only produced by Keynote 5 (at least with
122 * default settings)
123 * * packages (IOW, directories), produced by Keynote 1-4 and again
124 * starting with 6.
125 * But since the libetonyek import only works with a stream, we need
126 * to pass it one for the whole package. Here we determine if that
127 * is needed.
129 * Note: for convenience, we also recognize that the main XML file
130 * from a package was passed and pass the whole package to the
131 * filter instead.
133 if (xContent.is())
135 ucbhelper::Content aContent(xContent, Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext());
138 if (aContent.isFolder())
140 input.reset(new writerperfect::DirectoryStream(xContent));
141 bIsPackage = true;
144 catch (...)
146 return OUString();
150 libetonyek::EtonyekDocument::Type type = libetonyek::EtonyekDocument::TYPE_UNKNOWN;
151 const libetonyek::EtonyekDocument::Confidence confidence = libetonyek::EtonyekDocument::isSupported(input.get(), &type);
152 if ((libetonyek::EtonyekDocument::CONFIDENCE_NONE == confidence) || (libetonyek::EtonyekDocument::TYPE_KEYNOTE != type))
153 return OUString();
155 if (confidence == libetonyek::EtonyekDocument::CONFIDENCE_SUPPORTED_PART)
157 if (bIsPackage) // we passed a directory stream, but the filter claims it's APXL file?
158 return OUString();
160 const Reference < container::XChild > xChild(xContent, UNO_QUERY);
161 if (xChild.is())
163 const Reference < ucb::XContent > xPackageContent(xChild->getParent(), UNO_QUERY);
164 if (xPackageContent.is())
166 input.reset(new writerperfect::DirectoryStream(xPackageContent));
167 if (libetonyek::EtonyekDocument::CONFIDENCE_EXCELLENT == libetonyek::EtonyekDocument::isSupported(input.get()))
169 xContent = xPackageContent;
170 bUCBContentChanged = true;
171 bIsPackage = true;
173 else
175 // The passed stream has been detected as APXL file, but its parent dir is not a valid Keynote
176 // package? Something is wrong here...
177 return OUString();
183 // we do not need to insert ComponentData if this is not a package
184 if (!bIsPackage && (nComponentDataLocation == -1))
185 --nNewLength;
187 if (nNewLength > nLength)
188 Descriptor.realloc(nNewLength);
190 if (nTypeNameLocation == -1)
192 assert(nLength < nNewLength);
193 nTypeNameLocation = nLength++;
194 Descriptor[nTypeNameLocation].Name = "TypeName";
197 if (bIsPackage && (nComponentDataLocation == -1))
199 assert(nLength < nNewLength);
200 nComponentDataLocation = nLength++;
201 Descriptor[nComponentDataLocation].Name = "ComponentData";
204 if (bIsPackage)
206 if (bComponentDataNV)
208 const sal_Int32 nCDSize = lComponentDataNV.getLength();
209 lComponentDataNV.realloc(nCDSize + 1);
210 beans::NamedValue aValue;
211 aValue.Name = "IsPackage";
212 aValue.Value <<= true;
213 lComponentDataNV[nCDSize] = aValue;
214 Descriptor[nComponentDataLocation].Value <<= lComponentDataNV;
216 else
218 const sal_Int32 nCDSize = lComponentDataPV.getLength();
219 lComponentDataPV.realloc(nCDSize + 1);
220 beans::PropertyValue aProp;
221 aProp.Name = "IsPackage";
222 aProp.Value <<= true;
223 aProp.Handle = -1;
224 aProp.State = beans::PropertyState_DIRECT_VALUE;
225 lComponentDataPV[nCDSize] = aProp;
226 Descriptor[nComponentDataLocation].Value <<= lComponentDataPV;
230 if (bUCBContentChanged)
231 Descriptor[nUCBContentLocation].Value <<= xContent;
233 const OUString sTypeName("impress_AppleKeynote");
234 Descriptor[nTypeNameLocation].Value <<= sTypeName;
236 return sTypeName;
239 // XServiceInfo
240 OUString SAL_CALL KeynoteImportFilter::getImplementationName()
241 throw (RuntimeException, std::exception)
243 return OUString("org.libreoffice.comp.Impress.KeynoteImportFilter");
246 sal_Bool SAL_CALL KeynoteImportFilter::supportsService(const OUString &rServiceName)
247 throw (RuntimeException, std::exception)
249 return cppu::supportsService(this, rServiceName);
252 Sequence< OUString > SAL_CALL KeynoteImportFilter::getSupportedServiceNames()
253 throw (RuntimeException, std::exception)
255 Sequence < OUString > aRet(2);
256 OUString *pArray = aRet.getArray();
257 pArray[0] = "com.sun.star.document.ImportFilter";
258 pArray[1] = "com.sun.star.document.ExtendedTypeDetection";
259 return aRet;
262 extern "C"
263 SAL_DLLPUBLIC_EXPORT css::uno::XInterface *SAL_CALL
264 org_libreoffice_comp_Impress_KeynoteImportFilter_get_implementation(
265 css::uno::XComponentContext *const context,
266 const css::uno::Sequence<css::uno::Any> &)
268 return cppu::acquire(new KeynoteImportFilter(context));
271 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */