Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "pdfiadaptor.hxx"
31 : : #include "filterdet.hxx"
32 : : #include "saxemitter.hxx"
33 : : #include "odfemitter.hxx"
34 : : #include "inc/wrapper.hxx"
35 : : #include "inc/contentsink.hxx"
36 : : #include "tree/pdfiprocessor.hxx"
37 : :
38 : : #include <osl/file.h>
39 : : #include <osl/thread.h>
40 : : #include <osl/diagnose.h>
41 : : #include <cppuhelper/factory.hxx>
42 : : #include <cppuhelper/implementationentry.hxx>
43 : : #include <com/sun/star/lang/XMultiComponentFactory.hpp>
44 : : #include <com/sun/star/uno/RuntimeException.hpp>
45 : : #include <com/sun/star/io/XInputStream.hpp>
46 : : #include <com/sun/star/frame/XLoadable.hpp>
47 : : #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
48 : : #include <com/sun/star/io/XSeekable.hpp>
49 : :
50 : :
51 : : #include <boost/shared_ptr.hpp>
52 : :
53 : : using namespace com::sun::star;
54 : :
55 : :
56 : : namespace pdfi
57 : : {
58 : :
59 : 0 : PDFIHybridAdaptor::PDFIHybridAdaptor( const uno::Reference< uno::XComponentContext >& xContext ) :
60 : : PDFIHybridAdaptorBase( m_aMutex ),
61 : : m_xContext( xContext ),
62 : 0 : m_xModel()
63 : : {
64 : 0 : }
65 : :
66 : : // XFilter
67 : 0 : sal_Bool SAL_CALL PDFIHybridAdaptor::filter( const uno::Sequence< beans::PropertyValue >& rFilterData ) throw( uno::RuntimeException )
68 : : {
69 : 0 : sal_Bool bRet = sal_False;
70 [ # # ]: 0 : if( m_xModel.is() )
71 : : {
72 : 0 : uno::Reference< io::XStream > xSubStream;
73 : 0 : rtl::OUString aPwd;
74 : 0 : const beans::PropertyValue* pAttribs = rFilterData.getConstArray();
75 : 0 : sal_Int32 nAttribs = rFilterData.getLength();
76 : 0 : sal_Int32 nPwPos = -1;
77 [ # # ]: 0 : for( sal_Int32 i = 0; i < nAttribs; i++ )
78 : : {
79 : : #if OSL_DEBUG_LEVEL > 1
80 : : rtl::OUString aVal( RTL_CONSTASCII_USTRINGPARAM( "<no string>" ) );
81 : : pAttribs[i].Value >>= aVal;
82 : : OSL_TRACE( "filter: Attrib: %s = %s\n",
83 : : rtl::OUStringToOString( pAttribs[i].Name, RTL_TEXTENCODING_UTF8 ).getStr(),
84 : : rtl::OUStringToOString( aVal, RTL_TEXTENCODING_UTF8 ).getStr() );
85 : : #endif
86 [ # # ]: 0 : if ( pAttribs[i].Name == "EmbeddedSubstream" )
87 [ # # ]: 0 : pAttribs[i].Value >>= xSubStream;
88 [ # # ]: 0 : else if ( pAttribs[i].Name == "Password" )
89 : : {
90 : 0 : nPwPos = i;
91 : 0 : pAttribs[i].Value >>= aPwd;
92 : : }
93 : : }
94 : 0 : bool bAddPwdProp = false;
95 [ # # ]: 0 : if( ! xSubStream.is() )
96 : : {
97 : 0 : uno::Reference< io::XInputStream > xInput;
98 [ # # ]: 0 : for( sal_Int32 i = 0; i < nAttribs; i++ )
99 : : {
100 [ # # ]: 0 : if ( pAttribs[i].Name == "InputStream" )
101 : : {
102 [ # # ]: 0 : pAttribs[i].Value >>= xInput;
103 : 0 : break;
104 : : }
105 : : }
106 [ # # ]: 0 : if( xInput.is() )
107 : : {
108 : : // TODO(P2): extracting hybrid substream twice - once during detection, second time here
109 [ # # ]: 0 : uno::Reference< io::XSeekable > xSeek( xInput, uno::UNO_QUERY );
110 [ # # ]: 0 : if( xSeek.is() )
111 [ # # ][ # # ]: 0 : xSeek->seek( 0 );
112 : 0 : oslFileHandle aFile = NULL;
113 : 0 : sal_uInt64 nWritten = 0;
114 : 0 : rtl::OUString aURL;
115 [ # # ][ # # ]: 0 : if( osl_createTempFile( NULL, &aFile, &aURL.pData ) == osl_File_E_None )
116 : : {
117 : : OSL_TRACE( "created temp file %s", rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() );
118 : 0 : const sal_Int32 nBufSize = 4096;
119 [ # # ]: 0 : uno::Sequence<sal_Int8> aBuf(nBufSize);
120 : : // copy the bytes
121 : : sal_Int32 nBytes;
122 [ # # ]: 0 : do
123 : : {
124 [ # # ][ # # ]: 0 : nBytes = xInput->readBytes( aBuf, nBufSize );
125 [ # # ]: 0 : if( nBytes > 0 )
126 : : {
127 [ # # ]: 0 : osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
128 [ # # ]: 0 : if( static_cast<sal_Int32>(nWritten) != nBytes )
129 : : {
130 : 0 : xInput.clear();
131 : 0 : break;
132 : : }
133 : : }
134 : : } while( nBytes == nBufSize );
135 [ # # ]: 0 : osl_closeFile( aFile );
136 [ # # ]: 0 : if( xInput.is() )
137 : : {
138 : 0 : rtl::OUString aEmbedMimetype;
139 : 0 : rtl::OUString aOrgPwd( aPwd );
140 [ # # ][ # # ]: 0 : xSubStream = getAdditionalStream( aURL, aEmbedMimetype, aPwd, m_xContext, rFilterData, true );
141 [ # # ]: 0 : if( aOrgPwd != aPwd )
142 : 0 : bAddPwdProp = true;
143 : : }
144 [ # # ][ # # ]: 0 : osl_removeFile( aURL.pData );
145 : : }
146 : : else
147 : 0 : xSubStream.clear();
148 : 0 : }
149 : : }
150 [ # # ]: 0 : if( xSubStream.is() )
151 : : {
152 [ # # ]: 0 : uno::Sequence< uno::Any > aArgs( 2 );
153 [ # # ][ # # ]: 0 : aArgs[0] <<= m_xModel;
154 [ # # ][ # # ]: 0 : aArgs[1] <<= xSubStream;
155 : :
156 : : OSL_TRACE( "try to instantiate subfilter" );
157 : 0 : uno::Reference< document::XFilter > xSubFilter;
158 : : try {
159 : : xSubFilter = uno::Reference<document::XFilter>(
160 [ # # ]: 0 : m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
[ # # # # ]
[ # # ]
161 : : rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.OwnSubFilter" ) ),
162 : : aArgs,
163 : 0 : m_xContext ),
164 [ # # ][ # # ]: 0 : uno::UNO_QUERY );
[ # # ][ # # ]
165 : : }
166 [ # # ]: 0 : catch(const uno::Exception& e)
167 : : {
168 : : (void)e;
169 : : OSL_TRACE( "subfilter exception: %s\n",
170 : : OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
171 : : }
172 : :
173 : : OSL_TRACE( "subfilter: %p", xSubFilter.get() );
174 [ # # ]: 0 : if( xSubFilter.is() )
175 : : {
176 [ # # ]: 0 : if( bAddPwdProp )
177 : : {
178 [ # # ]: 0 : uno::Sequence<beans::PropertyValue> aFilterData( rFilterData );
179 [ # # ]: 0 : if( nPwPos == -1 )
180 : : {
181 : 0 : nPwPos = aFilterData.getLength();
182 [ # # ]: 0 : aFilterData.realloc( nPwPos+1 );
183 [ # # ]: 0 : aFilterData[nPwPos].Name = rtl::OUString(
184 [ # # ]: 0 : RTL_CONSTASCII_USTRINGPARAM( "Password" ) );
185 : : }
186 [ # # ][ # # ]: 0 : aFilterData[nPwPos].Value <<= aPwd;
187 [ # # ][ # # ]: 0 : bRet = xSubFilter->filter( aFilterData );
[ # # ]
188 : : }
189 : : else
190 [ # # ][ # # ]: 0 : bRet = xSubFilter->filter( rFilterData );
191 [ # # ]: 0 : }
192 : 0 : }
193 : : #if OSL_DEBUG_LEVEL > 1
194 : : else
195 : : OSL_TRACE( "PDFIAdaptor::filter: no embedded substream set" );
196 : : #endif
197 : : }
198 : : #if OSL_DEBUG_LEVEL > 1
199 : : else
200 : : OSL_TRACE( "PDFIAdaptor::filter: no model set" );
201 : : #endif
202 : :
203 : 0 : return bRet;
204 : : }
205 : :
206 : 0 : void SAL_CALL PDFIHybridAdaptor::cancel() throw()
207 : : {
208 : 0 : }
209 : :
210 : : //XImporter
211 : 0 : void SAL_CALL PDFIHybridAdaptor::setTargetDocument( const uno::Reference< lang::XComponent >& xDocument ) throw( lang::IllegalArgumentException )
212 : : {
213 : : OSL_TRACE( "PDFIAdaptor::setTargetDocument" );
214 [ # # ]: 0 : m_xModel = uno::Reference< frame::XModel >( xDocument, uno::UNO_QUERY );
215 [ # # ][ # # ]: 0 : if( xDocument.is() && ! m_xModel.is() )
[ # # ]
216 [ # # ]: 0 : throw lang::IllegalArgumentException();
217 : 0 : }
218 : :
219 : : //---------------------------------------------------------------------------------------
220 : :
221 : 6 : PDFIRawAdaptor::PDFIRawAdaptor( const uno::Reference< uno::XComponentContext >& xContext ) :
222 : : PDFIAdaptorBase( m_aMutex ),
223 : : m_xContext( xContext ),
224 : : m_xModel(),
225 : : m_pVisitorFactory(),
226 [ + - ]: 6 : m_bEnableToplevelText(false)
227 : : {
228 : 6 : }
229 : :
230 : 6 : void PDFIRawAdaptor::setTreeVisitorFactory(const TreeVisitorFactorySharedPtr& rVisitorFactory)
231 : : {
232 : 6 : m_pVisitorFactory = rVisitorFactory;
233 : 6 : }
234 : :
235 : 6 : bool PDFIRawAdaptor::parse( const uno::Reference<io::XInputStream>& xInput,
236 : : const uno::Reference<task::XInteractionHandler>& xIHdl,
237 : : const rtl::OUString& rPwd,
238 : : const uno::Reference<task::XStatusIndicator>& xStatus,
239 : : const XmlEmitterSharedPtr& rEmitter,
240 : : const rtl::OUString& rURL )
241 : : {
242 : : // container for metaformat
243 : : boost::shared_ptr<PDFIProcessor> pSink(
244 [ + - ][ + - ]: 6 : new PDFIProcessor(xStatus, m_xContext));
[ + - ]
245 : :
246 : : // TEMP! TEMP!
247 [ - + ]: 6 : if( m_bEnableToplevelText )
248 [ # # ]: 0 : pSink->enableToplevelText();
249 : :
250 : 6 : bool bSuccess=false;
251 : :
252 [ - + ]: 6 : if( xInput.is() )
253 [ # # ][ # # ]: 0 : bSuccess = xpdf_ImportFromStream( xInput, pSink, xIHdl, rPwd, m_xContext );
[ # # ]
254 : : else
255 [ + - ][ + - ]: 6 : bSuccess = xpdf_ImportFromFile( rURL, pSink, xIHdl, rPwd, m_xContext );
[ + - ]
256 : :
257 [ + - ]: 6 : if( bSuccess )
258 [ + - ]: 6 : pSink->emit(*rEmitter,*m_pVisitorFactory);
259 : :
260 [ + - ]: 6 : return bSuccess;
261 : : }
262 : :
263 : 6 : bool PDFIRawAdaptor::odfConvert( const rtl::OUString& rURL,
264 : : const uno::Reference<io::XOutputStream>& xOutput,
265 : : const uno::Reference<task::XStatusIndicator>& xStatus )
266 : : {
267 [ + - ]: 6 : XmlEmitterSharedPtr pEmitter = createOdfEmitter(xOutput);
268 : : const bool bSuccess = parse(uno::Reference<io::XInputStream>(),
269 : : uno::Reference<task::XInteractionHandler>(),
270 : : rtl::OUString(),
271 [ + - ]: 6 : xStatus,pEmitter,rURL);
272 : :
273 : : // tell input stream that it is no longer needed
274 [ + - ][ + - ]: 6 : xOutput->closeOutput();
275 : :
276 [ + - ]: 6 : return bSuccess;
277 : : }
278 : :
279 : : // XImportFilter
280 : 0 : sal_Bool SAL_CALL PDFIRawAdaptor::importer( const uno::Sequence< beans::PropertyValue >& rSourceData,
281 : : const uno::Reference< xml::sax::XDocumentHandler >& rHdl,
282 : : const uno::Sequence< rtl::OUString >& /*rUserData*/ ) throw( uno::RuntimeException )
283 : : {
284 : : // get the InputStream carrying the PDF content
285 : 0 : uno::Reference< io::XInputStream > xInput;
286 : 0 : uno::Reference< task::XStatusIndicator > xStatus;
287 : 0 : uno::Reference< task::XInteractionHandler > xInteractionHandler;
288 : 0 : rtl::OUString aURL;
289 : 0 : rtl::OUString aPwd;
290 : 0 : const beans::PropertyValue* pAttribs = rSourceData.getConstArray();
291 : 0 : sal_Int32 nAttribs = rSourceData.getLength();
292 [ # # ]: 0 : for( sal_Int32 i = 0; i < nAttribs; i++, pAttribs++ )
293 : : {
294 : : OSL_TRACE("importer Attrib: %s", OUStringToOString( pAttribs->Name, RTL_TEXTENCODING_UTF8 ).getStr() );
295 [ # # ]: 0 : if ( pAttribs->Name == "InputStream" )
296 [ # # ]: 0 : pAttribs->Value >>= xInput;
297 [ # # ]: 0 : else if ( pAttribs->Name == "URL" )
298 : 0 : pAttribs->Value >>= aURL;
299 [ # # ]: 0 : else if ( pAttribs->Name == "StatusIndicator" )
300 [ # # ]: 0 : pAttribs->Value >>= xStatus;
301 [ # # ]: 0 : else if ( pAttribs->Name == "InteractionHandler" )
302 [ # # ]: 0 : pAttribs->Value >>= xInteractionHandler;
303 [ # # ]: 0 : else if ( pAttribs->Name == "Password" )
304 : 0 : pAttribs->Value >>= aPwd;
305 : : }
306 [ # # ]: 0 : if( !xInput.is() )
307 : 0 : return sal_False;
308 : :
309 [ # # ]: 0 : XmlEmitterSharedPtr pEmitter = createSaxEmitter(rHdl);
310 [ # # ]: 0 : const bool bSuccess = parse(xInput,xInteractionHandler, aPwd, xStatus,pEmitter,aURL);
311 : :
312 : : // tell input stream that it is no longer needed
313 [ # # ][ # # ]: 0 : xInput->closeInput();
314 : 0 : xInput.clear();
315 : :
316 [ # # ]: 0 : return bSuccess;
317 : : }
318 : :
319 : : //XImporter
320 : 0 : void SAL_CALL PDFIRawAdaptor::setTargetDocument( const uno::Reference< lang::XComponent >& xDocument ) throw( lang::IllegalArgumentException )
321 : : {
322 : : OSL_TRACE( "PDFIAdaptor::setTargetDocument" );
323 [ # # ]: 0 : m_xModel = uno::Reference< frame::XModel >( xDocument, uno::UNO_QUERY );
324 [ # # ][ # # ]: 0 : if( xDocument.is() && ! m_xModel.is() )
[ # # ]
325 [ # # ]: 0 : throw lang::IllegalArgumentException();
326 : 0 : }
327 : :
328 : : }
329 : :
330 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|