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 <pdfiprocessor.hxx>
29 #include <sal/log.hxx>
30 #include <rtl/ref.hxx>
32 #include <cppuhelper/supportsservice.hxx>
33 #include <com/sun/star/lang/IllegalArgumentException.hpp>
34 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
35 #include <com/sun/star/io/XSeekable.hpp>
36 #include <comphelper/diagnose_ex.hxx>
40 using namespace com::sun::star
;
46 PDFIHybridAdaptor::PDFIHybridAdaptor( const uno::Reference
< uno::XComponentContext
>& xContext
) :
47 m_xContext( xContext
)
52 sal_Bool SAL_CALL
PDFIHybridAdaptor::filter( const uno::Sequence
< beans::PropertyValue
>& rFilterData
)
57 uno::Reference
< io::XStream
> xSubStream
;
59 const beans::PropertyValue
* pAttribs
= rFilterData
.getConstArray();
60 sal_Int32 nAttribs
= rFilterData
.getLength();
61 sal_Int32 nPwPos
= -1;
62 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
64 SAL_INFO("sdext.pdfimport", "filter: Attrib: " << pAttribs
[i
].Name
65 << " = " << (pAttribs
[i
].Value
.has
<OUString
>()
66 ? pAttribs
[i
].Value
.get
<OUString
>()
67 : OUString("<no string>"))
69 if ( pAttribs
[i
].Name
== "EmbeddedSubstream" )
70 pAttribs
[i
].Value
>>= xSubStream
;
71 else if ( pAttribs
[i
].Name
== "Password" )
74 pAttribs
[i
].Value
>>= aPwd
;
77 bool bAddPwdProp
= false;
78 if( ! xSubStream
.is() )
80 uno::Reference
< io::XInputStream
> xInput
;
81 auto pAttr
= std::find_if(rFilterData
.begin(), rFilterData
.end(),
82 [](const beans::PropertyValue
& rAttr
) { return rAttr
.Name
== "InputStream"; });
83 if (pAttr
!= rFilterData
.end())
84 pAttr
->Value
>>= xInput
;
87 // TODO(P2): extracting hybrid substream twice - once during detection, second time here
88 uno::Reference
< io::XSeekable
> xSeek( xInput
, uno::UNO_QUERY
);
91 oslFileHandle aFile
= nullptr;
92 sal_uInt64 nWritten
= 0;
94 if( osl_createTempFile( nullptr, &aFile
, &aURL
.pData
) == osl_File_E_None
)
96 SAL_INFO("sdext.pdfimport", "created temp file " << aURL
);
97 const sal_Int32 nBufSize
= 4096;
98 uno::Sequence
<sal_Int8
> aBuf(nBufSize
);
103 nBytes
= xInput
->readBytes( aBuf
, nBufSize
);
106 osl_writeFile( aFile
, aBuf
.getConstArray(), nBytes
, &nWritten
);
107 if( static_cast<sal_Int32
>(nWritten
) != nBytes
)
113 } while( nBytes
== nBufSize
);
114 osl_closeFile( aFile
);
117 OUString aEmbedMimetype
;
118 OUString
aOrgPwd( aPwd
);
119 xSubStream
= getAdditionalStream( aURL
, aEmbedMimetype
, aPwd
, m_xContext
, rFilterData
, true );
120 if( aOrgPwd
!= aPwd
)
123 osl_removeFile( aURL
.pData
);
129 if( xSubStream
.is() )
131 uno::Sequence
< uno::Any
> aArgs
{ uno::Any(m_xModel
), uno::Any(xSubStream
) };
133 SAL_INFO("sdext.pdfimport", "try to instantiate subfilter" );
134 uno::Reference
< document::XFilter
> xSubFilter
;
137 m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
138 "com.sun.star.document.OwnSubFilter",
143 catch(const uno::Exception
&)
145 TOOLS_INFO_EXCEPTION("sdext.pdfimport", "subfilter");
148 SAL_INFO("sdext.pdfimport", "subfilter: " << xSubFilter
.get() );
149 if( xSubFilter
.is() )
153 uno::Sequence
<beans::PropertyValue
> aFilterData( rFilterData
);
156 nPwPos
= aFilterData
.getLength();
157 aFilterData
.realloc( nPwPos
+1 );
158 aFilterData
.getArray()[nPwPos
].Name
= "Password";
160 aFilterData
.getArray()[nPwPos
].Value
<<= aPwd
;
161 bRet
= xSubFilter
->filter( aFilterData
);
164 bRet
= xSubFilter
->filter( rFilterData
);
168 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no embedded substream set" );
171 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no model set" );
176 void SAL_CALL
PDFIHybridAdaptor::cancel()
181 void SAL_CALL
PDFIHybridAdaptor::setTargetDocument( const uno::Reference
< lang::XComponent
>& xDocument
)
183 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
184 m_xModel
.set( xDocument
, uno::UNO_QUERY
);
185 if( xDocument
.is() && ! m_xModel
.is() )
186 throw lang::IllegalArgumentException();
189 OUString
PDFIHybridAdaptor::getImplementationName()
191 return "org.libreoffice.comp.documents.HybridPDFImport";
194 sal_Bool
PDFIHybridAdaptor::supportsService(OUString
const & ServiceName
)
196 return cppu::supportsService(this, ServiceName
);
199 css::uno::Sequence
<OUString
> PDFIHybridAdaptor::getSupportedServiceNames()
201 return {"com.sun.star.document.ImportFilter"};
204 PDFIRawAdaptor::PDFIRawAdaptor( OUString
const & implementationName
, const uno::Reference
< uno::XComponentContext
>& xContext
) :
205 m_implementationName(implementationName
),
206 m_xContext( xContext
)
210 void PDFIRawAdaptor::setTreeVisitorFactory(const TreeVisitorFactorySharedPtr
& rVisitorFactory
)
212 m_pVisitorFactory
= rVisitorFactory
;
215 bool PDFIRawAdaptor::parse( const uno::Reference
<io::XInputStream
>& xInput
,
216 const uno::Reference
<task::XInteractionHandler
>& xIHdl
,
217 const OUString
& rPwd
,
218 const uno::Reference
<task::XStatusIndicator
>& xStatus
,
219 const XmlEmitterSharedPtr
& rEmitter
,
220 const OUString
& rURL
,
221 const OUString
& rFilterOptions
)
223 // container for metaformat
224 auto pSink
= std::make_shared
<PDFIProcessor
>(xStatus
, m_xContext
);
229 bSuccess
= xpdf_ImportFromStream( xInput
, pSink
, xIHdl
,
230 rPwd
, m_xContext
, rFilterOptions
);
232 bSuccess
= xpdf_ImportFromFile( rURL
, pSink
, xIHdl
,
233 rPwd
, m_xContext
, rFilterOptions
);
236 pSink
->emit(*rEmitter
,*m_pVisitorFactory
);
241 bool PDFIRawAdaptor::odfConvert( const OUString
& rURL
,
242 const uno::Reference
<io::XOutputStream
>& xOutput
,
243 const uno::Reference
<task::XStatusIndicator
>& xStatus
)
245 XmlEmitterSharedPtr pEmitter
= createOdfEmitter(xOutput
);
246 const bool bSuccess
= parse(uno::Reference
<io::XInputStream
>(),
247 uno::Reference
<task::XInteractionHandler
>(),
249 xStatus
,pEmitter
,rURL
, "");
251 // tell input stream that it is no longer needed
252 xOutput
->closeOutput();
258 sal_Bool SAL_CALL
PDFIRawAdaptor::importer( const uno::Sequence
< beans::PropertyValue
>& rSourceData
,
259 const uno::Reference
< xml::sax::XDocumentHandler
>& rHdl
,
260 const uno::Sequence
< OUString
>& /*rUserData*/ )
262 // get the InputStream carrying the PDF content
263 uno::Reference
< io::XInputStream
> xInput
;
264 uno::Reference
< task::XStatusIndicator
> xStatus
;
265 uno::Reference
< task::XInteractionHandler
> xInteractionHandler
;
268 OUString aFilterOptions
;
269 for( const beans::PropertyValue
& rAttrib
: rSourceData
)
271 SAL_INFO("sdext.pdfimport", "importer Attrib: " << rAttrib
.Name
);
272 if ( rAttrib
.Name
== "InputStream" )
273 rAttrib
.Value
>>= xInput
;
274 else if ( rAttrib
.Name
== "URL" )
275 rAttrib
.Value
>>= aURL
;
276 else if ( rAttrib
.Name
== "StatusIndicator" )
277 rAttrib
.Value
>>= xStatus
;
278 else if ( rAttrib
.Name
== "InteractionHandler" )
279 rAttrib
.Value
>>= xInteractionHandler
;
280 else if ( rAttrib
.Name
== "Password" )
281 rAttrib
.Value
>>= aPwd
;
282 else if ( rAttrib
.Name
== "FilterOptions" )
283 rAttrib
.Value
>>= aFilterOptions
;
288 XmlEmitterSharedPtr pEmitter
= createSaxEmitter(rHdl
);
289 const bool bSuccess
= parse(xInput
, xInteractionHandler
,
290 aPwd
, xStatus
, pEmitter
, aURL
, aFilterOptions
);
292 // tell input stream that it is no longer needed
293 xInput
->closeInput();
300 void SAL_CALL
PDFIRawAdaptor::setTargetDocument( const uno::Reference
< lang::XComponent
>& xDocument
)
302 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
303 m_xModel
.set( xDocument
, uno::UNO_QUERY
);
304 if( xDocument
.is() && ! m_xModel
.is() )
305 throw lang::IllegalArgumentException();
308 OUString
PDFIRawAdaptor::getImplementationName()
310 return m_implementationName
;
313 sal_Bool
PDFIRawAdaptor::supportsService(OUString
const & ServiceName
)
315 return cppu::supportsService(this, ServiceName
);
318 css::uno::Sequence
<OUString
> PDFIRawAdaptor::getSupportedServiceNames()
320 return {"com.sun.star.document.ImportFilter"};
325 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
326 sdext_PDFIRawAdaptor_Writer_get_implementation(
327 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
329 rtl::Reference
<pdfi::PDFIRawAdaptor
> pAdaptor
= new pdfi::PDFIRawAdaptor( "org.libreoffice.comp.documents.WriterPDFImport", context
);
330 pAdaptor
->setTreeVisitorFactory(pdfi::createWriterTreeVisitorFactory());
332 return getXWeak(pAdaptor
.get());
335 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
336 sdext_PDFIRawAdaptor_Draw_get_implementation(
337 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
339 rtl::Reference
<pdfi::PDFIRawAdaptor
> pAdaptor
= new pdfi::PDFIRawAdaptor( "org.libreoffice.comp.documents.DrawPDFImport", context
);
340 pAdaptor
->setTreeVisitorFactory(pdfi::createDrawTreeVisitorFactory());
342 return getXWeak(pAdaptor
.get());
345 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
346 sdext_PDFIRawAdaptor_Impress_get_implementation(
347 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
349 rtl::Reference
<pdfi::PDFIRawAdaptor
> pAdaptor
= new pdfi::PDFIRawAdaptor( "org.libreoffice.comp.documents.ImpressPDFImport", context
);
350 pAdaptor
->setTreeVisitorFactory(pdfi::createImpressTreeVisitorFactory());
352 return getXWeak(pAdaptor
.get());
355 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
356 sdext_PDFIHybridAdaptor_get_implementation(
357 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
359 return cppu::acquire(new pdfi::PDFIHybridAdaptor( context
));
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */