Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*************************************************************************
3 : *
4 : * The Contents of this file are made available subject to the terms of
5 : * either of the following licenses
6 : *
7 : * - GNU Lesser General Public License Version 2.1
8 : * - Sun Industry Standards Source License Version 1.1
9 : *
10 : * Sun Microsystems Inc., October, 2000
11 : *
12 : * GNU Lesser General Public License Version 2.1
13 : * =============================================
14 : * Copyright 2000 by Sun Microsystems, Inc.
15 : * 901 San Antonio Road, Palo Alto, CA 94303, USA
16 : *
17 : * This library is free software; you can redistribute it and/or
18 : * modify it under the terms of the GNU Lesser General Public
19 : * License version 2.1, as published by the Free Software Foundation.
20 : *
21 : * This library is distributed in the hope that it will be useful,
22 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : * Lesser General Public License for more details.
25 : *
26 : * You should have received a copy of the GNU Lesser General Public
27 : * License along with this library; if not, write to the Free Software
28 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 : * MA 02111-1307 USA
30 : *
31 : *
32 : * Sun Industry Standards Source License Version 1.1
33 : * =================================================
34 : * The contents of this file are subject to the Sun Industry Standards
35 : * Source License Version 1.1 (the "License"); You may not use this file
36 : * except in compliance with the License. You may obtain a copy of the
37 : * License at http://www.openoffice.org/license.html.
38 : *
39 : * Software provided under this License is provided on an "AS IS" basis,
40 : * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41 : * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42 : * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43 : * See the License for the specific provisions governing your rights and
44 : * obligations concerning the Software.
45 : *
46 : * The Initial Developer of the Original Code is: IBM Corporation
47 : *
48 : * Copyright: 2008 by IBM Corporation
49 : *
50 : * All Rights Reserved.
51 : *
52 : * Contributor(s): _______________________________________
53 : *
54 : *
55 : ************************************************************************/
56 : /*************************************************************************
57 : * @file
58 : * Circle object.
59 : ************************************************************************/
60 : #include "lwpfilter.hxx"
61 : #include "lwpresource.hxx"
62 : //for sax stream
63 : #include "xfilter/xfsaxstream.hxx"
64 : //for file parser
65 : #include "lwp9reader.hxx"
66 : #include "lwpsvstream.hxx"
67 : //for container reset
68 : #include "xfilter/xffontfactory.hxx"
69 : #include "xfilter/xfstylemanager.hxx"
70 :
71 : #include <osl/file.h>
72 : #include <osl/file.hxx>
73 : #include <vcl/svapp.hxx>
74 : #include <xmloff/attrlist.hxx>
75 : #include <com/sun/star/io/IOException.hpp>
76 : #include <com/sun/star/frame/XDesktop.hpp>
77 : #include <com/sun/star/frame/XController.hpp>
78 : #include <com/sun/star/text/XTextDocument.hpp>
79 : #include <com/sun/star/text/XText.hpp>
80 :
81 : #include <tools/stream.hxx>
82 : #include <sfx2/docfile.hxx>
83 :
84 : #include <boost/scoped_ptr.hpp>
85 :
86 : using namespace ::cppu;
87 : using namespace ::com::sun::star::lang;
88 : using namespace ::com::sun::star::frame;
89 : using namespace ::com::sun::star::text;
90 : using namespace ::com::sun::star::io;
91 : using namespace ::com::sun::star::registry;
92 : using namespace ::com::sun::star::document;
93 : using namespace ::com::sun::star::beans;
94 : using namespace ::com::sun::star::xml::sax;
95 : using namespace ::com::sun::star;
96 : using ::rtl::OUString;
97 : using ::com::sun::star::uno::Sequence;
98 :
99 : sal_Bool IsWordproFile( uno::Reference<XInputStream>& rInputStream);
100 : sal_Bool IsWordproFile(rtl::OUString file);
101 :
102 0 : LWPFilterReader::LWPFilterReader()
103 : {
104 0 : }
105 :
106 0 : LWPFilterReader::~LWPFilterReader()
107 : {
108 0 : }
109 :
110 0 : sal_Bool LWPFilterReader::filter( const Sequence< PropertyValue >& aDescriptor )
111 : throw( RuntimeException )
112 : {
113 0 : ::rtl::OUString sURL;
114 0 : for( sal_Int32 i = 0; i < aDescriptor.getLength(); i++ )
115 : {
116 : //Note we should attempt to use "InputStream" if it exists first!
117 0 : if ( aDescriptor[i].Name == "URL" )
118 0 : aDescriptor[i].Value >>= sURL;
119 : }
120 :
121 0 : SvFileStream inputStream( sURL, STREAM_READ );
122 0 : if ( inputStream.IsEof() || ( inputStream.GetError() != SVSTREAM_OK ) )
123 0 : return sal_False;
124 :
125 0 : return (ReadWordproFile(inputStream, m_DocumentHandler) == 0);
126 : }
127 :
128 0 : void LWPFilterReader::cancel() throw (com::sun::star::uno::RuntimeException)
129 : {
130 0 : }
131 :
132 0 : uno::Reference< XInterface > LWPFilterImportFilter_CreateInstance(
133 : const uno::Reference< XMultiServiceFactory >& rSMgr ) throw( Exception )
134 : {
135 0 : LWPFilterImportFilter *p = new LWPFilterImportFilter( rSMgr );
136 :
137 0 : return uno::Reference< XInterface > ( (OWeakObject* )p );
138 : }
139 :
140 0 : LWPFilterImportFilter::LWPFilterImportFilter( const uno::Reference< XMultiServiceFactory >& xFact )
141 : {
142 : try
143 : {
144 0 : uno::Reference< XDocumentHandler > xDoc( xFact->createInstance( OUString( STR_WRITER_IMPORTER_NAME ) ), UNO_QUERY );
145 :
146 0 : LWPFilterReader *p = new LWPFilterReader;
147 0 : p->setDocumentHandler( xDoc );
148 :
149 0 : uno::Reference< XImporter > xImporter = uno::Reference< XImporter >( xDoc, UNO_QUERY );
150 0 : rImporter = xImporter;
151 0 : uno::Reference< XFilter > xFilter = uno::Reference< XFilter >( p );
152 0 : rFilter = xFilter;
153 : }
154 0 : catch( Exception & )
155 : {
156 0 : exit( 1 );
157 : }
158 0 : }
159 :
160 0 : LWPFilterImportFilter::~LWPFilterImportFilter()
161 : {
162 0 : }
163 :
164 0 : sal_Bool LWPFilterImportFilter::filter( const Sequence< PropertyValue >& aDescriptor )
165 : throw( RuntimeException )
166 : {
167 0 : sal_Bool ret = rFilter->filter( aDescriptor );
168 :
169 0 : return ret;
170 : }
171 :
172 0 : void LWPFilterImportFilter::cancel() throw (::com::sun::star::uno::RuntimeException)
173 : {
174 0 : rFilter->cancel();
175 0 : }
176 :
177 0 : void LWPFilterImportFilter::setTargetDocument( const uno::Reference< XComponent >& xDoc )
178 : throw( IllegalArgumentException, RuntimeException )
179 : {
180 0 : rImporter->setTargetDocument( xDoc );
181 0 : }
182 :
183 0 : OUString LWPFilterImportFilter::getImplementationName() throw()
184 : {
185 0 : return OUString( STR_IMPLEMENTATION_NAME );
186 : }
187 :
188 0 : sal_Bool LWPFilterImportFilter::supportsService( const OUString& ServiceName ) throw()
189 : {
190 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
191 0 : const OUString *pArray = aSNL.getConstArray();
192 :
193 0 : for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
194 : {
195 0 : if ( pArray[i] == ServiceName ) return sal_True;
196 : }
197 :
198 0 : return sal_False;
199 : }
200 :
201 0 : Sequence< OUString> LWPFilterImportFilter::getSupportedServiceNames( void ) throw()
202 : {
203 0 : Sequence< OUString > seq(1);
204 0 : seq.getArray()[0] = OUString( STR_SERVICE_NAME );
205 0 : return seq;
206 : }
207 :
208 :
209 0 : ::rtl::OUString SAL_CALL LWPFilterImportFilter::detect( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
210 : throw (::com::sun::star::uno::RuntimeException)
211 : {
212 0 : rtl::OUString ret;
213 0 : rtl::OUString aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
214 : // opening as template is done when a parameter tells to do so and a template filter can be detected
215 : // (otherwise no valid filter would be found) or if the detected filter is a template filter and
216 : // there is no parameter that forbids to open as template
217 0 : sal_Bool bOpenAsTemplate = sal_False;
218 0 : sal_Int32 nPropertyCount = aDescriptor.getLength();
219 0 : for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
220 : {
221 0 : if ( aDescriptor[nProperty].Name == "TypeName" )
222 : {
223 0 : aDescriptor[nProperty].Value >>= aTypeName;
224 : }
225 0 : else if ( aDescriptor[nProperty].Name == "AsTemplate" )
226 : {
227 0 : bOpenAsTemplate = sal_True;
228 : }
229 : }
230 :
231 0 : for( sal_Int32 i = 0; i < aDescriptor.getLength(); i++ )
232 : {
233 0 : OUString strTemp;
234 0 : aDescriptor[i].Value >>= strTemp;
235 0 : if ( aDescriptor[i].Name == "InputStream" )
236 : {
237 0 : uno::Reference< XInputStream> rInputStream;
238 0 : aDescriptor[i].Value >>= rInputStream;
239 : //
240 : // TODO TRANSFORM IMPLEMENTATION HERE!!!!!!
241 : // and call m_DocumentHandler's SAX mDochods
242 : //
243 0 : if( IsWordproFile(rInputStream) )
244 : {
245 0 : if ( aTypeName == "wordpro_template" )
246 : {
247 0 : if(!bOpenAsTemplate)
248 : {
249 0 : aDescriptor.realloc( nPropertyCount + 1 );
250 0 : aDescriptor[nPropertyCount].Name = ::rtl::OUString("AsTemplate");
251 0 : aDescriptor[nPropertyCount].Value <<= sal_True;
252 : }
253 0 : return OUString("wordpro_template");
254 : }
255 : else
256 : {
257 0 : return OUString("wordpro");
258 : }
259 : }
260 0 : return ret;
261 : }
262 0 : else if ( aDescriptor[i].Name == "URL" )
263 : {
264 0 : OUString sURL;
265 0 : OUString sFileName;
266 :
267 0 : aDescriptor[i].Value >>= sURL;
268 : /*
269 : osl::FileBase::RC rc = osl::FileBase::getSystemPathFromFileURL( sURL, sFileName );
270 : if(rc != osl::FileBase::E_None)
271 : {
272 : SAXException except;
273 : except.Message = OUString( "GDocting system path from URL failed!");
274 : throw except;
275 : }
276 : */
277 : //end with .lwp:
278 0 : if( IsWordproFile(sURL) )
279 : {
280 0 : if ( aTypeName == "wordpro_template" )
281 : {
282 0 : if(!bOpenAsTemplate)
283 : {
284 0 : aDescriptor.realloc( nPropertyCount + 1 );
285 0 : aDescriptor[nPropertyCount].Name = ::rtl::OUString("AsTemplate");
286 0 : aDescriptor[nPropertyCount].Value <<= sal_True;
287 : }
288 0 : return OUString("wordpro_template");
289 : }
290 : else
291 : {
292 0 : return OUString("wordpro");
293 : }
294 : }
295 0 : return ret;
296 : }
297 0 : }
298 0 : return ret;
299 : }
300 :
301 : /**
302 : * @descr decompressed small file
303 : * @param pCompressed - real file stream
304 : * @param pDecompressed - file decompressed, create inside, caller should delete it
305 : * @return success - sal_True, fail - sal_False
306 : */
307 : #include "bento.hxx"
308 : using namespace OpenStormBento;
309 : #include "explode.hxx"
310 0 : sal_Bool Decompress(SvStream *pCompressed, SvStream * & pOutDecompressed)
311 : {
312 0 : pCompressed->Seek(0);
313 0 : std::auto_ptr<SvStream> aDecompressed(new SvMemoryStream(4096, 4096));
314 : unsigned char buffer[512];
315 0 : pCompressed->Read(buffer, 16);
316 0 : aDecompressed->Write(buffer, 16);
317 :
318 0 : boost::scoped_ptr<LwpSvStream> aLwpStream(new LwpSvStream(pCompressed));
319 : LtcBenContainer* pBentoContainer;
320 0 : sal_uLong ulRet = BenOpenContainer(aLwpStream.get(), &pBentoContainer);
321 0 : if (ulRet != BenErr_OK)
322 0 : return sal_False;
323 :
324 0 : boost::scoped_ptr<LtcUtBenValueStream> aWordProData((LtcUtBenValueStream *)pBentoContainer->FindValueStreamWithPropertyName("WordProData"));
325 :
326 0 : if (!aWordProData.get())
327 0 : return sal_False;
328 :
329 : // decompressing
330 0 : Decompression decompress(aWordProData.get(), aDecompressed.get());
331 0 : if (0!= decompress.explode())
332 0 : return sal_False;
333 :
334 0 : sal_uInt32 nPos = aWordProData->GetSize();
335 0 : nPos += 0x10;
336 :
337 0 : pCompressed->Seek(nPos);
338 0 : while (sal_uInt32 iRead = pCompressed->Read(buffer, 512))
339 0 : aDecompressed->Write(buffer, iRead);
340 :
341 : //transfer ownership of aDecompressed's ptr
342 0 : pOutDecompressed = aDecompressed.release();
343 0 : return sal_True;
344 : }
345 :
346 : /**
347 : * @descr Get LwpSvStream, if small file, both compressed/decompressed stream
348 : * Otherwise, only normal stream
349 : * @param pStream - real file stream
350 : * @param LwpSvStream * , created inside, deleted outside
351 : * @param sal_Bool, sal_True -
352 : */
353 6 : sal_Bool GetLwpSvStream(SvStream *pStream, LwpSvStream * & pLwpSvStream)
354 : {
355 6 : SvStream * pDecompressed = NULL;
356 :
357 : sal_uInt32 nTag;
358 6 : pStream->Seek(0x10);
359 6 : *pStream >> nTag;
360 6 : if (nTag != 0x3750574c) // "LWP7"
361 : {
362 : // small file, needs decompression
363 0 : if (!Decompress(pStream, pDecompressed))
364 : {
365 0 : pLwpSvStream = NULL;
366 0 : return sal_True;
367 : }
368 0 : pStream->Seek(0);
369 0 : pDecompressed->Seek(0);
370 : }
371 :
372 6 : pLwpSvStream = NULL;
373 6 : sal_Bool bCompressed = sal_False;
374 6 : if (pDecompressed)
375 : {
376 0 : LwpSvStream *pOriginalLwpSvStream = new LwpSvStream(pStream);
377 0 : pLwpSvStream = new LwpSvStream(pDecompressed, pOriginalLwpSvStream);
378 0 : bCompressed = sal_True;
379 : }
380 : else
381 : {
382 6 : pLwpSvStream = new LwpSvStream(pStream);
383 : }
384 6 : return bCompressed;
385 : }
386 6 : int ReadWordproFile(SvStream &rStream, uno::Reference<XDocumentHandler>& xHandler)
387 : {
388 : try
389 : {
390 6 : LwpSvStream *pRawLwpSvStream = NULL;
391 6 : boost::scoped_ptr<LwpSvStream> aLwpSvStream;
392 6 : boost::scoped_ptr<LwpSvStream> aCompressedLwpSvStream;
393 6 : boost::scoped_ptr<SvStream> aDecompressed;
394 6 : if (GetLwpSvStream(&rStream, pRawLwpSvStream) && pRawLwpSvStream)
395 : {
396 0 : SvStream *pDecompressed = pRawLwpSvStream->GetStream();
397 0 : if (pDecompressed)
398 : {
399 0 : aDecompressed.reset(pDecompressed);
400 0 : aCompressedLwpSvStream.reset(pRawLwpSvStream->GetCompressedStream());
401 : }
402 : }
403 :
404 6 : if (!pRawLwpSvStream)
405 : {
406 : // nothing returned, fail when uncompressing
407 0 : return 1;
408 : }
409 :
410 6 : aLwpSvStream.reset(pRawLwpSvStream);
411 :
412 6 : boost::scoped_ptr<IXFStream> pStrm(new XFSaxStream(xHandler));
413 6 : Lwp9Reader reader(aLwpSvStream.get(), pStrm.get());
414 : //Reset all static objects,because this function may be called many times.
415 6 : XFGlobalReset();
416 6 : reader.Read();
417 :
418 6 : return 0;
419 : }
420 6 : catch (...)
421 : {
422 3 : return 1;
423 : }
424 : }
425 :
426 0 : void ErrorMsg(int /*iErrCode*/)
427 : {
428 :
429 0 : }
430 :
431 : /**
432 : * @descr Compare if pBuf equals with the first 16 bytes
433 : * @param pBuf that contains the file data
434 : * @return if equals with the Word Pro characteristic strings
435 : */
436 0 : sal_Bool IsWordProStr(const sal_Int8 *pBuf)
437 : {
438 0 : sal_Bool bRet = sal_True;
439 : const sal_Int8 pLotusLwp[] =
440 : {
441 : 0x57, 0x6F, 0x72, 0x64,
442 : 0x50, 0x72, 0x6F
443 0 : };
444 0 : for(size_t i=0; i<sizeof(pLotusLwp); ++i)
445 : {
446 0 : if( pBuf[i] != pLotusLwp[i] )
447 : {
448 0 : bRet = sal_False;
449 : }
450 : }
451 0 : return bRet;
452 : }
453 :
454 0 : sal_Bool IsWordproFile(rtl::OUString file)
455 : {
456 0 : sal_Bool bRet = sal_False;
457 0 : SfxMedium aMedium( file, STREAM_STD_READ);
458 0 : SvStream* pStm = aMedium.GetInStream();
459 :
460 0 : if(pStm)
461 : {
462 : sal_Int8 buf[16];
463 0 : bRet = sal_True;
464 :
465 0 : pStm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
466 0 : pStm->Seek(STREAM_SEEK_TO_BEGIN);
467 0 : sal_Size nRead = pStm->Read(buf, sizeof(buf));
468 0 : if( nRead< sizeof(buf) )
469 0 : bRet = sal_False;
470 : else
471 0 : bRet = IsWordProStr(buf);
472 : }
473 0 : return bRet;
474 : }
475 :
476 :
477 0 : sal_Bool IsWordproFile( uno::Reference<XInputStream>& rInputStream)
478 : {
479 0 : Sequence<sal_Int8> aData;
480 0 : sal_Bool bRet = sal_False;
481 :
482 0 : sal_Int32 nRead = rInputStream->readBytes(aData, 16);
483 0 : if( nRead != 16 )
484 : {
485 0 : bRet = sal_False;
486 : }
487 : else
488 : {
489 0 : const sal_Int8 *data = aData.getConstArray();
490 0 : bRet = IsWordProStr(data);
491 : }
492 0 : return bRet;
493 : }
494 :
495 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|