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>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <com/sun/star/lang/IllegalArgumentException.hpp>
33 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
34 #include <com/sun/star/io/XSeekable.hpp>
35 #include <tools/diagnose_ex.h>
39 using namespace com::sun::star
;
45 PDFIHybridAdaptor::PDFIHybridAdaptor( const uno::Reference
< uno::XComponentContext
>& xContext
) :
46 PDFIHybridAdaptorBase( m_aMutex
),
47 m_xContext( xContext
),
53 sal_Bool SAL_CALL
PDFIHybridAdaptor::filter( const uno::Sequence
< beans::PropertyValue
>& rFilterData
)
58 uno::Reference
< io::XStream
> xSubStream
;
60 const beans::PropertyValue
* pAttribs
= rFilterData
.getConstArray();
61 sal_Int32 nAttribs
= rFilterData
.getLength();
62 sal_Int32 nPwPos
= -1;
63 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
65 SAL_INFO("sdext.pdfimport", "filter: Attrib: " << pAttribs
[i
].Name
66 << " = " << (pAttribs
[i
].Value
.has
<OUString
>()
67 ? pAttribs
[i
].Value
.get
<OUString
>()
68 : OUString("<no string>"))
70 if ( pAttribs
[i
].Name
== "EmbeddedSubstream" )
71 pAttribs
[i
].Value
>>= xSubStream
;
72 else if ( pAttribs
[i
].Name
== "Password" )
75 pAttribs
[i
].Value
>>= aPwd
;
78 bool bAddPwdProp
= false;
79 if( ! xSubStream
.is() )
81 uno::Reference
< io::XInputStream
> xInput
;
82 auto pAttr
= std::find_if(rFilterData
.begin(), rFilterData
.end(),
83 [](const beans::PropertyValue
& rAttr
) { return rAttr
.Name
== "InputStream"; });
84 if (pAttr
!= rFilterData
.end())
85 pAttr
->Value
>>= xInput
;
88 // TODO(P2): extracting hybrid substream twice - once during detection, second time here
89 uno::Reference
< io::XSeekable
> xSeek( xInput
, uno::UNO_QUERY
);
92 oslFileHandle aFile
= nullptr;
93 sal_uInt64 nWritten
= 0;
95 if( osl_createTempFile( nullptr, &aFile
, &aURL
.pData
) == osl_File_E_None
)
97 SAL_INFO("sdext.pdfimport", "created temp file " << aURL
);
98 const sal_Int32 nBufSize
= 4096;
99 uno::Sequence
<sal_Int8
> aBuf(nBufSize
);
104 nBytes
= xInput
->readBytes( aBuf
, nBufSize
);
107 osl_writeFile( aFile
, aBuf
.getConstArray(), nBytes
, &nWritten
);
108 if( static_cast<sal_Int32
>(nWritten
) != nBytes
)
114 } while( nBytes
== nBufSize
);
115 osl_closeFile( aFile
);
118 OUString aEmbedMimetype
;
119 OUString
aOrgPwd( aPwd
);
120 xSubStream
= getAdditionalStream( aURL
, aEmbedMimetype
, aPwd
, m_xContext
, rFilterData
, true );
121 if( aOrgPwd
!= aPwd
)
124 osl_removeFile( aURL
.pData
);
130 if( xSubStream
.is() )
132 uno::Sequence
< uno::Any
> aArgs( 2 );
133 aArgs
[0] <<= m_xModel
;
134 aArgs
[1] <<= xSubStream
;
136 SAL_INFO("sdext.pdfimport", "try to instantiate subfilter" );
137 uno::Reference
< document::XFilter
> xSubFilter
;
140 m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
141 "com.sun.star.document.OwnSubFilter",
146 catch(const uno::Exception
&)
148 TOOLS_INFO_EXCEPTION("sdext.pdfimport", "subfilter");
151 SAL_INFO("sdext.pdfimport", "subfilter: " << xSubFilter
.get() );
152 if( xSubFilter
.is() )
156 uno::Sequence
<beans::PropertyValue
> aFilterData( rFilterData
);
159 nPwPos
= aFilterData
.getLength();
160 aFilterData
.realloc( nPwPos
+1 );
161 aFilterData
[nPwPos
].Name
= "Password";
163 aFilterData
[nPwPos
].Value
<<= aPwd
;
164 bRet
= xSubFilter
->filter( aFilterData
);
167 bRet
= xSubFilter
->filter( rFilterData
);
171 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no embedded substream set" );
174 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no model set" );
179 void SAL_CALL
PDFIHybridAdaptor::cancel()
184 void SAL_CALL
PDFIHybridAdaptor::setTargetDocument( const uno::Reference
< lang::XComponent
>& xDocument
)
186 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
187 m_xModel
.set( xDocument
, uno::UNO_QUERY
);
188 if( xDocument
.is() && ! m_xModel
.is() )
189 throw lang::IllegalArgumentException();
192 OUString
PDFIHybridAdaptor::getImplementationName()
194 return "org.libreoffice.comp.documents.HybridPDFImport";
197 sal_Bool
PDFIHybridAdaptor::supportsService(OUString
const & ServiceName
)
199 return cppu::supportsService(this, ServiceName
);
202 css::uno::Sequence
<OUString
> PDFIHybridAdaptor::getSupportedServiceNames()
204 return css::uno::Sequence
<OUString
>{"com.sun.star.document.ImportFilter"};
207 PDFIRawAdaptor::PDFIRawAdaptor( OUString
const & implementationName
, const uno::Reference
< uno::XComponentContext
>& xContext
) :
208 PDFIAdaptorBase( m_aMutex
),
209 m_implementationName(implementationName
),
210 m_xContext( xContext
),
216 void PDFIRawAdaptor::setTreeVisitorFactory(const TreeVisitorFactorySharedPtr
& rVisitorFactory
)
218 m_pVisitorFactory
= rVisitorFactory
;
221 bool PDFIRawAdaptor::parse( const uno::Reference
<io::XInputStream
>& xInput
,
222 const uno::Reference
<task::XInteractionHandler
>& xIHdl
,
223 const OUString
& rPwd
,
224 const uno::Reference
<task::XStatusIndicator
>& xStatus
,
225 const XmlEmitterSharedPtr
& rEmitter
,
226 const OUString
& rURL
,
227 const OUString
& rFilterOptions
)
229 // container for metaformat
230 std::shared_ptr
<PDFIProcessor
> pSink(
231 new PDFIProcessor(xStatus
, m_xContext
));
236 bSuccess
= xpdf_ImportFromStream( xInput
, pSink
, xIHdl
,
237 rPwd
, m_xContext
, rFilterOptions
);
239 bSuccess
= xpdf_ImportFromFile( rURL
, pSink
, xIHdl
,
240 rPwd
, m_xContext
, rFilterOptions
);
243 pSink
->emit(*rEmitter
,*m_pVisitorFactory
);
248 bool PDFIRawAdaptor::odfConvert( const OUString
& rURL
,
249 const uno::Reference
<io::XOutputStream
>& xOutput
,
250 const uno::Reference
<task::XStatusIndicator
>& xStatus
)
252 XmlEmitterSharedPtr pEmitter
= createOdfEmitter(xOutput
);
253 const bool bSuccess
= parse(uno::Reference
<io::XInputStream
>(),
254 uno::Reference
<task::XInteractionHandler
>(),
256 xStatus
,pEmitter
,rURL
, "");
258 // tell input stream that it is no longer needed
259 xOutput
->closeOutput();
265 sal_Bool SAL_CALL
PDFIRawAdaptor::importer( const uno::Sequence
< beans::PropertyValue
>& rSourceData
,
266 const uno::Reference
< xml::sax::XDocumentHandler
>& rHdl
,
267 const uno::Sequence
< OUString
>& /*rUserData*/ )
269 // get the InputStream carrying the PDF content
270 uno::Reference
< io::XInputStream
> xInput
;
271 uno::Reference
< task::XStatusIndicator
> xStatus
;
272 uno::Reference
< task::XInteractionHandler
> xInteractionHandler
;
275 OUString aFilterOptions
;
276 for( const beans::PropertyValue
& rAttrib
: rSourceData
)
278 SAL_INFO("sdext.pdfimport", "importer Attrib: " << rAttrib
.Name
);
279 if ( rAttrib
.Name
== "InputStream" )
280 rAttrib
.Value
>>= xInput
;
281 else if ( rAttrib
.Name
== "URL" )
282 rAttrib
.Value
>>= aURL
;
283 else if ( rAttrib
.Name
== "StatusIndicator" )
284 rAttrib
.Value
>>= xStatus
;
285 else if ( rAttrib
.Name
== "InteractionHandler" )
286 rAttrib
.Value
>>= xInteractionHandler
;
287 else if ( rAttrib
.Name
== "Password" )
288 rAttrib
.Value
>>= aPwd
;
289 else if ( rAttrib
.Name
== "FilterOptions" )
290 rAttrib
.Value
>>= aFilterOptions
;
295 XmlEmitterSharedPtr pEmitter
= createSaxEmitter(rHdl
);
296 const bool bSuccess
= parse(xInput
, xInteractionHandler
,
297 aPwd
, xStatus
, pEmitter
, aURL
, aFilterOptions
);
299 // tell input stream that it is no longer needed
300 xInput
->closeInput();
307 void SAL_CALL
PDFIRawAdaptor::setTargetDocument( const uno::Reference
< lang::XComponent
>& xDocument
)
309 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
310 m_xModel
.set( xDocument
, uno::UNO_QUERY
);
311 if( xDocument
.is() && ! m_xModel
.is() )
312 throw lang::IllegalArgumentException();
315 OUString
PDFIRawAdaptor::getImplementationName()
317 return m_implementationName
;
320 sal_Bool
PDFIRawAdaptor::supportsService(OUString
const & ServiceName
)
322 return cppu::supportsService(this, ServiceName
);
325 css::uno::Sequence
<OUString
> PDFIRawAdaptor::getSupportedServiceNames()
327 return css::uno::Sequence
<OUString
>{"com.sun.star.document.ImportFilter"};
332 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */