LibreOffice Module sdext (master) 1
pdfiadaptor.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
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>
27
28#include <osl/file.h>
29#include <sal/log.hxx>
30#include <rtl/ref.hxx>
31
33#include <com/sun/star/lang/IllegalArgumentException.hpp>
34#include <com/sun/star/lang/XMultiComponentFactory.hpp>
35#include <com/sun/star/io/XSeekable.hpp>
37
38#include <memory>
39
40using namespace com::sun::star;
41
42
43namespace pdfi
44{
45
46PDFIHybridAdaptor::PDFIHybridAdaptor( const uno::Reference< uno::XComponentContext >& xContext ) :
48 m_xContext( xContext )
49{
50}
51
52// XFilter
53sal_Bool SAL_CALL PDFIHybridAdaptor::filter( const uno::Sequence< beans::PropertyValue >& rFilterData )
54{
55 bool bRet = false;
56 if( m_xModel.is() )
57 {
58 uno::Reference< io::XStream > xSubStream;
59 OUString aPwd;
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++ )
64 {
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>"))
69 << "\n");
70 if ( pAttribs[i].Name == "EmbeddedSubstream" )
71 pAttribs[i].Value >>= xSubStream;
72 else if ( pAttribs[i].Name == "Password" )
73 {
74 nPwPos = i;
75 pAttribs[i].Value >>= aPwd;
76 }
77 }
78 bool bAddPwdProp = false;
79 if( ! xSubStream.is() )
80 {
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;
86 if( xInput.is() )
87 {
88 // TODO(P2): extracting hybrid substream twice - once during detection, second time here
89 uno::Reference< io::XSeekable > xSeek( xInput, uno::UNO_QUERY );
90 if( xSeek.is() )
91 xSeek->seek( 0 );
92 oslFileHandle aFile = nullptr;
93 sal_uInt64 nWritten = 0;
94 OUString aURL;
95 if( osl_createTempFile( nullptr, &aFile, &aURL.pData ) == osl_File_E_None )
96 {
97 SAL_INFO("sdext.pdfimport", "created temp file " << aURL);
98 const sal_Int32 nBufSize = 4096;
99 uno::Sequence<sal_Int8> aBuf(nBufSize);
100 // copy the bytes
101 sal_Int32 nBytes;
102 do
103 {
104 nBytes = xInput->readBytes( aBuf, nBufSize );
105 if( nBytes > 0 )
106 {
107 osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
108 if( static_cast<sal_Int32>(nWritten) != nBytes )
109 {
110 xInput.clear();
111 break;
112 }
113 }
114 } while( nBytes == nBufSize );
115 osl_closeFile( aFile );
116 if( xInput.is() )
117 {
118 OUString aEmbedMimetype;
119 OUString aOrgPwd( aPwd );
120 xSubStream = getAdditionalStream( aURL, aEmbedMimetype, aPwd, m_xContext, rFilterData, true );
121 if( aOrgPwd != aPwd )
122 bAddPwdProp = true;
123 }
124 osl_removeFile( aURL.pData );
125 }
126 else
127 xSubStream.clear();
128 }
129 }
130 if( xSubStream.is() )
131 {
132 uno::Sequence< uno::Any > aArgs{ uno::Any(m_xModel), uno::Any(xSubStream) };
133
134 SAL_INFO("sdext.pdfimport", "try to instantiate subfilter" );
135 uno::Reference< document::XFilter > xSubFilter;
136 try {
137 xSubFilter.set(
138 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
139 "com.sun.star.document.OwnSubFilter",
140 aArgs,
141 m_xContext ),
142 uno::UNO_QUERY );
143 }
144 catch(const uno::Exception&)
145 {
146 TOOLS_INFO_EXCEPTION("sdext.pdfimport", "subfilter");
147 }
148
149 SAL_INFO("sdext.pdfimport", "subfilter: " << xSubFilter.get() );
150 if( xSubFilter.is() )
151 {
152 if( bAddPwdProp )
153 {
154 uno::Sequence<beans::PropertyValue> aFilterData( rFilterData );
155 if( nPwPos == -1 )
156 {
157 nPwPos = aFilterData.getLength();
158 aFilterData.realloc( nPwPos+1 );
159 aFilterData.getArray()[nPwPos].Name = "Password";
160 }
161 aFilterData.getArray()[nPwPos].Value <<= aPwd;
162 bRet = xSubFilter->filter( aFilterData );
163 }
164 else
165 bRet = xSubFilter->filter( rFilterData );
166 }
167 }
168 else
169 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no embedded substream set" );
170 }
171 else
172 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no model set" );
173
174 return bRet;
175}
176
178{
179}
180
181//XImporter
182void SAL_CALL PDFIHybridAdaptor::setTargetDocument( const uno::Reference< lang::XComponent >& xDocument )
183{
184 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
185 m_xModel.set( xDocument, uno::UNO_QUERY );
186 if( xDocument.is() && ! m_xModel.is() )
187 throw lang::IllegalArgumentException();
188}
189
191{
192 return "org.libreoffice.comp.documents.HybridPDFImport";
193}
194
195sal_Bool PDFIHybridAdaptor::supportsService(OUString const & ServiceName)
196{
198}
199
201{
202 return {"com.sun.star.document.ImportFilter"};
203}
204
205PDFIRawAdaptor::PDFIRawAdaptor( OUString const & implementationName, const uno::Reference< uno::XComponentContext >& xContext ) :
207 m_implementationName(implementationName),
208 m_xContext( xContext )
209{
210}
211
213{
214 m_pVisitorFactory = rVisitorFactory;
215}
216
217bool PDFIRawAdaptor::parse( const uno::Reference<io::XInputStream>& xInput,
218 const uno::Reference<task::XInteractionHandler>& xIHdl,
219 const OUString& rPwd,
220 const uno::Reference<task::XStatusIndicator>& xStatus,
221 const XmlEmitterSharedPtr& rEmitter,
222 const OUString& rURL,
223 const OUString& rFilterOptions )
224{
225 // container for metaformat
226 auto pSink = std::make_shared<PDFIProcessor>(xStatus, m_xContext);
227
228 bool bSuccess=false;
229
230 if( xInput.is() )
231 bSuccess = xpdf_ImportFromStream( xInput, pSink, xIHdl,
232 rPwd, m_xContext, rFilterOptions );
233 else
234 bSuccess = xpdf_ImportFromFile( rURL, pSink, xIHdl,
235 rPwd, m_xContext, rFilterOptions );
236
237 if( bSuccess )
238 pSink->emit(*rEmitter,*m_pVisitorFactory);
239
240 return bSuccess;
241}
242
243bool PDFIRawAdaptor::odfConvert( const OUString& rURL,
244 const uno::Reference<io::XOutputStream>& xOutput,
245 const uno::Reference<task::XStatusIndicator>& xStatus )
246{
247 XmlEmitterSharedPtr pEmitter = createOdfEmitter(xOutput);
248 const bool bSuccess = parse(uno::Reference<io::XInputStream>(),
249 uno::Reference<task::XInteractionHandler>(),
250 OUString(),
251 xStatus,pEmitter,rURL, "");
252
253 // tell input stream that it is no longer needed
254 xOutput->closeOutput();
255
256 return bSuccess;
257}
258
259// XImportFilter
260sal_Bool SAL_CALL PDFIRawAdaptor::importer( const uno::Sequence< beans::PropertyValue >& rSourceData,
261 const uno::Reference< xml::sax::XDocumentHandler >& rHdl,
262 const uno::Sequence< OUString >& /*rUserData*/ )
263{
264 // get the InputStream carrying the PDF content
265 uno::Reference< io::XInputStream > xInput;
266 uno::Reference< task::XStatusIndicator > xStatus;
267 uno::Reference< task::XInteractionHandler > xInteractionHandler;
268 OUString aURL;
269 OUString aPwd;
270 OUString aFilterOptions;
271 for( const beans::PropertyValue& rAttrib : rSourceData )
272 {
273 SAL_INFO("sdext.pdfimport", "importer Attrib: " << rAttrib.Name );
274 if ( rAttrib.Name == "InputStream" )
275 rAttrib.Value >>= xInput;
276 else if ( rAttrib.Name == "URL" )
277 rAttrib.Value >>= aURL;
278 else if ( rAttrib.Name == "StatusIndicator" )
279 rAttrib.Value >>= xStatus;
280 else if ( rAttrib.Name == "InteractionHandler" )
281 rAttrib.Value >>= xInteractionHandler;
282 else if ( rAttrib.Name == "Password" )
283 rAttrib.Value >>= aPwd;
284 else if ( rAttrib.Name == "FilterOptions" )
285 rAttrib.Value >>= aFilterOptions;
286 }
287 if( !xInput.is() )
288 return false;
289
290 XmlEmitterSharedPtr pEmitter = createSaxEmitter(rHdl);
291 const bool bSuccess = parse(xInput, xInteractionHandler,
292 aPwd, xStatus, pEmitter, aURL, aFilterOptions);
293
294 // tell input stream that it is no longer needed
295 xInput->closeInput();
296 xInput.clear();
297
298 return bSuccess;
299}
300
301//XImporter
302void SAL_CALL PDFIRawAdaptor::setTargetDocument( const uno::Reference< lang::XComponent >& xDocument )
303{
304 SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
305 m_xModel.set( xDocument, uno::UNO_QUERY );
306 if( xDocument.is() && ! m_xModel.is() )
307 throw lang::IllegalArgumentException();
308}
309
311{
313}
314
315sal_Bool PDFIRawAdaptor::supportsService(OUString const & ServiceName)
316{
318}
319
320css::uno::Sequence<OUString> PDFIRawAdaptor::getSupportedServiceNames()
321{
322 return {"com.sun.star.document.ImportFilter"};
323}
324
325
326
327extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
329 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
330{
331 rtl::Reference<pdfi::PDFIRawAdaptor> pAdaptor = new pdfi::PDFIRawAdaptor( "org.libreoffice.comp.documents.WriterPDFImport", context );
332 pAdaptor->setTreeVisitorFactory(pdfi::createWriterTreeVisitorFactory());
333 pAdaptor->acquire();
334 return static_cast<cppu::OWeakObject*>(pAdaptor.get());
335}
336
337extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
339 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
340{
341 rtl::Reference<pdfi::PDFIRawAdaptor> pAdaptor = new pdfi::PDFIRawAdaptor( "org.libreoffice.comp.documents.DrawPDFImport", context );
342 pAdaptor->setTreeVisitorFactory(pdfi::createDrawTreeVisitorFactory());
343 pAdaptor->acquire();
344 return static_cast<cppu::OWeakObject*>(pAdaptor.get());
345}
346
347extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
349 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
350{
351 rtl::Reference<pdfi::PDFIRawAdaptor> pAdaptor = new pdfi::PDFIRawAdaptor( "org.libreoffice.comp.documents.ImpressPDFImport", context );
352 pAdaptor->setTreeVisitorFactory(pdfi::createImpressTreeVisitorFactory());
353 pAdaptor->acquire();
354 return static_cast<cppu::OWeakObject*>(pAdaptor.get());
355}
356
357extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
359 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
360{
361 return cppu::acquire(new pdfi::PDFIHybridAdaptor( context ));
362}
363
364}
365
366/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void SAL_CALL cancel() override
sal_Bool SAL_CALL supportsService(OUString const &ServiceName) override
css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual sal_Bool SAL_CALL filter(const css::uno::Sequence< css::beans::PropertyValue > &rFilterData) override
Definition: pdfiadaptor.cxx:53
virtual void SAL_CALL setTargetDocument(const css::uno::Reference< css::lang::XComponent > &xDocument) override
OUString SAL_CALL getImplementationName() override
css::uno::Reference< css::uno::XComponentContext > m_xContext
Definition: pdfiadaptor.hxx:53
PDFIHybridAdaptor(const css::uno::Reference< css::uno::XComponentContext > &xContext)
Definition: pdfiadaptor.cxx:46
css::uno::Reference< css::frame::XModel > m_xModel
Definition: pdfiadaptor.hxx:55
Adapts raw pdf import to XImportFilter interface.
Definition: pdfiadaptor.hxx:84
bool parse(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::task::XInteractionHandler > &xIHdl, const OUString &rPwd, const css::uno::Reference< css::task::XStatusIndicator > &xStatus, const XmlEmitterSharedPtr &rEmitter, const OUString &rURL, const OUString &rFilterOptions)
bool odfConvert(const OUString &rURL, const css::uno::Reference< css::io::XOutputStream > &xOutput, const css::uno::Reference< css::task::XStatusIndicator > &xStatus)
Export pdf document to ODG.
css::uno::Reference< css::frame::XModel > m_xModel
Definition: pdfiadaptor.hxx:90
virtual void SAL_CALL setTargetDocument(const css::uno::Reference< css::lang::XComponent > &xDocument) override
TreeVisitorFactorySharedPtr m_pVisitorFactory
Definition: pdfiadaptor.hxx:91
css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
void setTreeVisitorFactory(const TreeVisitorFactorySharedPtr &rVisitorFactory)
Set factory object used to create the tree visitors.
PDFIRawAdaptor(OUString const &implementationName, const css::uno::Reference< css::uno::XComponentContext > &xContext)
css::uno::Reference< css::uno::XComponentContext > m_xContext
Definition: pdfiadaptor.hxx:88
OUString SAL_CALL getImplementationName() override
sal_Bool SAL_CALL supportsService(OUString const &ServiceName) override
OUString const m_implementationName
Definition: pdfiadaptor.hxx:86
virtual sal_Bool SAL_CALL importer(const css::uno::Sequence< css::beans::PropertyValue > &rSourceData, const css::uno::Reference< css::xml::sax::XDocumentHandler > &rHdl, const css::uno::Sequence< OUString > &rUserData) override
#define TOOLS_INFO_EXCEPTION(area, stream)
URL aURL
std::mutex m_aMutex
#define SAL_INFO(area, stream)
aBuf
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Value
int i
constexpr OUStringLiteral implementationName
XmlEmitterSharedPtr createSaxEmitter(const css::uno::Reference< css::xml::sax::XDocumentHandler > &xDocHdl)
bool xpdf_ImportFromStream(const css::uno::Reference< css::io::XInputStream > &xInput, const ContentSinkSharedPtr &rSink, const css::uno::Reference< css::task::XInteractionHandler > &xIHdl, const OUString &rPwd, const css::uno::Reference< css::uno::XComponentContext > &xContext, const OUString &rFilterOptions)
bool xpdf_ImportFromFile(const OUString &rURL, const ContentSinkSharedPtr &rSink, const css::uno::Reference< css::task::XInteractionHandler > &xIHdl, const OUString &rPwd, const css::uno::Reference< css::uno::XComponentContext > &xContext, const OUString &rFilterOptions)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * sdext_PDFIRawAdaptor_Writer_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
::cppu::WeakComponentImplHelper< css::document::XFilter, css::document::XImporter, css::lang::XServiceInfo > PDFIHybridAdaptorBase
Definition: pdfiadaptor.hxx:46
uno::Reference< io::XStream > getAdditionalStream(const OUString &rInPDFFileURL, OUString &rOutMimetype, OUString &io_rPwd, const uno::Reference< uno::XComponentContext > &xContext, const uno::Sequence< beans::PropertyValue > &rFilterData, bool bMayUseUI)
Definition: filterdet.cxx:472
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * sdext_PDFIRawAdaptor_Draw_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
XmlEmitterSharedPtr createOdfEmitter(const css::uno::Reference< css::io::XOutputStream > &xOut)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * sdext_PDFIRawAdaptor_Impress_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
std::shared_ptr< TreeVisitorFactory > TreeVisitorFactorySharedPtr
TreeVisitorFactorySharedPtr createWriterTreeVisitorFactory()
TreeVisitorFactorySharedPtr createDrawTreeVisitorFactory()
std::shared_ptr< XmlEmitter > XmlEmitterSharedPtr
Definition: xmlemitter.hxx:48
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * sdext_PDFIHybridAdaptor_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
TreeVisitorFactorySharedPtr createImpressTreeVisitorFactory()
::cppu::WeakComponentImplHelper< css::xml::XImportFilter, css::document::XImporter, css::lang::XServiceInfo > PDFIAdaptorBase
Definition: pdfiadaptor.hxx:78
OUString Name
unsigned char sal_Bool
const uno::Reference< uno::XComponentContext > m_xContext
Definition: wrapper.cxx:144