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