Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 : */
7 : /* "This product is not manufactured, approved, or supported by
8 : * Corel Corporation or Corel Corporation Limited."
9 : */
10 :
11 : #include <osl/diagnose.h>
12 : #include <rtl/tencinfo.h>
13 :
14 : #include <com/sun/star/io/XInputStream.hpp>
15 : #include <com/sun/star/xml/sax/XAttributeList.hpp>
16 : #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
17 : #include <com/sun/star/xml/sax/InputSource.hpp>
18 : #include <com/sun/star/xml/sax/XParser.hpp>
19 : #include <com/sun/star/io/XSeekable.hpp>
20 : #include <com/sun/star/uno/Reference.h>
21 : #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
22 : #include <cppuhelper/supportsservice.hxx>
23 :
24 : #include <DocumentHandler.hxx>
25 : #include <WPXSvInputStream.hxx>
26 :
27 : #include <xmloff/attrlist.hxx>
28 : #include <sfx2/passwd.hxx>
29 : #include <ucbhelper/content.hxx>
30 :
31 : #include <libodfgen/libodfgen.hxx>
32 : #include <libwpd/libwpd.h>
33 : #include <libwpg/libwpg.h>
34 :
35 : #include "WordPerfectImportFilter.hxx"
36 :
37 : using ::ucbhelper::Content;
38 : using com::sun::star::uno::Sequence;
39 : using com::sun::star::uno::Reference;
40 : using com::sun::star::uno::Any;
41 : using com::sun::star::uno::UNO_QUERY;
42 : using com::sun::star::uno::XInterface;
43 : using com::sun::star::uno::Exception;
44 : using com::sun::star::uno::RuntimeException;
45 : using com::sun::star::uno::XComponentContext;
46 : using com::sun::star::beans::PropertyValue;
47 : using com::sun::star::document::XFilter;
48 : using com::sun::star::document::XExtendedFilterDetection;
49 : using com::sun::star::ucb::XCommandEnvironment;
50 :
51 : using com::sun::star::io::XInputStream;
52 : using com::sun::star::document::XImporter;
53 : using com::sun::star::xml::sax::InputSource;
54 : using com::sun::star::xml::sax::XAttributeList;
55 : using com::sun::star::xml::sax::XDocumentHandler;
56 : using com::sun::star::xml::sax::XParser;
57 :
58 : using writerperfect::DocumentHandler;
59 : using writerperfect::WPXSvInputStream;
60 :
61 0 : static bool handleEmbeddedWPGObject(const librevenge::RVNGBinaryData &data, OdfDocumentHandler *pHandler, const OdfStreamType streamType)
62 : {
63 0 : OdgGenerator exporter;
64 0 : exporter.addDocumentHandler(pHandler, streamType);
65 :
66 0 : libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT;
67 :
68 0 : if (!libwpg::WPGraphics::isSupported(data.getDataStream()))
69 0 : fileFormat = libwpg::WPG_WPG1;
70 :
71 0 : return libwpg::WPGraphics::parse(data.getDataStream(), &exporter, fileFormat);
72 : }
73 :
74 0 : static bool handleEmbeddedWPGImage(const librevenge::RVNGBinaryData &input, librevenge::RVNGBinaryData &output)
75 : {
76 0 : libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT;
77 :
78 0 : if (!libwpg::WPGraphics::isSupported(input.getDataStream()))
79 0 : fileFormat = libwpg::WPG_WPG1;
80 :
81 0 : librevenge::RVNGStringVector svgOutput;
82 0 : librevenge::RVNGSVGDrawingGenerator aSVGGenerator(svgOutput, "");
83 :
84 0 : if (!libwpg::WPGraphics::parse(input.getDataStream(), &aSVGGenerator, fileFormat))
85 0 : return false;
86 :
87 : assert(1 == svgOutput.size());
88 :
89 0 : output.clear();
90 0 : output.append(reinterpret_cast<const unsigned char *>(svgOutput[0].cstr()), svgOutput[0].size());
91 0 : return true;
92 : }
93 :
94 7 : bool SAL_CALL WordPerfectImportFilter::importImpl(const Sequence< ::com::sun::star::beans::PropertyValue > &aDescriptor)
95 : throw (RuntimeException, std::exception)
96 : {
97 7 : sal_Int32 nLength = aDescriptor.getLength();
98 7 : const PropertyValue *pValue = aDescriptor.getConstArray();
99 7 : Reference < XInputStream > xInputStream;
100 42 : for (sal_Int32 i = 0 ; i < nLength; i++)
101 : {
102 35 : if (pValue[i].Name == "InputStream")
103 7 : pValue[i].Value >>= xInputStream;
104 : }
105 7 : if (!xInputStream.is())
106 : {
107 : OSL_ASSERT(false);
108 0 : return false;
109 : }
110 :
111 14 : WPXSvInputStream input(xInputStream);
112 :
113 14 : OString aUtf8Passwd;
114 :
115 7 : libwpd::WPDConfidence confidence = libwpd::WPDocument::isFileFormatSupported(&input);
116 :
117 7 : if (libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence)
118 : {
119 0 : int unsuccessfulAttempts = 0;
120 : while (true)
121 : {
122 0 : ScopedVclPtrInstance< SfxPasswordDialog > aPasswdDlg(nullptr);
123 0 : aPasswdDlg->SetMinLen(0);
124 0 : if (!aPasswdDlg->Execute())
125 0 : return false;
126 0 : OUString aPasswd = aPasswdDlg->GetPassword();
127 0 : aUtf8Passwd = OUStringToOString(aPasswd, RTL_TEXTENCODING_UTF8);
128 0 : if (libwpd::WPD_PASSWORD_MATCH_OK == libwpd::WPDocument::verifyPassword(&input, aUtf8Passwd.getStr()))
129 0 : break;
130 : else
131 0 : unsuccessfulAttempts++;
132 0 : if (unsuccessfulAttempts == 3) // timeout after 3 password atempts
133 0 : return false;
134 0 : }
135 : }
136 :
137 : // An XML import service: what we push sax messages to..
138 : Reference < XDocumentHandler > xInternalHandler(
139 14 : mxContext->getServiceManager()->createInstanceWithContext(
140 7 : "com.sun.star.comp.Writer.XMLOasisImporter", mxContext),
141 14 : css::uno::UNO_QUERY_THROW);
142 :
143 : // The XImporter sets up an empty target document for XDocumentHandler to write to..
144 14 : Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY);
145 7 : xImporter->setTargetDocument(mxDoc);
146 :
147 : // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here
148 : // writes to in-memory target doc
149 14 : DocumentHandler xHandler(xInternalHandler);
150 :
151 14 : OdtGenerator collector;
152 7 : collector.addDocumentHandler(&xHandler, ODF_FLAT_XML);
153 7 : collector.registerEmbeddedObjectHandler("image/x-wpg", &handleEmbeddedWPGObject);
154 7 : collector.registerEmbeddedImageHandler("image/x-wpg", &handleEmbeddedWPGImage);
155 7 : if (libwpd::WPD_OK == libwpd::WPDocument::parse(&input, &collector, aUtf8Passwd.isEmpty() ? 0 : aUtf8Passwd.getStr()))
156 7 : return true;
157 7 : return false;
158 : }
159 :
160 7 : sal_Bool SAL_CALL WordPerfectImportFilter::filter(const Sequence< ::com::sun::star::beans::PropertyValue > &aDescriptor)
161 : throw (RuntimeException, std::exception)
162 : {
163 7 : return importImpl(aDescriptor);
164 : }
165 0 : void SAL_CALL WordPerfectImportFilter::cancel()
166 : throw (RuntimeException, std::exception)
167 : {
168 0 : }
169 :
170 : // XImporter
171 7 : void SAL_CALL WordPerfectImportFilter::setTargetDocument(const Reference< ::com::sun::star::lang::XComponent > &xDoc)
172 : throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException, std::exception)
173 : {
174 7 : mxDoc = xDoc;
175 7 : }
176 :
177 : // XExtendedFilterDetection
178 91 : OUString SAL_CALL WordPerfectImportFilter::detect(Sequence< PropertyValue > &Descriptor)
179 : throw(RuntimeException, std::exception)
180 : {
181 91 : libwpd::WPDConfidence confidence = libwpd::WPD_CONFIDENCE_NONE;
182 91 : OUString sTypeName;
183 91 : sal_Int32 nLength = Descriptor.getLength();
184 91 : sal_Int32 location = nLength;
185 91 : const PropertyValue *pValue = Descriptor.getConstArray();
186 182 : Reference < XInputStream > xInputStream;
187 785 : for (sal_Int32 i = 0 ; i < nLength; i++)
188 : {
189 694 : if (pValue[i].Name == "TypeName")
190 84 : location=i;
191 610 : else if (pValue[i].Name == "InputStream")
192 91 : pValue[i].Value >>= xInputStream;
193 : }
194 :
195 91 : if (!xInputStream.is())
196 0 : return OUString();
197 :
198 182 : WPXSvInputStream input(xInputStream);
199 :
200 91 : confidence = libwpd::WPDocument::isFileFormatSupported(&input);
201 :
202 91 : if (confidence == libwpd::WPD_CONFIDENCE_EXCELLENT || confidence == libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION)
203 7 : sTypeName = "writer_WordPerfect_Document";
204 :
205 91 : if (!sTypeName.isEmpty())
206 : {
207 7 : if (location == nLength)
208 : {
209 7 : Descriptor.realloc(nLength+1);
210 7 : Descriptor[location].Name = "TypeName";
211 : }
212 :
213 7 : Descriptor[location].Value <<=sTypeName;
214 : }
215 :
216 182 : return sTypeName;
217 : }
218 :
219 :
220 : // XInitialization
221 0 : void SAL_CALL WordPerfectImportFilter::initialize(const Sequence< Any > &aArguments)
222 : throw (Exception, RuntimeException, std::exception)
223 : {
224 0 : Sequence < PropertyValue > aAnySeq;
225 0 : sal_Int32 nLength = aArguments.getLength();
226 0 : if (nLength && (aArguments[0] >>= aAnySeq))
227 : {
228 0 : const PropertyValue *pValue = aAnySeq.getConstArray();
229 0 : nLength = aAnySeq.getLength();
230 0 : for (sal_Int32 i = 0 ; i < nLength; i++)
231 : {
232 0 : if (pValue[i].Name == "Type")
233 : {
234 0 : pValue[i].Value >>= msFilterName;
235 0 : break;
236 : }
237 : }
238 0 : }
239 0 : }
240 33 : OUString WordPerfectImportFilter_getImplementationName()
241 : throw (RuntimeException)
242 : {
243 33 : return OUString("com.sun.star.comp.Writer.WordPerfectImportFilter");
244 : }
245 :
246 5 : Sequence< OUString > SAL_CALL WordPerfectImportFilter_getSupportedServiceNames()
247 : throw (RuntimeException)
248 : {
249 5 : Sequence < OUString > aRet(2);
250 5 : OUString *pArray = aRet.getArray();
251 5 : pArray[0] = "com.sun.star.document.ImportFilter";
252 5 : pArray[1] = "com.sun.star.document.ExtendedTypeDetection";
253 5 : return aRet;
254 : }
255 :
256 86 : Reference< XInterface > SAL_CALL WordPerfectImportFilter_createInstance(const Reference< XComponentContext > &rContext)
257 : throw(Exception)
258 : {
259 86 : return static_cast<cppu::OWeakObject *>(new WordPerfectImportFilter(rContext));
260 : }
261 :
262 : // XServiceInfo
263 1 : OUString SAL_CALL WordPerfectImportFilter::getImplementationName()
264 : throw (RuntimeException, std::exception)
265 : {
266 1 : return WordPerfectImportFilter_getImplementationName();
267 : }
268 0 : sal_Bool SAL_CALL WordPerfectImportFilter::supportsService(const OUString &rServiceName)
269 : throw (RuntimeException, std::exception)
270 : {
271 0 : return cppu::supportsService(this, rServiceName);
272 : }
273 1 : Sequence< OUString > SAL_CALL WordPerfectImportFilter::getSupportedServiceNames()
274 : throw (RuntimeException, std::exception)
275 : {
276 1 : return WordPerfectImportFilter_getSupportedServiceNames();
277 : }
278 :
279 :
280 0 : WordPerfectImportFilterDialog::WordPerfectImportFilterDialog(const Reference< XComponentContext > &rContext) :
281 0 : mxContext(rContext) {}
282 :
283 0 : WordPerfectImportFilterDialog::~WordPerfectImportFilterDialog()
284 : {
285 0 : }
286 :
287 0 : void SAL_CALL WordPerfectImportFilterDialog::setTitle(const OUString &)
288 : throw (RuntimeException, std::exception)
289 : {
290 0 : }
291 :
292 0 : sal_Int16 SAL_CALL WordPerfectImportFilterDialog::execute()
293 : throw (RuntimeException, std::exception)
294 : {
295 0 : WPXSvInputStream input(mxInputStream);
296 :
297 0 : OString aUtf8Passwd;
298 :
299 0 : libwpd::WPDConfidence confidence = libwpd::WPDocument::isFileFormatSupported(&input);
300 :
301 0 : if (libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence)
302 : {
303 0 : int unsuccessfulAttempts = 0;
304 : while (true)
305 : {
306 0 : ScopedVclPtrInstance< SfxPasswordDialog > aPasswdDlg(nullptr);
307 0 : aPasswdDlg->SetMinLen(0);
308 0 : if (!aPasswdDlg->Execute())
309 0 : return com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL;
310 0 : msPassword = aPasswdDlg->GetPassword().getStr();
311 0 : aUtf8Passwd = OUStringToOString(msPassword, RTL_TEXTENCODING_UTF8);
312 0 : if (libwpd::WPD_PASSWORD_MATCH_OK == libwpd::WPDocument::verifyPassword(&input, aUtf8Passwd.getStr()))
313 0 : break;
314 : else
315 0 : unsuccessfulAttempts++;
316 0 : if (unsuccessfulAttempts == 3) // timeout after 3 password atempts
317 0 : return com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL;
318 0 : }
319 : }
320 0 : return com::sun::star::ui::dialogs::ExecutableDialogResults::OK;
321 : }
322 :
323 0 : Sequence<PropertyValue> SAL_CALL WordPerfectImportFilterDialog::getPropertyValues() throw(RuntimeException, std::exception)
324 : {
325 0 : Sequence<PropertyValue> aRet(1);
326 0 : PropertyValue *pArray = aRet.getArray();
327 :
328 0 : pArray[0].Name = "Password";
329 0 : pArray[0].Value <<= msPassword;
330 :
331 0 : return aRet;
332 : }
333 :
334 0 : void SAL_CALL WordPerfectImportFilterDialog::setPropertyValues(const Sequence<PropertyValue> &aProps)
335 : throw(com::sun::star::beans::UnknownPropertyException, com::sun::star::beans::PropertyVetoException,
336 : com::sun::star::lang::IllegalArgumentException, com::sun::star::lang::WrappedTargetException, RuntimeException, std::exception)
337 : {
338 0 : const PropertyValue *pPropArray = aProps.getConstArray();
339 0 : long nPropCount = aProps.getLength();
340 0 : for (long i = 0; i < nPropCount; i++)
341 : {
342 0 : const PropertyValue &rProp = pPropArray[i];
343 0 : OUString aPropName = rProp.Name;
344 :
345 0 : if (aPropName == "Password")
346 0 : rProp.Value >>= msPassword;
347 0 : else if (aPropName == "InputStream")
348 0 : rProp.Value >>= mxInputStream;
349 0 : }
350 0 : }
351 :
352 :
353 : // XServiceInfo
354 0 : OUString SAL_CALL WordPerfectImportFilterDialog::getImplementationName()
355 : throw (RuntimeException, std::exception)
356 : {
357 0 : return WordPerfectImportFilterDialog_getImplementationName();
358 : }
359 :
360 0 : sal_Bool SAL_CALL WordPerfectImportFilterDialog::supportsService(const OUString &rServiceName)
361 : throw (RuntimeException, std::exception)
362 : {
363 0 : return cppu::supportsService(this, rServiceName);
364 : }
365 :
366 0 : Sequence< OUString > SAL_CALL WordPerfectImportFilterDialog::getSupportedServiceNames()
367 : throw (RuntimeException, std::exception)
368 : {
369 0 : return WordPerfectImportFilterDialog_getSupportedServiceNames();
370 : }
371 :
372 0 : OUString WordPerfectImportFilterDialog_getImplementationName()
373 : throw (RuntimeException)
374 : {
375 0 : return OUString("com.sun.star.comp.Writer.WordPerfectImportFilterDialog");
376 : }
377 :
378 0 : Sequence< OUString > SAL_CALL WordPerfectImportFilterDialog_getSupportedServiceNames()
379 : throw (RuntimeException)
380 : {
381 0 : Sequence < OUString > aRet(1);
382 0 : OUString *pArray = aRet.getArray();
383 0 : pArray[0] = "com.sun.star.ui.dialogs.FilterOptionsDialog";
384 0 : return aRet;
385 : }
386 :
387 0 : Reference< XInterface > SAL_CALL WordPerfectImportFilterDialog_createInstance(const Reference< XComponentContext > &rContext)
388 : throw(Exception)
389 : {
390 0 : return static_cast<cppu::OWeakObject *>(new WordPerfectImportFilterDialog(rContext));
391 18 : }
392 :
393 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|