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 ::com::sun::star::uno::Sequence;
97 :
98 : sal_Bool IsWordproFile( uno::Reference<XInputStream>& rInputStream);
99 : sal_Bool IsWordproFile(OUString file);
100 :
101 0 : LWPFilterReader::LWPFilterReader()
102 : {
103 0 : }
104 :
105 0 : LWPFilterReader::~LWPFilterReader()
106 : {
107 0 : }
108 :
109 0 : sal_Bool LWPFilterReader::filter( const Sequence< PropertyValue >& aDescriptor )
110 : throw( RuntimeException )
111 : {
112 0 : OUString sURL;
113 0 : for( sal_Int32 i = 0; i < aDescriptor.getLength(); i++ )
114 : {
115 : //Note we should attempt to use "InputStream" if it exists first!
116 0 : if ( aDescriptor[i].Name == "URL" )
117 0 : aDescriptor[i].Value >>= sURL;
118 : }
119 :
120 0 : SvFileStream inputStream( sURL, STREAM_READ );
121 0 : if ( inputStream.IsEof() || ( inputStream.GetError() != SVSTREAM_OK ) )
122 0 : return sal_False;
123 :
124 0 : return (ReadWordproFile(inputStream, m_DocumentHandler) == 0);
125 : }
126 :
127 0 : void LWPFilterReader::cancel() throw (com::sun::star::uno::RuntimeException)
128 : {
129 0 : }
130 :
131 0 : uno::Reference< XInterface > LWPFilterImportFilter_CreateInstance(
132 : const uno::Reference< XMultiServiceFactory >& rSMgr ) throw( Exception )
133 : {
134 0 : LWPFilterImportFilter *p = new LWPFilterImportFilter( rSMgr );
135 :
136 0 : return uno::Reference< XInterface > ( (OWeakObject* )p );
137 : }
138 :
139 0 : LWPFilterImportFilter::LWPFilterImportFilter( const uno::Reference< XMultiServiceFactory >& xFact )
140 : {
141 : try
142 : {
143 0 : uno::Reference< XDocumentHandler > xDoc( xFact->createInstance( OUString( STR_WRITER_IMPORTER_NAME ) ), UNO_QUERY );
144 :
145 0 : LWPFilterReader *p = new LWPFilterReader;
146 0 : p->setDocumentHandler( xDoc );
147 :
148 0 : uno::Reference< XImporter > xImporter = uno::Reference< XImporter >( xDoc, UNO_QUERY );
149 0 : rImporter = xImporter;
150 0 : uno::Reference< XFilter > xFilter = uno::Reference< XFilter >( p );
151 0 : rFilter = xFilter;
152 : }
153 0 : catch( Exception & )
154 : {
155 0 : exit( 1 );
156 : }
157 0 : }
158 :
159 0 : LWPFilterImportFilter::~LWPFilterImportFilter()
160 : {
161 0 : }
162 :
163 0 : sal_Bool LWPFilterImportFilter::filter( const Sequence< PropertyValue >& aDescriptor )
164 : throw( RuntimeException )
165 : {
166 0 : sal_Bool ret = rFilter->filter( aDescriptor );
167 :
168 0 : return ret;
169 : }
170 :
171 0 : void LWPFilterImportFilter::cancel() throw (::com::sun::star::uno::RuntimeException)
172 : {
173 0 : rFilter->cancel();
174 0 : }
175 :
176 0 : void LWPFilterImportFilter::setTargetDocument( const uno::Reference< XComponent >& xDoc )
177 : throw( IllegalArgumentException, RuntimeException )
178 : {
179 0 : rImporter->setTargetDocument( xDoc );
180 0 : }
181 :
182 0 : OUString LWPFilterImportFilter::getImplementationName() throw()
183 : {
184 0 : return OUString( STR_IMPLEMENTATION_NAME );
185 : }
186 :
187 0 : sal_Bool LWPFilterImportFilter::supportsService( const OUString& ServiceName ) throw()
188 : {
189 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
190 0 : const OUString *pArray = aSNL.getConstArray();
191 :
192 0 : for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
193 : {
194 0 : if ( pArray[i] == ServiceName ) return sal_True;
195 : }
196 :
197 0 : return sal_False;
198 : }
199 :
200 0 : Sequence< OUString> LWPFilterImportFilter::getSupportedServiceNames( void ) throw()
201 : {
202 0 : Sequence< OUString > seq(1);
203 0 : seq.getArray()[0] = OUString( STR_SERVICE_NAME );
204 0 : return seq;
205 : }
206 :
207 :
208 0 : OUString SAL_CALL LWPFilterImportFilter::detect( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
209 : throw (::com::sun::star::uno::RuntimeException)
210 : {
211 0 : OUString ret;
212 0 : OUString aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
213 : // opening as template is done when a parameter tells to do so and a template filter can be detected
214 : // (otherwise no valid filter would be found) or if the detected filter is a template filter and
215 : // there is no parameter that forbids to open as template
216 0 : sal_Bool bOpenAsTemplate = sal_False;
217 0 : sal_Int32 nPropertyCount = aDescriptor.getLength();
218 0 : for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
219 : {
220 0 : if ( aDescriptor[nProperty].Name == "TypeName" )
221 : {
222 0 : aDescriptor[nProperty].Value >>= aTypeName;
223 : }
224 0 : else if ( aDescriptor[nProperty].Name == "AsTemplate" )
225 : {
226 0 : bOpenAsTemplate = sal_True;
227 : }
228 : }
229 :
230 0 : for( sal_Int32 i = 0; i < aDescriptor.getLength(); i++ )
231 : {
232 0 : OUString strTemp;
233 0 : aDescriptor[i].Value >>= strTemp;
234 0 : if ( aDescriptor[i].Name == "InputStream" )
235 : {
236 0 : uno::Reference< XInputStream> rInputStream;
237 0 : aDescriptor[i].Value >>= rInputStream;
238 : //
239 : // TODO TRANSFORM IMPLEMENTATION HERE!!!!!!
240 : // and call m_DocumentHandler's SAX mDochods
241 : //
242 0 : if( IsWordproFile(rInputStream) )
243 : {
244 0 : if ( aTypeName == "wordpro_template" )
245 : {
246 0 : if(!bOpenAsTemplate)
247 : {
248 0 : aDescriptor.realloc( nPropertyCount + 1 );
249 0 : aDescriptor[nPropertyCount].Name = OUString("AsTemplate");
250 0 : aDescriptor[nPropertyCount].Value <<= sal_True;
251 : }
252 0 : return OUString("wordpro_template");
253 : }
254 : else
255 : {
256 0 : return OUString("wordpro");
257 : }
258 : }
259 0 : return ret;
260 : }
261 0 : else if ( aDescriptor[i].Name == "URL" )
262 : {
263 0 : OUString sURL;
264 :
265 0 : aDescriptor[i].Value >>= sURL;
266 : /*
267 : osl::FileBase::RC rc = osl::FileBase::getSystemPathFromFileURL( sURL, sFileName );
268 : if(rc != osl::FileBase::E_None)
269 : {
270 : SAXException except;
271 : except.Message = OUString( "GDocting system path from URL failed!");
272 : throw except;
273 : }
274 : */
275 : //end with .lwp:
276 0 : if( IsWordproFile(sURL) )
277 : {
278 0 : if ( aTypeName == "wordpro_template" )
279 : {
280 0 : if(!bOpenAsTemplate)
281 : {
282 0 : aDescriptor.realloc( nPropertyCount + 1 );
283 0 : aDescriptor[nPropertyCount].Name = OUString("AsTemplate");
284 0 : aDescriptor[nPropertyCount].Value <<= sal_True;
285 : }
286 0 : return OUString("wordpro_template");
287 : }
288 : else
289 : {
290 0 : return OUString("wordpro");
291 : }
292 : }
293 0 : return ret;
294 : }
295 0 : }
296 0 : return ret;
297 : }
298 :
299 : /**
300 : * @descr decompressed small file
301 : * @param pCompressed - real file stream
302 : * @param pDecompressed - file decompressed, create inside, caller should delete it
303 : * @return success - sal_True, fail - sal_False
304 : */
305 : #include "bento.hxx"
306 : using namespace OpenStormBento;
307 : #include "explode.hxx"
308 0 : sal_Bool Decompress(SvStream *pCompressed, SvStream * & pOutDecompressed)
309 : {
310 0 : pCompressed->Seek(0);
311 0 : std::auto_ptr<SvStream> aDecompressed(new SvMemoryStream(4096, 4096));
312 : unsigned char buffer[512];
313 0 : pCompressed->Read(buffer, 16);
314 0 : aDecompressed->Write(buffer, 16);
315 :
316 0 : boost::scoped_ptr<LwpSvStream> aLwpStream(new LwpSvStream(pCompressed));
317 : LtcBenContainer* pBentoContainer;
318 0 : sal_uLong ulRet = BenOpenContainer(aLwpStream.get(), &pBentoContainer);
319 0 : if (ulRet != BenErr_OK)
320 0 : return sal_False;
321 :
322 0 : boost::scoped_ptr<LtcUtBenValueStream> aWordProData((LtcUtBenValueStream *)pBentoContainer->FindValueStreamWithPropertyName("WordProData"));
323 :
324 0 : if (!aWordProData.get())
325 0 : return sal_False;
326 :
327 : // decompressing
328 0 : Decompression decompress(aWordProData.get(), aDecompressed.get());
329 0 : if (0!= decompress.explode())
330 0 : return sal_False;
331 :
332 0 : sal_uInt32 nPos = aWordProData->GetSize();
333 0 : nPos += 0x10;
334 :
335 0 : pCompressed->Seek(nPos);
336 0 : while (sal_uInt32 iRead = pCompressed->Read(buffer, 512))
337 0 : aDecompressed->Write(buffer, iRead);
338 :
339 : //transfer ownership of aDecompressed's ptr
340 0 : pOutDecompressed = aDecompressed.release();
341 0 : return sal_True;
342 : }
343 :
344 : /**
345 : * @descr Get LwpSvStream, if small file, both compressed/decompressed stream
346 : * Otherwise, only normal stream
347 : * @param pStream - real file stream
348 : * @param LwpSvStream * , created inside, deleted outside
349 : * @param sal_Bool, sal_True -
350 : */
351 6 : sal_Bool GetLwpSvStream(SvStream *pStream, LwpSvStream * & pLwpSvStream)
352 : {
353 6 : SvStream * pDecompressed = NULL;
354 :
355 : sal_uInt32 nTag;
356 6 : pStream->Seek(0x10);
357 6 : *pStream >> nTag;
358 6 : if (nTag != 0x3750574c) // "LWP7"
359 : {
360 : // small file, needs decompression
361 0 : if (!Decompress(pStream, pDecompressed))
362 : {
363 0 : pLwpSvStream = NULL;
364 0 : return sal_True;
365 : }
366 0 : pStream->Seek(0);
367 0 : pDecompressed->Seek(0);
368 : }
369 :
370 6 : pLwpSvStream = NULL;
371 6 : sal_Bool bCompressed = sal_False;
372 6 : if (pDecompressed)
373 : {
374 0 : LwpSvStream *pOriginalLwpSvStream = new LwpSvStream(pStream);
375 0 : pLwpSvStream = new LwpSvStream(pDecompressed, pOriginalLwpSvStream);
376 0 : bCompressed = sal_True;
377 : }
378 : else
379 : {
380 6 : pLwpSvStream = new LwpSvStream(pStream);
381 : }
382 6 : return bCompressed;
383 : }
384 6 : int ReadWordproFile(SvStream &rStream, uno::Reference<XDocumentHandler>& xHandler)
385 : {
386 : try
387 : {
388 6 : LwpSvStream *pRawLwpSvStream = NULL;
389 6 : boost::scoped_ptr<LwpSvStream> aLwpSvStream;
390 12 : boost::scoped_ptr<LwpSvStream> aCompressedLwpSvStream;
391 12 : boost::scoped_ptr<SvStream> aDecompressed;
392 6 : if (GetLwpSvStream(&rStream, pRawLwpSvStream) && pRawLwpSvStream)
393 : {
394 0 : SvStream *pDecompressed = pRawLwpSvStream->GetStream();
395 0 : if (pDecompressed)
396 : {
397 0 : aDecompressed.reset(pDecompressed);
398 0 : aCompressedLwpSvStream.reset(pRawLwpSvStream->GetCompressedStream());
399 : }
400 : }
401 :
402 6 : if (!pRawLwpSvStream)
403 : {
404 : // nothing returned, fail when uncompressing
405 0 : return 1;
406 : }
407 :
408 6 : aLwpSvStream.reset(pRawLwpSvStream);
409 :
410 12 : boost::scoped_ptr<IXFStream> pStrm(new XFSaxStream(xHandler));
411 12 : Lwp9Reader reader(aLwpSvStream.get(), pStrm.get());
412 : //Reset all static objects,because this function may be called many times.
413 6 : XFGlobalReset();
414 6 : reader.Read();
415 :
416 9 : return 0;
417 : }
418 6 : catch (...)
419 : {
420 3 : return 1;
421 : }
422 : }
423 :
424 0 : void ErrorMsg(int /*iErrCode*/)
425 : {
426 :
427 0 : }
428 :
429 : /**
430 : * @descr Compare if pBuf equals with the first 16 bytes
431 : * @param pBuf that contains the file data
432 : * @return if equals with the Word Pro characteristic strings
433 : */
434 0 : sal_Bool IsWordProStr(const sal_Int8 *pBuf)
435 : {
436 0 : sal_Bool bRet = sal_True;
437 : const sal_Int8 pLotusLwp[] =
438 : {
439 : 0x57, 0x6F, 0x72, 0x64,
440 : 0x50, 0x72, 0x6F
441 0 : };
442 0 : for(size_t i=0; i<sizeof(pLotusLwp); ++i)
443 : {
444 0 : if( pBuf[i] != pLotusLwp[i] )
445 : {
446 0 : bRet = sal_False;
447 : }
448 : }
449 0 : return bRet;
450 : }
451 :
452 0 : sal_Bool IsWordproFile(OUString file)
453 : {
454 0 : sal_Bool bRet = sal_False;
455 0 : SfxMedium aMedium( file, STREAM_STD_READ);
456 0 : SvStream* pStm = aMedium.GetInStream();
457 :
458 0 : if(pStm)
459 : {
460 : sal_Int8 buf[16];
461 0 : bRet = sal_True;
462 :
463 0 : pStm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
464 0 : pStm->Seek(STREAM_SEEK_TO_BEGIN);
465 0 : sal_Size nRead = pStm->Read(buf, sizeof(buf));
466 0 : if( nRead< sizeof(buf) )
467 0 : bRet = sal_False;
468 : else
469 0 : bRet = IsWordProStr(buf);
470 : }
471 0 : return bRet;
472 : }
473 :
474 :
475 0 : sal_Bool IsWordproFile( uno::Reference<XInputStream>& rInputStream)
476 : {
477 0 : Sequence<sal_Int8> aData;
478 0 : sal_Bool bRet = sal_False;
479 :
480 0 : sal_Int32 nRead = rInputStream->readBytes(aData, 16);
481 0 : if( nRead != 16 )
482 : {
483 0 : bRet = sal_False;
484 : }
485 : else
486 : {
487 0 : const sal_Int8 *data = aData.getConstArray();
488 0 : bRet = IsWordProStr(data);
489 : }
490 0 : return bRet;
491 3 : }
492 :
493 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|