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, std::exception )
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 : SAL_INFO("sdext.pdfimport", "filter: Attrib: " << pAttribs[i].Name
72 : << " = " << (pAttribs[i].Value.has<OUString>()
73 : ? pAttribs[i].Value.get<OUString>()
74 : : OUString("<no string>"))
75 : << "\n");
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 = "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 : }
181 : else
182 0 : SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no embedded substream set" );
183 : }
184 : else
185 : SAL_INFO("sdext.pdfimport", "PDFIAdaptor::filter: no model set" );
186 :
187 0 : return bRet;
188 : }
189 :
190 0 : void SAL_CALL PDFIHybridAdaptor::cancel() throw(std::exception)
191 : {
192 0 : }
193 :
194 : //XImporter
195 0 : void SAL_CALL PDFIHybridAdaptor::setTargetDocument( const uno::Reference< lang::XComponent >& xDocument ) throw( lang::IllegalArgumentException, std::exception )
196 : {
197 : SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
198 0 : m_xModel = uno::Reference< frame::XModel >( xDocument, uno::UNO_QUERY );
199 0 : if( xDocument.is() && ! m_xModel.is() )
200 0 : throw lang::IllegalArgumentException();
201 0 : }
202 :
203 :
204 :
205 0 : PDFIRawAdaptor::PDFIRawAdaptor( const uno::Reference< uno::XComponentContext >& xContext ) :
206 : PDFIAdaptorBase( m_aMutex ),
207 : m_xContext( xContext ),
208 : m_xModel(),
209 : m_pVisitorFactory(),
210 0 : m_bEnableToplevelText(false)
211 : {
212 0 : }
213 :
214 0 : void PDFIRawAdaptor::setTreeVisitorFactory(const TreeVisitorFactorySharedPtr& rVisitorFactory)
215 : {
216 0 : m_pVisitorFactory = rVisitorFactory;
217 0 : }
218 :
219 0 : bool PDFIRawAdaptor::parse( const uno::Reference<io::XInputStream>& xInput,
220 : const uno::Reference<task::XInteractionHandler>& xIHdl,
221 : const OUString& rPwd,
222 : const uno::Reference<task::XStatusIndicator>& xStatus,
223 : const XmlEmitterSharedPtr& rEmitter,
224 : const OUString& rURL )
225 : {
226 : // container for metaformat
227 : boost::shared_ptr<PDFIProcessor> pSink(
228 0 : new PDFIProcessor(xStatus, m_xContext));
229 :
230 : // TEMP! TEMP!
231 0 : if( m_bEnableToplevelText )
232 0 : pSink->enableToplevelText();
233 :
234 0 : bool bSuccess=false;
235 :
236 0 : if( xInput.is() )
237 0 : bSuccess = xpdf_ImportFromStream( xInput, pSink, xIHdl, rPwd, m_xContext );
238 : else
239 0 : bSuccess = xpdf_ImportFromFile( rURL, pSink, xIHdl, rPwd, m_xContext );
240 :
241 0 : if( bSuccess )
242 0 : pSink->emit(*rEmitter,*m_pVisitorFactory);
243 :
244 0 : return bSuccess;
245 : }
246 :
247 0 : bool PDFIRawAdaptor::odfConvert( const OUString& rURL,
248 : const uno::Reference<io::XOutputStream>& xOutput,
249 : const uno::Reference<task::XStatusIndicator>& xStatus )
250 : {
251 0 : XmlEmitterSharedPtr pEmitter = createOdfEmitter(xOutput);
252 : const bool bSuccess = parse(uno::Reference<io::XInputStream>(),
253 : uno::Reference<task::XInteractionHandler>(),
254 : OUString(),
255 0 : xStatus,pEmitter,rURL);
256 :
257 : // tell input stream that it is no longer needed
258 0 : xOutput->closeOutput();
259 :
260 0 : return bSuccess;
261 : }
262 :
263 : // XImportFilter
264 0 : sal_Bool SAL_CALL PDFIRawAdaptor::importer( const uno::Sequence< beans::PropertyValue >& rSourceData,
265 : const uno::Reference< xml::sax::XDocumentHandler >& rHdl,
266 : const uno::Sequence< OUString >& /*rUserData*/ ) throw( uno::RuntimeException, std::exception )
267 : {
268 : // get the InputStream carrying the PDF content
269 0 : uno::Reference< io::XInputStream > xInput;
270 0 : uno::Reference< task::XStatusIndicator > xStatus;
271 0 : uno::Reference< task::XInteractionHandler > xInteractionHandler;
272 0 : OUString aURL;
273 0 : OUString aPwd;
274 0 : const beans::PropertyValue* pAttribs = rSourceData.getConstArray();
275 0 : sal_Int32 nAttribs = rSourceData.getLength();
276 0 : for( sal_Int32 i = 0; i < nAttribs; i++, pAttribs++ )
277 : {
278 : SAL_INFO("sdext.pdfimport","importer Attrib: " << OUStringToOString( pAttribs->Name, RTL_TEXTENCODING_UTF8 ).getStr() );
279 0 : if ( pAttribs->Name == "InputStream" )
280 0 : pAttribs->Value >>= xInput;
281 0 : else if ( pAttribs->Name == "URL" )
282 0 : pAttribs->Value >>= aURL;
283 0 : else if ( pAttribs->Name == "StatusIndicator" )
284 0 : pAttribs->Value >>= xStatus;
285 0 : else if ( pAttribs->Name == "InteractionHandler" )
286 0 : pAttribs->Value >>= xInteractionHandler;
287 0 : else if ( pAttribs->Name == "Password" )
288 0 : pAttribs->Value >>= aPwd;
289 : }
290 0 : if( !xInput.is() )
291 0 : return sal_False;
292 :
293 0 : XmlEmitterSharedPtr pEmitter = createSaxEmitter(rHdl);
294 0 : const bool bSuccess = parse(xInput,xInteractionHandler, aPwd, xStatus,pEmitter,aURL);
295 :
296 : // tell input stream that it is no longer needed
297 0 : xInput->closeInput();
298 0 : xInput.clear();
299 :
300 0 : return bSuccess;
301 : }
302 :
303 : //XImporter
304 0 : void SAL_CALL PDFIRawAdaptor::setTargetDocument( const uno::Reference< lang::XComponent >& xDocument ) throw( lang::IllegalArgumentException, std::exception )
305 : {
306 : SAL_INFO("sdext.pdfimport", "PDFIAdaptor::setTargetDocument" );
307 0 : m_xModel = uno::Reference< frame::XModel >( xDocument, uno::UNO_QUERY );
308 0 : if( xDocument.is() && ! m_xModel.is() )
309 0 : throw lang::IllegalArgumentException();
310 0 : }
311 :
312 : }
313 :
314 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|