1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pdfiadaptor.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_sdext.hxx"
35 #include "pdfiadaptor.hxx"
36 #include "filterdet.hxx"
37 #include "saxemitter.hxx"
38 #include "odfemitter.hxx"
39 #include "inc/wrapper.hxx"
40 #include "inc/contentsink.hxx"
41 #include "tree/pdfiprocessor.hxx"
44 #include <osl/thread.h>
45 #include <osl/diagnose.h>
46 #include <cppuhelper/factory.hxx>
47 #include <cppuhelper/implementationentry.hxx>
48 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
49 #include <com/sun/star/uno/RuntimeException.hpp>
50 #include <com/sun/star/io/XInputStream.hpp>
51 #include <com/sun/star/frame/XLoadable.hpp>
52 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
53 #include <com/sun/star/io/XSeekable.hpp>
56 #include <boost/shared_ptr.hpp>
58 using namespace com::sun::star
;
64 PDFIHybridAdaptor::PDFIHybridAdaptor( const uno::Reference
< uno::XComponentContext
>& xContext
) :
65 PDFIHybridAdaptorBase( m_aMutex
),
66 m_xContext( xContext
),
72 sal_Bool SAL_CALL
PDFIHybridAdaptor::filter( const uno::Sequence
< beans::PropertyValue
>& rFilterData
) throw( uno::RuntimeException
)
74 sal_Bool bRet
= sal_False
;
77 uno::Reference
< io::XStream
> xSubStream
;
79 const beans::PropertyValue
* pAttribs
= rFilterData
.getConstArray();
80 sal_Int32 nAttribs
= rFilterData
.getLength();
81 sal_Int32 nPwPos
= -1;
82 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
84 #if OSL_DEBUG_LEVEL > 1
85 rtl::OUString
aVal( RTL_CONSTASCII_USTRINGPARAM( "<no string>" ) );
86 pAttribs
[i
].Value
>>= aVal
;
87 OSL_TRACE( "filter: Attrib: %s = %s\n",
88 rtl::OUStringToOString( pAttribs
[i
].Name
, RTL_TEXTENCODING_UTF8
).getStr(),
89 rtl::OUStringToOString( aVal
, RTL_TEXTENCODING_UTF8
).getStr() );
91 if( pAttribs
[i
].Name
.equalsAscii( "EmbeddedSubstream" ) )
92 pAttribs
[i
].Value
>>= xSubStream
;
93 else if( pAttribs
[i
].Name
.equalsAscii( "Password" ) )
96 pAttribs
[i
].Value
>>= aPwd
;
99 bool bAddPwdProp
= false;
100 if( ! xSubStream
.is() )
102 uno::Reference
< io::XInputStream
> xInput
;
103 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
105 if( pAttribs
[i
].Name
.equalsAscii( "InputStream" ) )
107 pAttribs
[i
].Value
>>= xInput
;
113 // TODO(P2): extracting hybrid substream twice - once during detection, second time here
114 uno::Reference
< io::XSeekable
> xSeek( xInput
, uno::UNO_QUERY
);
117 oslFileHandle aFile
= NULL
;
118 sal_uInt64 nWritten
= 0;
120 if( osl_createTempFile( NULL
, &aFile
, &aURL
.pData
) == osl_File_E_None
)
122 OSL_TRACE( "created temp file %s\n", rtl::OUStringToOString( aURL
, RTL_TEXTENCODING_UTF8
).getStr() );
123 const sal_Int32 nBufSize
= 4096;
124 uno::Sequence
<sal_Int8
> aBuf(nBufSize
);
129 nBytes
= xInput
->readBytes( aBuf
, nBufSize
);
132 osl_writeFile( aFile
, aBuf
.getConstArray(), nBytes
, &nWritten
);
133 if( static_cast<sal_Int32
>(nWritten
) != nBytes
)
139 } while( nBytes
== nBufSize
);
140 osl_closeFile( aFile
);
143 rtl::OUString aEmbedMimetype
;
144 rtl::OUString
aOrgPwd( aPwd
);
145 xSubStream
= getAdditionalStream( aURL
, aEmbedMimetype
, aPwd
, m_xContext
, rFilterData
, true );
146 if( aOrgPwd
!= aPwd
)
149 osl_removeFile( aURL
.pData
);
155 if( xSubStream
.is() )
157 uno::Sequence
< uno::Any
> aArgs( 2 );
158 aArgs
[0] <<= m_xModel
;
159 aArgs
[1] <<= xSubStream
;
161 OSL_TRACE( "try to instantiate subfilter\n" );
162 uno::Reference
< document::XFilter
> xSubFilter
;
164 xSubFilter
= uno::Reference
<document::XFilter
>(
165 m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
166 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.OwnSubFilter" ) ),
171 catch(uno::Exception
& e
)
174 OSL_TRACE( "subfilter exception: %s\n",
175 OUStringToOString( e
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
178 OSL_TRACE( "subfilter: %p\n", xSubFilter
.get() );
179 if( xSubFilter
.is() )
183 uno::Sequence
<beans::PropertyValue
> aFilterData( rFilterData
);
186 nPwPos
= aFilterData
.getLength();
187 aFilterData
.realloc( nPwPos
+1 );
188 aFilterData
[nPwPos
].Name
= rtl::OUString(
189 RTL_CONSTASCII_USTRINGPARAM( "Password" ) );
191 aFilterData
[nPwPos
].Value
<<= aPwd
;
192 bRet
= xSubFilter
->filter( aFilterData
);
195 bRet
= xSubFilter
->filter( rFilterData
);
198 #if OSL_DEBUG_LEVEL > 1
200 OSL_TRACE( "PDFIAdaptor::filter: no embedded substream set\n" );
203 #if OSL_DEBUG_LEVEL > 1
205 OSL_TRACE( "PDFIAdaptor::filter: no model set\n" );
211 void SAL_CALL
PDFIHybridAdaptor::cancel() throw()
216 void SAL_CALL
PDFIHybridAdaptor::setTargetDocument( const uno::Reference
< lang::XComponent
>& xDocument
) throw( lang::IllegalArgumentException
)
218 OSL_TRACE( "PDFIAdaptor::setTargetDocument\n" );
219 m_xModel
= uno::Reference
< frame::XModel
>( xDocument
, uno::UNO_QUERY
);
220 if( xDocument
.is() && ! m_xModel
.is() )
221 throw lang::IllegalArgumentException();
224 //---------------------------------------------------------------------------------------
226 PDFIRawAdaptor::PDFIRawAdaptor( const uno::Reference
< uno::XComponentContext
>& xContext
) :
227 PDFIAdaptorBase( m_aMutex
),
228 m_xContext( xContext
),
231 m_bEnableToplevelText(false)
235 void PDFIRawAdaptor::setTreeVisitorFactory(const TreeVisitorFactorySharedPtr
& rVisitorFactory
)
237 m_pVisitorFactory
= rVisitorFactory
;
240 bool PDFIRawAdaptor::parse( const uno::Reference
<io::XInputStream
>& xInput
,
241 const uno::Reference
<task::XInteractionHandler
>& xIHdl
,
242 const rtl::OUString
& rPwd
,
243 const uno::Reference
<task::XStatusIndicator
>& xStatus
,
244 const XmlEmitterSharedPtr
& rEmitter
,
245 const rtl::OUString
& rURL
)
247 // container for metaformat
248 boost::shared_ptr
<PDFIProcessor
> pSink(
249 new PDFIProcessor(xStatus
));
252 if( m_bEnableToplevelText
)
253 pSink
->enableToplevelText();
257 if( xInput
.is() && (!rURL
.getLength() || rURL
.compareToAscii( "file:", 5 ) != 0) )
258 bSuccess
= xpdf_ImportFromStream( xInput
, pSink
, xIHdl
, rPwd
, m_xContext
);
260 bSuccess
= xpdf_ImportFromFile( rURL
, pSink
, xIHdl
, rPwd
, m_xContext
);
263 pSink
->emit(*rEmitter
,*m_pVisitorFactory
);
268 bool PDFIRawAdaptor::odfConvert( const rtl::OUString
& rURL
,
269 const uno::Reference
<io::XOutputStream
>& xOutput
,
270 const uno::Reference
<task::XStatusIndicator
>& xStatus
)
272 XmlEmitterSharedPtr pEmitter
= createOdfEmitter(xOutput
);
273 const bool bSuccess
= parse(uno::Reference
<io::XInputStream
>(),
274 uno::Reference
<task::XInteractionHandler
>(),
276 xStatus
,pEmitter
,rURL
);
278 // tell input stream that it is no longer needed
279 xOutput
->closeOutput();
285 sal_Bool SAL_CALL
PDFIRawAdaptor::importer( const uno::Sequence
< beans::PropertyValue
>& rSourceData
,
286 const uno::Reference
< xml::sax::XDocumentHandler
>& rHdl
,
287 const uno::Sequence
< rtl::OUString
>& /*rUserData*/ ) throw( uno::RuntimeException
)
289 // get the InputStream carrying the PDF content
290 uno::Reference
< io::XInputStream
> xInput
;
291 uno::Reference
< task::XStatusIndicator
> xStatus
;
292 uno::Reference
< task::XInteractionHandler
> xInteractionHandler
;
295 const beans::PropertyValue
* pAttribs
= rSourceData
.getConstArray();
296 sal_Int32 nAttribs
= rSourceData
.getLength();
297 for( sal_Int32 i
= 0; i
< nAttribs
; i
++, pAttribs
++ )
299 OSL_TRACE("importer Attrib: %s\n", OUStringToOString( pAttribs
->Name
, RTL_TEXTENCODING_UTF8
).getStr() );
300 if( pAttribs
->Name
.equalsAscii( "InputStream" ) )
301 pAttribs
->Value
>>= xInput
;
302 else if( pAttribs
->Name
.equalsAscii( "URL" ) )
303 pAttribs
->Value
>>= aURL
;
304 else if( pAttribs
->Name
.equalsAscii( "StatusIndicator" ) )
305 pAttribs
->Value
>>= xStatus
;
306 else if( pAttribs
->Name
.equalsAscii( "InteractionHandler" ) )
307 pAttribs
->Value
>>= xInteractionHandler
;
308 else if( pAttribs
->Name
.equalsAscii( "Password" ) )
309 pAttribs
->Value
>>= aPwd
;
314 XmlEmitterSharedPtr pEmitter
= createSaxEmitter(rHdl
);
315 const bool bSuccess
= parse(xInput
,xInteractionHandler
, aPwd
, xStatus
,pEmitter
,aURL
);
317 // tell input stream that it is no longer needed
318 xInput
->closeInput();
325 void SAL_CALL
PDFIRawAdaptor::setTargetDocument( const uno::Reference
< lang::XComponent
>& xDocument
) throw( lang::IllegalArgumentException
)
327 OSL_TRACE( "PDFIAdaptor::setTargetDocument\n" );
328 m_xModel
= uno::Reference
< frame::XModel
>( xDocument
, uno::UNO_QUERY
);
329 if( xDocument
.is() && ! m_xModel
.is() )
330 throw lang::IllegalArgumentException();