1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "pdfiadaptor.hxx"
22 #include "filterdet.hxx"
23 #include "saxemitter.hxx"
24 #include "odfemitter.hxx"
25 #include "inc/wrapper.hxx"
26 #include "inc/contentsink.hxx"
27 #include "tree/pdfiprocessor.hxx"
30 #include <osl/thread.h>
31 #include "sal/log.hxx"
33 #include <cppuhelper/factory.hxx>
34 #include <cppuhelper/implementationentry.hxx>
35 #include <cppuhelper/supportsservice.hxx>
36 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
37 #include <com/sun/star/uno/RuntimeException.hpp>
38 #include <com/sun/star/io/XInputStream.hpp>
39 #include <com/sun/star/frame/XLoadable.hpp>
40 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
41 #include <com/sun/star/io/XSeekable.hpp>
44 #include <boost/shared_ptr.hpp>
46 using namespace com::sun::star
;
52 PDFIHybridAdaptor::PDFIHybridAdaptor( const uno::Reference
< uno::XComponentContext
>& xContext
) :
53 PDFIHybridAdaptorBase( m_aMutex
),
54 m_xContext( xContext
),
60 sal_Bool SAL_CALL
PDFIHybridAdaptor::filter( const uno::Sequence
< beans::PropertyValue
>& rFilterData
) throw( uno::RuntimeException
, std::exception
)
65 uno::Reference
< io::XStream
> xSubStream
;
67 const beans::PropertyValue
* pAttribs
= rFilterData
.getConstArray();
68 sal_Int32 nAttribs
= rFilterData
.getLength();
69 sal_Int32 nPwPos
= -1;
70 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
72 SAL_INFO("sdext.pdfimport", "filter: Attrib: " << pAttribs
[i
].Name
73 << " = " << (pAttribs
[i
].Value
.has
<OUString
>()
74 ? pAttribs
[i
].Value
.get
<OUString
>()
75 : OUString("<no string>"))
77 if ( pAttribs
[i
].Name
== "EmbeddedSubstream" )
78 pAttribs
[i
].Value
>>= xSubStream
;
79 else if ( pAttribs
[i
].Name
== "Password" )
82 pAttribs
[i
].Value
>>= aPwd
;
85 bool bAddPwdProp
= false;
86 if( ! xSubStream
.is() )
88 uno::Reference
< io::XInputStream
> xInput
;
89 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
91 if ( pAttribs
[i
].Name
== "InputStream" )
93 pAttribs
[i
].Value
>>= xInput
;
99 // TODO(P2): extracting hybrid substream twice - once during detection, second time here
100 uno::Reference
< io::XSeekable
> xSeek( xInput
, uno::UNO_QUERY
);
103 oslFileHandle aFile
= NULL
;
104 sal_uInt64 nWritten
= 0;
106 if( osl_createTempFile( NULL
, &aFile
, &aURL
.pData
) == osl_File_E_None
)
108 SAL_INFO("sdext.pdfimport", "created temp file " << aURL
);
109 const sal_Int32 nBufSize
= 4096;
110 uno::Sequence
<sal_Int8
> aBuf(nBufSize
);
115 nBytes
= xInput
->readBytes( aBuf
, nBufSize
);
118 osl_writeFile( aFile
, aBuf
.getConstArray(), nBytes
, &nWritten
);
119 if( static_cast<sal_Int32
>(nWritten
) != nBytes
)
125 } while( nBytes
== nBufSize
);
126 osl_closeFile( aFile
);
129 OUString aEmbedMimetype
;
130 OUString
aOrgPwd( aPwd
);
131 xSubStream
= getAdditionalStream( aURL
, aEmbedMimetype
, aPwd
, m_xContext
, rFilterData
, true );
132 if( aOrgPwd
!= aPwd
)
135 osl_removeFile( aURL
.pData
);
141 if( xSubStream
.is() )
143 uno::Sequence
< uno::Any
> aArgs( 2 );
144 aArgs
[0] <<= m_xModel
;
145 aArgs
[1] <<= xSubStream
;
147 SAL_INFO("sdext.pdfimport", "try to instantiate subfilter" );
148 uno::Reference
< document::XFilter
> xSubFilter
;
150 xSubFilter
= uno::Reference
<document::XFilter
>(
151 m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
152 OUString( "com.sun.star.document.OwnSubFilter" ),
157 catch(const uno::Exception
& e
)
160 SAL_INFO("sdext.pdfimport", "subfilter exception: " << e
.Message
<< "\n");
163 SAL_INFO("sdext.pdfimport", "subfilter: " << xSubFilter
.get() );
164 if( xSubFilter
.is() )
168 uno::Sequence
<beans::PropertyValue
> aFilterData( rFilterData
);
171 nPwPos
= aFilterData
.getLength();
172 aFilterData
.realloc( nPwPos
+1 );
173 aFilterData
[nPwPos
].Name
= "Password";
175 aFilterData
[nPwPos
].Value
<<= aPwd
;
176 bRet
= xSubFilter
->filter( aFilterData
);
179 bRet
= xSubFilter
->filter( rFilterData
);
183 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no embedded substream set" );
186 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no model set" );
191 void SAL_CALL
PDFIHybridAdaptor::cancel() throw(std::exception
)
196 void SAL_CALL
PDFIHybridAdaptor::setTargetDocument( const uno::Reference
< lang::XComponent
>& xDocument
) throw( lang::IllegalArgumentException
, std::exception
)
198 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
199 m_xModel
= uno::Reference
< frame::XModel
>( xDocument
, uno::UNO_QUERY
);
200 if( xDocument
.is() && ! m_xModel
.is() )
201 throw lang::IllegalArgumentException();
204 OUString
PDFIHybridAdaptor::getImplementationName()
205 throw (css::uno::RuntimeException
, std::exception
)
207 return OUString("org.libreoffice.comp.documents.HybridPDFImport");
210 sal_Bool
PDFIHybridAdaptor::supportsService(OUString
const & ServiceName
)
211 throw (css::uno::RuntimeException
, std::exception
)
213 return cppu::supportsService(this, ServiceName
);
216 css::uno::Sequence
<OUString
> PDFIHybridAdaptor::getSupportedServiceNames()
217 throw (css::uno::RuntimeException
, std::exception
)
219 return css::uno::Sequence
<OUString
>{"com.sun.star.document.ImportFilter"};
222 PDFIRawAdaptor::PDFIRawAdaptor( OUString
const & implementationName
, const uno::Reference
< uno::XComponentContext
>& xContext
) :
223 PDFIAdaptorBase( m_aMutex
),
224 m_implementationName(implementationName
),
225 m_xContext( xContext
),
228 m_bEnableToplevelText(false)
232 void PDFIRawAdaptor::setTreeVisitorFactory(const TreeVisitorFactorySharedPtr
& rVisitorFactory
)
234 m_pVisitorFactory
= rVisitorFactory
;
237 bool PDFIRawAdaptor::parse( const uno::Reference
<io::XInputStream
>& xInput
,
238 const uno::Reference
<task::XInteractionHandler
>& xIHdl
,
239 const OUString
& rPwd
,
240 const uno::Reference
<task::XStatusIndicator
>& xStatus
,
241 const XmlEmitterSharedPtr
& rEmitter
,
242 const OUString
& rURL
,
243 const OUString
& rFilterOptions
)
245 // container for metaformat
246 boost::shared_ptr
<PDFIProcessor
> pSink(
247 new PDFIProcessor(xStatus
, m_xContext
));
250 if( m_bEnableToplevelText
)
251 pSink
->enableToplevelText();
256 bSuccess
= xpdf_ImportFromStream( xInput
, pSink
, xIHdl
,
257 rPwd
, m_xContext
, rFilterOptions
);
259 bSuccess
= xpdf_ImportFromFile( rURL
, pSink
, xIHdl
,
260 rPwd
, m_xContext
, rFilterOptions
);
263 pSink
->emit(*rEmitter
,*m_pVisitorFactory
);
268 bool PDFIRawAdaptor::odfConvert( const 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
< OUString
>& /*rUserData*/ ) throw( uno::RuntimeException
, std::exception
)
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 OUString aFilterOptions
;
296 const beans::PropertyValue
* pAttribs
= rSourceData
.getConstArray();
297 sal_Int32 nAttribs
= rSourceData
.getLength();
298 for( sal_Int32 i
= 0; i
< nAttribs
; i
++, pAttribs
++ )
300 SAL_INFO("sdext.pdfimport","importer Attrib: " << OUStringToOString( pAttribs
->Name
, RTL_TEXTENCODING_UTF8
).getStr() );
301 if ( pAttribs
->Name
== "InputStream" )
302 pAttribs
->Value
>>= xInput
;
303 else if ( pAttribs
->Name
== "URL" )
304 pAttribs
->Value
>>= aURL
;
305 else if ( pAttribs
->Name
== "StatusIndicator" )
306 pAttribs
->Value
>>= xStatus
;
307 else if ( pAttribs
->Name
== "InteractionHandler" )
308 pAttribs
->Value
>>= xInteractionHandler
;
309 else if ( pAttribs
->Name
== "Password" )
310 pAttribs
->Value
>>= aPwd
;
311 else if ( pAttribs
->Name
== "FilterOptions" )
312 pAttribs
->Value
>>= aFilterOptions
;
317 XmlEmitterSharedPtr pEmitter
= createSaxEmitter(rHdl
);
318 const bool bSuccess
= parse(xInput
, xInteractionHandler
,
319 aPwd
, xStatus
, pEmitter
, aURL
, aFilterOptions
);
321 // tell input stream that it is no longer needed
322 xInput
->closeInput();
329 void SAL_CALL
PDFIRawAdaptor::setTargetDocument( const uno::Reference
< lang::XComponent
>& xDocument
) throw( lang::IllegalArgumentException
, std::exception
)
331 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
332 m_xModel
= uno::Reference
< frame::XModel
>( xDocument
, uno::UNO_QUERY
);
333 if( xDocument
.is() && ! m_xModel
.is() )
334 throw lang::IllegalArgumentException();
337 OUString
PDFIRawAdaptor::getImplementationName()
338 throw (css::uno::RuntimeException
, std::exception
)
340 return m_implementationName
;
343 sal_Bool
PDFIRawAdaptor::supportsService(OUString
const & ServiceName
)
344 throw (css::uno::RuntimeException
, std::exception
)
346 return cppu::supportsService(this, ServiceName
);
349 css::uno::Sequence
<OUString
> PDFIRawAdaptor::getSupportedServiceNames()
350 throw (css::uno::RuntimeException
, std::exception
)
352 return css::uno::Sequence
<OUString
>{"com.sun.star.document.ImportFilter"};
357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */