Line data Source code
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 "inc/contentsink.hxx"
27 : #include "tree/pdfiprocessor.hxx"
28 :
29 : #include <osl/file.h>
30 : #include <osl/thread.h>
31 : #include "sal/log.hxx"
32 :
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>
42 :
43 :
44 : #include <boost/shared_ptr.hpp>
45 :
46 : using namespace com::sun::star;
47 :
48 :
49 : namespace pdfi
50 : {
51 :
52 1 : PDFIHybridAdaptor::PDFIHybridAdaptor( const uno::Reference< uno::XComponentContext >& xContext ) :
53 : PDFIHybridAdaptorBase( m_aMutex ),
54 : m_xContext( xContext ),
55 1 : m_xModel()
56 : {
57 1 : }
58 :
59 : // XFilter
60 0 : sal_Bool SAL_CALL PDFIHybridAdaptor::filter( const uno::Sequence< beans::PropertyValue >& rFilterData ) throw( uno::RuntimeException, std::exception )
61 : {
62 0 : bool bRet = false;
63 0 : if( m_xModel.is() )
64 : {
65 0 : uno::Reference< io::XStream > xSubStream;
66 0 : OUString aPwd;
67 0 : const beans::PropertyValue* pAttribs = rFilterData.getConstArray();
68 0 : sal_Int32 nAttribs = rFilterData.getLength();
69 0 : sal_Int32 nPwPos = -1;
70 0 : for( sal_Int32 i = 0; i < nAttribs; i++ )
71 : {
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>"))
76 : << "\n");
77 0 : if ( pAttribs[i].Name == "EmbeddedSubstream" )
78 0 : pAttribs[i].Value >>= xSubStream;
79 0 : else if ( pAttribs[i].Name == "Password" )
80 : {
81 0 : nPwPos = i;
82 0 : pAttribs[i].Value >>= aPwd;
83 : }
84 : }
85 0 : bool bAddPwdProp = false;
86 0 : if( ! xSubStream.is() )
87 : {
88 0 : uno::Reference< io::XInputStream > xInput;
89 0 : for( sal_Int32 i = 0; i < nAttribs; i++ )
90 : {
91 0 : if ( pAttribs[i].Name == "InputStream" )
92 : {
93 0 : pAttribs[i].Value >>= xInput;
94 0 : break;
95 : }
96 : }
97 0 : if( xInput.is() )
98 : {
99 : // TODO(P2): extracting hybrid substream twice - once during detection, second time here
100 0 : uno::Reference< io::XSeekable > xSeek( xInput, uno::UNO_QUERY );
101 0 : if( xSeek.is() )
102 0 : xSeek->seek( 0 );
103 0 : oslFileHandle aFile = NULL;
104 0 : sal_uInt64 nWritten = 0;
105 0 : OUString aURL;
106 0 : if( osl_createTempFile( NULL, &aFile, &aURL.pData ) == osl_File_E_None )
107 : {
108 : SAL_INFO("sdext.pdfimport", "created temp file " << aURL);
109 0 : const sal_Int32 nBufSize = 4096;
110 0 : uno::Sequence<sal_Int8> aBuf(nBufSize);
111 : // copy the bytes
112 : sal_Int32 nBytes;
113 0 : do
114 : {
115 0 : nBytes = xInput->readBytes( aBuf, nBufSize );
116 0 : if( nBytes > 0 )
117 : {
118 0 : osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
119 0 : if( static_cast<sal_Int32>(nWritten) != nBytes )
120 : {
121 0 : xInput.clear();
122 0 : break;
123 : }
124 : }
125 : } while( nBytes == nBufSize );
126 0 : osl_closeFile( aFile );
127 0 : if( xInput.is() )
128 : {
129 0 : OUString aEmbedMimetype;
130 0 : OUString aOrgPwd( aPwd );
131 0 : xSubStream = getAdditionalStream( aURL, aEmbedMimetype, aPwd, m_xContext, rFilterData, true );
132 0 : if( aOrgPwd != aPwd )
133 0 : bAddPwdProp = true;
134 : }
135 0 : osl_removeFile( aURL.pData );
136 : }
137 : else
138 0 : xSubStream.clear();
139 0 : }
140 : }
141 0 : if( xSubStream.is() )
142 : {
143 0 : uno::Sequence< uno::Any > aArgs( 2 );
144 0 : aArgs[0] <<= m_xModel;
145 0 : aArgs[1] <<= xSubStream;
146 :
147 : SAL_INFO("sdext.pdfimport", "try to instantiate subfilter" );
148 0 : uno::Reference< document::XFilter > xSubFilter;
149 : try {
150 0 : xSubFilter = uno::Reference<document::XFilter>(
151 0 : m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
152 : OUString( "com.sun.star.document.OwnSubFilter" ),
153 : aArgs,
154 0 : m_xContext ),
155 0 : uno::UNO_QUERY );
156 : }
157 0 : catch(const uno::Exception& e)
158 : {
159 : (void)e;
160 : SAL_INFO("sdext.pdfimport", "subfilter exception: " << e.Message << "\n");
161 : }
162 :
163 : SAL_INFO("sdext.pdfimport", "subfilter: " << xSubFilter.get() );
164 0 : if( xSubFilter.is() )
165 : {
166 0 : if( bAddPwdProp )
167 : {
168 0 : uno::Sequence<beans::PropertyValue> aFilterData( rFilterData );
169 0 : if( nPwPos == -1 )
170 : {
171 0 : nPwPos = aFilterData.getLength();
172 0 : aFilterData.realloc( nPwPos+1 );
173 0 : aFilterData[nPwPos].Name = "Password";
174 : }
175 0 : aFilterData[nPwPos].Value <<= aPwd;
176 0 : bRet = xSubFilter->filter( aFilterData );
177 : }
178 : else
179 0 : bRet = xSubFilter->filter( rFilterData );
180 0 : }
181 : }
182 : else
183 0 : SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no embedded substream set" );
184 : }
185 : else
186 : SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no model set" );
187 :
188 0 : return bRet;
189 : }
190 :
191 0 : void SAL_CALL PDFIHybridAdaptor::cancel() throw(std::exception)
192 : {
193 0 : }
194 :
195 : //XImporter
196 0 : void SAL_CALL PDFIHybridAdaptor::setTargetDocument( const uno::Reference< lang::XComponent >& xDocument ) throw( lang::IllegalArgumentException, std::exception )
197 : {
198 : SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
199 0 : m_xModel = uno::Reference< frame::XModel >( xDocument, uno::UNO_QUERY );
200 0 : if( xDocument.is() && ! m_xModel.is() )
201 0 : throw lang::IllegalArgumentException();
202 0 : }
203 :
204 1 : OUString PDFIHybridAdaptor::getImplementationName()
205 : throw (css::uno::RuntimeException, std::exception)
206 : {
207 1 : return OUString("org.libreoffice.comp.documents.HybridPDFImport");
208 : }
209 :
210 0 : sal_Bool PDFIHybridAdaptor::supportsService(OUString const & ServiceName)
211 : throw (css::uno::RuntimeException, std::exception)
212 : {
213 0 : return cppu::supportsService(this, ServiceName);
214 : }
215 :
216 1 : css::uno::Sequence<OUString> PDFIHybridAdaptor::getSupportedServiceNames()
217 : throw (css::uno::RuntimeException, std::exception)
218 : {
219 1 : return css::uno::Sequence<OUString>{"com.sun.star.document.ImportFilter"};
220 : }
221 :
222 7 : PDFIRawAdaptor::PDFIRawAdaptor( OUString const & implementationName, const uno::Reference< uno::XComponentContext >& xContext ) :
223 : PDFIAdaptorBase( m_aMutex ),
224 : m_implementationName(implementationName),
225 : m_xContext( xContext ),
226 : m_xModel(),
227 : m_pVisitorFactory(),
228 7 : m_bEnableToplevelText(false)
229 : {
230 7 : }
231 :
232 7 : void PDFIRawAdaptor::setTreeVisitorFactory(const TreeVisitorFactorySharedPtr& rVisitorFactory)
233 : {
234 7 : m_pVisitorFactory = rVisitorFactory;
235 7 : }
236 :
237 4 : 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 )
244 : {
245 : // container for metaformat
246 : boost::shared_ptr<PDFIProcessor> pSink(
247 4 : new PDFIProcessor(xStatus, m_xContext));
248 :
249 : // TEMP! TEMP!
250 4 : if( m_bEnableToplevelText )
251 0 : pSink->enableToplevelText();
252 :
253 4 : bool bSuccess=false;
254 :
255 4 : if( xInput.is() )
256 : bSuccess = xpdf_ImportFromStream( xInput, pSink, xIHdl,
257 2 : rPwd, m_xContext, rFilterOptions );
258 : else
259 : bSuccess = xpdf_ImportFromFile( rURL, pSink, xIHdl,
260 2 : rPwd, m_xContext, rFilterOptions );
261 :
262 4 : if( bSuccess )
263 4 : pSink->emit(*rEmitter,*m_pVisitorFactory);
264 :
265 4 : return bSuccess;
266 : }
267 :
268 2 : bool PDFIRawAdaptor::odfConvert( const OUString& rURL,
269 : const uno::Reference<io::XOutputStream>& xOutput,
270 : const uno::Reference<task::XStatusIndicator>& xStatus )
271 : {
272 2 : XmlEmitterSharedPtr pEmitter = createOdfEmitter(xOutput);
273 : const bool bSuccess = parse(uno::Reference<io::XInputStream>(),
274 : uno::Reference<task::XInteractionHandler>(),
275 : OUString(),
276 2 : xStatus,pEmitter,rURL);
277 :
278 : // tell input stream that it is no longer needed
279 2 : xOutput->closeOutput();
280 :
281 2 : return bSuccess;
282 : }
283 :
284 : // XImportFilter
285 2 : 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 )
288 : {
289 : // get the InputStream carrying the PDF content
290 2 : uno::Reference< io::XInputStream > xInput;
291 4 : uno::Reference< task::XStatusIndicator > xStatus;
292 4 : uno::Reference< task::XInteractionHandler > xInteractionHandler;
293 4 : OUString aURL;
294 4 : OUString aPwd;
295 4 : OUString aFilterOptions;
296 2 : const beans::PropertyValue* pAttribs = rSourceData.getConstArray();
297 2 : sal_Int32 nAttribs = rSourceData.getLength();
298 13 : for( sal_Int32 i = 0; i < nAttribs; i++, pAttribs++ )
299 : {
300 : SAL_INFO("sdext.pdfimport","importer Attrib: " << OUStringToOString( pAttribs->Name, RTL_TEXTENCODING_UTF8 ).getStr() );
301 11 : if ( pAttribs->Name == "InputStream" )
302 2 : pAttribs->Value >>= xInput;
303 9 : else if ( pAttribs->Name == "URL" )
304 2 : pAttribs->Value >>= aURL;
305 7 : else if ( pAttribs->Name == "StatusIndicator" )
306 0 : pAttribs->Value >>= xStatus;
307 7 : else if ( pAttribs->Name == "InteractionHandler" )
308 0 : pAttribs->Value >>= xInteractionHandler;
309 7 : else if ( pAttribs->Name == "Password" )
310 0 : pAttribs->Value >>= aPwd;
311 7 : else if ( pAttribs->Name == "FilterOptions" )
312 1 : pAttribs->Value >>= aFilterOptions;
313 : }
314 2 : if( !xInput.is() )
315 0 : return sal_False;
316 :
317 4 : XmlEmitterSharedPtr pEmitter = createSaxEmitter(rHdl);
318 : const bool bSuccess = parse(xInput, xInteractionHandler,
319 2 : aPwd, xStatus, pEmitter, aURL, aFilterOptions);
320 :
321 : // tell input stream that it is no longer needed
322 2 : xInput->closeInput();
323 2 : xInput.clear();
324 :
325 4 : return bSuccess;
326 : }
327 :
328 : //XImporter
329 0 : void SAL_CALL PDFIRawAdaptor::setTargetDocument( const uno::Reference< lang::XComponent >& xDocument ) throw( lang::IllegalArgumentException, std::exception )
330 : {
331 : SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
332 0 : m_xModel = uno::Reference< frame::XModel >( xDocument, uno::UNO_QUERY );
333 0 : if( xDocument.is() && ! m_xModel.is() )
334 0 : throw lang::IllegalArgumentException();
335 0 : }
336 :
337 3 : OUString PDFIRawAdaptor::getImplementationName()
338 : throw (css::uno::RuntimeException, std::exception)
339 : {
340 3 : return m_implementationName;
341 : }
342 :
343 0 : sal_Bool PDFIRawAdaptor::supportsService(OUString const & ServiceName)
344 : throw (css::uno::RuntimeException, std::exception)
345 : {
346 0 : return cppu::supportsService(this, ServiceName);
347 : }
348 :
349 3 : css::uno::Sequence<OUString> PDFIRawAdaptor::getSupportedServiceNames()
350 : throw (css::uno::RuntimeException, std::exception)
351 : {
352 3 : return css::uno::Sequence<OUString>{"com.sun.star.document.ImportFilter"};
353 : }
354 :
355 : }
356 :
357 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|