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