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 <com/sun/star/ucb/XCommandEnvironment.hpp>
23 :
24 : #include <comphelper/componentcontext.hxx>
25 : #include <xmloff/attrlist.hxx>
26 : #include <sfx2/passwd.hxx>
27 : #include <ucbhelper/content.hxx>
28 :
29 : #include <libwpd/libwpd.h>
30 :
31 : #include "filter/FilterInternal.hxx"
32 : #include "filter/DocumentHandler.hxx"
33 : #include "filter/OdgGenerator.hxx"
34 : #include "filter/OdtGenerator.hxx"
35 : #include "stream/WPXSvStream.h"
36 : #include "WordPerfectImportFilter.hxx"
37 :
38 : using ::ucbhelper::Content;
39 : using com::sun::star::uno::Sequence;
40 : using com::sun::star::uno::Reference;
41 : using com::sun::star::uno::Any;
42 : using com::sun::star::uno::UNO_QUERY;
43 : using com::sun::star::uno::XInterface;
44 : using com::sun::star::uno::Exception;
45 : using com::sun::star::uno::RuntimeException;
46 : using com::sun::star::uno::XComponentContext;
47 : using com::sun::star::beans::PropertyValue;
48 : using com::sun::star::document::XFilter;
49 : using com::sun::star::document::XExtendedFilterDetection;
50 : using com::sun::star::ucb::XCommandEnvironment;
51 :
52 : using com::sun::star::io::XInputStream;
53 : using com::sun::star::document::XImporter;
54 : using com::sun::star::xml::sax::InputSource;
55 : using com::sun::star::xml::sax::XAttributeList;
56 : using com::sun::star::xml::sax::XDocumentHandler;
57 : using com::sun::star::xml::sax::XParser;
58 :
59 : void callHandler(Reference < XDocumentHandler > xDocHandler);
60 :
61 :
62 0 : static bool handleEmbeddedWPGObject(const WPXBinaryData &data, OdfDocumentHandler *pHandler, const OdfStreamType streamType)
63 : {
64 0 : OdgGenerator exporter(pHandler, streamType);
65 :
66 0 : libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT;
67 :
68 0 : if (!libwpg::WPGraphics::isSupported(const_cast<WPXInputStream *>(data.getDataStream())))
69 0 : fileFormat = libwpg::WPG_WPG1;
70 :
71 0 : return libwpg::WPGraphics::parse(const_cast<WPXInputStream *>(data.getDataStream()), &exporter, fileFormat);
72 : }
73 :
74 0 : static bool handleEmbeddedWPGImage(const WPXBinaryData &input, WPXBinaryData &output)
75 : {
76 0 : WPXString svgOutput;
77 0 : libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT;
78 :
79 0 : if (!libwpg::WPGraphics::isSupported(const_cast<WPXInputStream *>(input.getDataStream())))
80 0 : fileFormat = libwpg::WPG_WPG1;
81 :
82 0 : if (!libwpg::WPGraphics::generateSVG(const_cast<WPXInputStream *>(input.getDataStream()), svgOutput, fileFormat))
83 0 : return false;
84 :
85 0 : output.clear();
86 0 : output.append((unsigned char *)svgOutput.cstr(), strlen(svgOutput.cstr()));
87 0 : return true;
88 : }
89 :
90 0 : sal_Bool SAL_CALL WordPerfectImportFilter::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
91 : throw (RuntimeException)
92 : {
93 : WRITER_DEBUG_MSG(("WordPerfectImportFilter::importImpl: Got here!\n"));
94 :
95 0 : sal_Int32 nLength = aDescriptor.getLength();
96 0 : const PropertyValue *pValue = aDescriptor.getConstArray();
97 0 : OUString sURL;
98 0 : Reference < XInputStream > xInputStream;
99 0 : for ( sal_Int32 i = 0 ; i < nLength; i++)
100 : {
101 0 : if ( pValue[i].Name == "InputStream" )
102 0 : pValue[i].Value >>= xInputStream;
103 0 : else if ( pValue[i].Name == "URL" )
104 0 : pValue[i].Value >>= sURL;
105 : }
106 0 : if ( !xInputStream.is() )
107 : {
108 : OSL_ASSERT( 0 );
109 0 : return sal_False;
110 : }
111 :
112 0 : WPXSvInputStream input( xInputStream );
113 :
114 0 : OString aUtf8Passwd;
115 :
116 0 : WPDConfidence confidence = WPDocument::isFileFormatSupported(&input);
117 :
118 0 : if (WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence)
119 : {
120 0 : int unsuccessfulAttempts = 0;
121 0 : while (true )
122 : {
123 0 : SfxPasswordDialog aPasswdDlg( 0 );
124 0 : aPasswdDlg.SetMinLen(0);
125 0 : if(!aPasswdDlg.Execute())
126 0 : return sal_False;
127 0 : OUString aPasswd = aPasswdDlg.GetPassword();
128 0 : aUtf8Passwd = OUStringToOString(aPasswd, RTL_TEXTENCODING_UTF8);
129 0 : if (WPD_PASSWORD_MATCH_OK == WPDocument::verifyPassword(&input, aUtf8Passwd.getStr()))
130 : break;
131 : else
132 0 : unsuccessfulAttempts++;
133 0 : if (unsuccessfulAttempts == 3) // timeout after 3 password atempts
134 0 : return sal_False;
135 0 : }
136 : }
137 :
138 : // An XML import service: what we push sax messages to..
139 0 : OUString sXMLImportService ( "com.sun.star.comp.Writer.XMLOasisImporter" );
140 0 : Reference < XDocumentHandler > xInternalHandler( comphelper::ComponentContext( mxContext ).createComponent( sXMLImportService ), UNO_QUERY );
141 :
142 : // The XImporter sets up an empty target document for XDocumentHandler to write to..
143 0 : Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY);
144 0 : xImporter->setTargetDocument(mxDoc);
145 :
146 : // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here
147 : // writes to in-memory target doc
148 0 : DocumentHandler xHandler(xInternalHandler);
149 :
150 0 : OdtGenerator collector(&xHandler, ODF_FLAT_XML);
151 0 : collector.registerEmbeddedObjectHandler("image/x-wpg", &handleEmbeddedWPGObject);
152 0 : collector.registerEmbeddedImageHandler("image/x-wpg", &handleEmbeddedWPGImage);
153 0 : if (WPD_OK == WPDocument::parse(&input, &collector, aUtf8Passwd.isEmpty() ? 0 : aUtf8Passwd.getStr()))
154 0 : return sal_True;
155 0 : return sal_False;
156 : }
157 :
158 0 : sal_Bool SAL_CALL WordPerfectImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
159 : throw (RuntimeException)
160 : {
161 : WRITER_DEBUG_MSG(("WordPerfectImportFilter::filter: Got here!\n"));
162 0 : return importImpl ( aDescriptor );
163 : }
164 0 : void SAL_CALL WordPerfectImportFilter::cancel( )
165 : throw (RuntimeException)
166 : {
167 : WRITER_DEBUG_MSG(("WordPerfectImportFilter::cancel: Got here!\n"));
168 0 : }
169 :
170 : // XImporter
171 0 : void SAL_CALL WordPerfectImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc )
172 : throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
173 : {
174 : WRITER_DEBUG_MSG(("WordPerfectImportFilter::getTargetDocument: Got here!\n"));
175 0 : mxDoc = xDoc;
176 0 : }
177 :
178 : // XExtendedFilterDetection
179 0 : OUString SAL_CALL WordPerfectImportFilter::detect( Sequence< PropertyValue >& Descriptor )
180 : throw( RuntimeException )
181 : {
182 : WRITER_DEBUG_MSG(("WordPerfectImportFilter::detect: Got here!\n"));
183 :
184 0 : WPDConfidence confidence = WPD_CONFIDENCE_NONE;
185 0 : OUString sTypeName;
186 0 : sal_Int32 nLength = Descriptor.getLength();
187 0 : sal_Int32 location = nLength;
188 0 : OUString sURL;
189 0 : const PropertyValue *pValue = Descriptor.getConstArray();
190 0 : Reference < XInputStream > xInputStream;
191 0 : for ( sal_Int32 i = 0 ; i < nLength; i++)
192 : {
193 0 : if ( pValue[i].Name == "TypeName" )
194 0 : location=i;
195 0 : else if ( pValue[i].Name == "InputStream" )
196 0 : pValue[i].Value >>= xInputStream;
197 0 : else if ( pValue[i].Name == "URL" )
198 0 : pValue[i].Value >>= sURL;
199 : }
200 :
201 0 : Reference< com::sun::star::ucb::XCommandEnvironment > xEnv;
202 0 : if (!xInputStream.is())
203 : {
204 : try
205 : {
206 0 : Content aContent(sURL, xEnv, mxContext);
207 0 : xInputStream = aContent.openStream();
208 : }
209 0 : catch ( ... )
210 : {
211 0 : return OUString();
212 : }
213 :
214 0 : if (!xInputStream.is())
215 0 : return OUString();
216 : }
217 :
218 0 : WPXSvInputStream input( xInputStream );
219 :
220 0 : if (input.atEOS())
221 0 : return OUString();
222 :
223 0 : confidence = WPDocument::isFileFormatSupported(&input);
224 :
225 0 : if (confidence == WPD_CONFIDENCE_EXCELLENT || confidence == WPD_CONFIDENCE_SUPPORTED_ENCRYPTION)
226 0 : sTypeName = "writer_WordPerfect_Document";
227 :
228 0 : if (!sTypeName.isEmpty())
229 : {
230 0 : if ( location == Descriptor.getLength() )
231 : {
232 0 : Descriptor.realloc(nLength+1);
233 0 : Descriptor[location].Name = "TypeName";
234 : }
235 :
236 0 : Descriptor[location].Value <<=sTypeName;
237 : }
238 :
239 0 : return sTypeName;
240 : }
241 :
242 :
243 : // XInitialization
244 0 : void SAL_CALL WordPerfectImportFilter::initialize( const Sequence< Any >& aArguments )
245 : throw (Exception, RuntimeException)
246 : {
247 : WRITER_DEBUG_MSG(("WordPerfectImportFilter::initialize: Got here!\n"));
248 0 : Sequence < PropertyValue > aAnySeq;
249 0 : sal_Int32 nLength = aArguments.getLength();
250 0 : if ( nLength && ( aArguments[0] >>= aAnySeq ) )
251 : {
252 0 : const PropertyValue *pValue = aAnySeq.getConstArray();
253 0 : nLength = aAnySeq.getLength();
254 0 : for ( sal_Int32 i = 0 ; i < nLength; i++)
255 : {
256 0 : if ( pValue[i].Name == "Type" )
257 : {
258 0 : pValue[i].Value >>= msFilterName;
259 0 : break;
260 : }
261 : }
262 0 : }
263 0 : }
264 0 : OUString WordPerfectImportFilter_getImplementationName ()
265 : throw (RuntimeException)
266 : {
267 0 : return OUString ( "com.sun.star.comp.Writer.WordPerfectImportFilter" );
268 : }
269 :
270 : #define SERVICE_NAME1 "com.sun.star.document.ImportFilter"
271 : #define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection"
272 0 : sal_Bool SAL_CALL WordPerfectImportFilter_supportsService( const OUString &ServiceName )
273 : throw (RuntimeException)
274 : {
275 0 : return ( ServiceName == SERVICE_NAME1 || ServiceName == SERVICE_NAME2 );
276 : }
277 0 : Sequence< OUString > SAL_CALL WordPerfectImportFilter_getSupportedServiceNames( )
278 : throw (RuntimeException)
279 : {
280 0 : Sequence < OUString > aRet(2);
281 0 : OUString *pArray = aRet.getArray();
282 0 : pArray[0] = OUString ( SERVICE_NAME1 );
283 0 : pArray[1] = OUString ( SERVICE_NAME2 );
284 0 : return aRet;
285 : }
286 : #undef SERVICE_NAME2
287 : #undef SERVICE_NAME1
288 :
289 0 : Reference< XInterface > SAL_CALL WordPerfectImportFilter_createInstance( const Reference< XComponentContext > & rContext)
290 : throw( Exception )
291 : {
292 0 : return (cppu::OWeakObject *) new WordPerfectImportFilter( rContext );
293 : }
294 :
295 : // XServiceInfo
296 0 : OUString SAL_CALL WordPerfectImportFilter::getImplementationName( )
297 : throw (RuntimeException)
298 : {
299 0 : return WordPerfectImportFilter_getImplementationName();
300 : }
301 0 : sal_Bool SAL_CALL WordPerfectImportFilter::supportsService( const OUString &rServiceName )
302 : throw (RuntimeException)
303 : {
304 0 : return WordPerfectImportFilter_supportsService( rServiceName );
305 : }
306 0 : Sequence< OUString > SAL_CALL WordPerfectImportFilter::getSupportedServiceNames( )
307 : throw (RuntimeException)
308 : {
309 0 : return WordPerfectImportFilter_getSupportedServiceNames();
310 : }
311 :
312 :
313 0 : WordPerfectImportFilterDialog::WordPerfectImportFilterDialog( const Reference< XComponentContext > & rContext) :
314 0 : mxContext( rContext ) {}
315 :
316 0 : WordPerfectImportFilterDialog::~WordPerfectImportFilterDialog()
317 : {
318 0 : }
319 :
320 0 : void SAL_CALL WordPerfectImportFilterDialog::setTitle( const OUString & )
321 : throw (RuntimeException)
322 : {
323 0 : }
324 :
325 0 : sal_Int16 SAL_CALL WordPerfectImportFilterDialog::execute()
326 : throw (RuntimeException)
327 : {
328 0 : WPXSvInputStream input( mxInputStream );
329 :
330 0 : OString aUtf8Passwd;
331 :
332 0 : WPDConfidence confidence = WPDocument::isFileFormatSupported(&input);
333 :
334 0 : if (WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence)
335 : {
336 0 : int unsuccessfulAttempts = 0;
337 0 : while (true )
338 : {
339 0 : SfxPasswordDialog aPasswdDlg(0);
340 0 : aPasswdDlg.SetMinLen(0);
341 0 : if(!aPasswdDlg.Execute())
342 0 : return com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL;
343 0 : msPassword = aPasswdDlg.GetPassword().GetBuffer();
344 0 : aUtf8Passwd = OUStringToOString(msPassword, RTL_TEXTENCODING_UTF8);
345 0 : if (WPD_PASSWORD_MATCH_OK == WPDocument::verifyPassword(&input, aUtf8Passwd.getStr()))
346 : break;
347 : else
348 0 : unsuccessfulAttempts++;
349 0 : if (unsuccessfulAttempts == 3) // timeout after 3 password atempts
350 0 : return com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL;
351 0 : }
352 : }
353 0 : return com::sun::star::ui::dialogs::ExecutableDialogResults::OK;
354 : }
355 :
356 0 : Sequence<PropertyValue> SAL_CALL WordPerfectImportFilterDialog::getPropertyValues() throw(RuntimeException)
357 : {
358 0 : Sequence<PropertyValue> aRet(1);
359 0 : PropertyValue *pArray = aRet.getArray();
360 :
361 0 : pArray[0].Name = "Password";
362 0 : pArray[0].Value <<= msPassword;
363 :
364 0 : return aRet;
365 : }
366 :
367 0 : void SAL_CALL WordPerfectImportFilterDialog::setPropertyValues( const Sequence<PropertyValue>& aProps)
368 : throw(com::sun::star::beans::UnknownPropertyException, com::sun::star::beans::PropertyVetoException,
369 : com::sun::star::lang::IllegalArgumentException, com::sun::star::lang::WrappedTargetException, RuntimeException)
370 : {
371 0 : const PropertyValue *pPropArray = aProps.getConstArray();
372 0 : long nPropCount = aProps.getLength();
373 0 : for (long i = 0; i < nPropCount; i++)
374 : {
375 0 : const PropertyValue &rProp = pPropArray[i];
376 0 : OUString aPropName = rProp.Name;
377 :
378 0 : if ( aPropName == "Password" )
379 0 : rProp.Value >>= msPassword;
380 0 : else if ( aPropName == "InputStream" )
381 0 : rProp.Value >>= mxInputStream;
382 0 : }
383 0 : }
384 :
385 :
386 : // XServiceInfo
387 0 : OUString SAL_CALL WordPerfectImportFilterDialog::getImplementationName( )
388 : throw (RuntimeException)
389 : {
390 0 : return WordPerfectImportFilterDialog_getImplementationName();
391 : }
392 :
393 0 : sal_Bool SAL_CALL WordPerfectImportFilterDialog::supportsService( const OUString &rServiceName )
394 : throw (RuntimeException)
395 : {
396 0 : return WordPerfectImportFilterDialog_supportsService( rServiceName );
397 : }
398 :
399 0 : Sequence< OUString > SAL_CALL WordPerfectImportFilterDialog::getSupportedServiceNames( )
400 : throw (RuntimeException)
401 : {
402 0 : return WordPerfectImportFilterDialog_getSupportedServiceNames();
403 : }
404 :
405 0 : OUString WordPerfectImportFilterDialog_getImplementationName ()
406 : throw (RuntimeException)
407 : {
408 0 : return OUString ( "com.sun.star.comp.Writer.WordPerfectImportFilterDialog" );
409 : }
410 :
411 : #define SERVICE_NAME "com.sun.star.ui.dialogs.FilterOptionsDialog"
412 0 : sal_Bool SAL_CALL WordPerfectImportFilterDialog_supportsService( const OUString &ServiceName )
413 : throw (RuntimeException)
414 : {
415 0 : return ( ServiceName == SERVICE_NAME );
416 : }
417 :
418 0 : Sequence< OUString > SAL_CALL WordPerfectImportFilterDialog_getSupportedServiceNames( )
419 : throw (RuntimeException)
420 : {
421 0 : Sequence < OUString > aRet(1);
422 0 : OUString *pArray = aRet.getArray();
423 0 : pArray[0] = OUString ( SERVICE_NAME );
424 0 : return aRet;
425 : }
426 : #undef SERVICE_NAME
427 :
428 0 : Reference< XInterface > SAL_CALL WordPerfectImportFilterDialog_createInstance( const Reference< XComponentContext > & rContext)
429 : throw( Exception )
430 : {
431 0 : return (cppu::OWeakObject *) new WordPerfectImportFilterDialog( rContext );
432 0 : }
433 :
434 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|