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 "filterdet.hxx"
22 : #include "inc/pdfihelper.hxx"
23 : #include "inc/pdfparse.hxx"
24 :
25 : #include <osl/diagnose.h>
26 : #include <osl/file.h>
27 : #include <osl/thread.h>
28 : #include <rtl/digest.h>
29 : #include <rtl/ref.hxx>
30 : #include <com/sun/star/uno/RuntimeException.hpp>
31 : #include <com/sun/star/io/XInputStream.hpp>
32 : #include <com/sun/star/io/XStream.hpp>
33 : #include <com/sun/star/io/XSeekable.hpp>
34 : #include <com/sun/star/io/TempFile.hpp>
35 : #include <cppuhelper/supportsservice.hxx>
36 : #include <boost/scoped_ptr.hpp>
37 : #include <string.h>
38 :
39 : using namespace com::sun::star;
40 :
41 : namespace pdfi
42 : {
43 :
44 : // TODO(T3): locking/thread safety
45 :
46 : class FileEmitContext : public pdfparse::EmitContext
47 : {
48 : private:
49 : oslFileHandle m_aReadHandle;
50 : unsigned int m_nReadLen;
51 : uno::Reference< io::XStream > m_xContextStream;
52 : uno::Reference< io::XSeekable > m_xSeek;
53 : uno::Reference< io::XOutputStream > m_xOut;
54 :
55 : public:
56 : FileEmitContext( const OUString& rOrigFile,
57 : const uno::Reference< uno::XComponentContext >& xContext,
58 : const pdfparse::PDFContainer* pTop );
59 : virtual ~FileEmitContext();
60 :
61 : virtual bool write( const void* pBuf, unsigned int nLen ) SAL_OVERRIDE;
62 : virtual unsigned int getCurPos() SAL_OVERRIDE;
63 : virtual bool copyOrigBytes( unsigned int nOrigOffset, unsigned int nLen ) SAL_OVERRIDE;
64 : virtual unsigned int readOrigBytes( unsigned int nOrigOffset, unsigned int nLen, void* pBuf ) SAL_OVERRIDE;
65 :
66 0 : const uno::Reference< io::XStream >& getContextStream() const { return m_xContextStream; }
67 : };
68 :
69 0 : FileEmitContext::FileEmitContext( const OUString& rOrigFile,
70 : const uno::Reference< uno::XComponentContext >& xContext,
71 : const pdfparse::PDFContainer* pTop ) :
72 : pdfparse::EmitContext( pTop ),
73 : m_aReadHandle(NULL),
74 : m_nReadLen(0),
75 : m_xContextStream(),
76 : m_xSeek(),
77 0 : m_xOut()
78 : {
79 0 : m_xContextStream = uno::Reference< io::XStream >(
80 0 : io::TempFile::create(xContext), uno::UNO_QUERY_THROW );
81 0 : m_xOut = m_xContextStream->getOutputStream();
82 0 : m_xSeek = uno::Reference<io::XSeekable>(m_xOut, uno::UNO_QUERY_THROW );
83 :
84 0 : oslFileError aErr = osl_File_E_None;
85 0 : if( (aErr=osl_openFile( rOrigFile.pData,
86 : &m_aReadHandle,
87 0 : osl_File_OpenFlag_Read )) == osl_File_E_None )
88 : {
89 0 : if( (aErr=osl_setFilePos( m_aReadHandle,
90 : osl_Pos_End,
91 0 : 0 )) == osl_File_E_None )
92 : {
93 0 : sal_uInt64 nFileSize = 0;
94 0 : if( (aErr=osl_getFilePos( m_aReadHandle,
95 0 : &nFileSize )) == osl_File_E_None )
96 : {
97 0 : m_nReadLen = static_cast<unsigned int>(nFileSize);
98 : }
99 : }
100 0 : if( aErr != osl_File_E_None )
101 : {
102 0 : osl_closeFile( m_aReadHandle );
103 0 : m_aReadHandle = NULL;
104 : }
105 : }
106 0 : m_bDeflate = true;
107 0 : }
108 :
109 0 : FileEmitContext::~FileEmitContext()
110 : {
111 0 : if( m_aReadHandle )
112 0 : osl_closeFile( m_aReadHandle );
113 0 : }
114 :
115 0 : bool FileEmitContext::write( const void* pBuf, unsigned int nLen )
116 : {
117 0 : if( ! m_xOut.is() )
118 0 : return false;
119 :
120 0 : uno::Sequence< sal_Int8 > aSeq( nLen );
121 0 : memcpy( aSeq.getArray(), pBuf, nLen );
122 0 : m_xOut->writeBytes( aSeq );
123 0 : return true;
124 : }
125 :
126 0 : unsigned int FileEmitContext::getCurPos()
127 : {
128 0 : unsigned int nPos = 0;
129 0 : if( m_xSeek.is() )
130 : {
131 0 : nPos = static_cast<unsigned int>( m_xSeek->getPosition() );
132 : }
133 0 : return nPos;
134 : }
135 :
136 0 : bool FileEmitContext::copyOrigBytes( unsigned int nOrigOffset, unsigned int nLen )
137 : {
138 0 : if( nOrigOffset + nLen > m_nReadLen )
139 0 : return false;
140 :
141 0 : if( osl_setFilePos( m_aReadHandle, osl_Pos_Absolut, nOrigOffset ) != osl_File_E_None )
142 0 : return false;
143 :
144 0 : uno::Sequence< sal_Int8 > aSeq( nLen );
145 :
146 0 : sal_uInt64 nBytesRead = 0;
147 0 : if( osl_readFile( m_aReadHandle,
148 0 : aSeq.getArray(),
149 : nLen,
150 0 : &nBytesRead ) != osl_File_E_None
151 0 : || nBytesRead != static_cast<sal_uInt64>(nLen) )
152 : {
153 0 : return false;
154 : }
155 :
156 0 : m_xOut->writeBytes( aSeq );
157 0 : return true;
158 : }
159 :
160 0 : unsigned int FileEmitContext::readOrigBytes( unsigned int nOrigOffset, unsigned int nLen, void* pBuf )
161 : {
162 0 : if( nOrigOffset + nLen > m_nReadLen )
163 0 : return 0;
164 :
165 0 : if( osl_setFilePos( m_aReadHandle,
166 : osl_Pos_Absolut,
167 0 : nOrigOffset ) != osl_File_E_None )
168 : {
169 0 : return 0;
170 : }
171 :
172 0 : sal_uInt64 nBytesRead = 0;
173 0 : if( osl_readFile( m_aReadHandle,
174 : pBuf,
175 : nLen,
176 0 : &nBytesRead ) != osl_File_E_None )
177 : {
178 0 : return 0;
179 : }
180 0 : return static_cast<unsigned int>(nBytesRead);
181 : }
182 :
183 :
184 :
185 :
186 :
187 85 : PDFDetector::PDFDetector( const uno::Reference< uno::XComponentContext >& xContext) :
188 : PDFDetectorBase( m_aMutex ),
189 85 : m_xContext( xContext )
190 85 : {}
191 :
192 : // XExtendedFilterDetection
193 84 : OUString SAL_CALL PDFDetector::detect( uno::Sequence< beans::PropertyValue >& rFilterData ) throw( uno::RuntimeException, std::exception )
194 : {
195 84 : osl::MutexGuard const guard( m_aMutex );
196 84 : bool bSuccess = false;
197 :
198 : // get the InputStream carrying the PDF content
199 168 : uno::Reference< io::XInputStream > xInput;
200 168 : uno::Reference< io::XStream > xEmbedStream;
201 168 : OUString aOutFilterName, aOutTypeName;
202 168 : OUString aURL;
203 168 : OUString aPwd;
204 84 : const beans::PropertyValue* pAttribs = rFilterData.getConstArray();
205 84 : sal_Int32 nAttribs = rFilterData.getLength();
206 84 : sal_Int32 nFilterNamePos = -1;
207 84 : sal_Int32 nPwdPos = -1;
208 757 : for( sal_Int32 i = 0; i < nAttribs; i++ )
209 : {
210 : #if OSL_DEBUG_LEVEL > 1
211 : OUString aVal( "<no string>" );
212 : pAttribs[i].Value >>= aVal;
213 : OSL_TRACE( "doDetection: Attrib: %s = %s\n",
214 : OUStringToOString( pAttribs[i].Name, RTL_TEXTENCODING_UTF8 ).getStr(),
215 : OUStringToOString( aVal, RTL_TEXTENCODING_UTF8 ).getStr() );
216 : #endif
217 673 : if ( pAttribs[i].Name == "InputStream" )
218 84 : pAttribs[i].Value >>= xInput;
219 589 : else if ( pAttribs[i].Name == "URL" )
220 84 : pAttribs[i].Value >>= aURL;
221 505 : else if ( pAttribs[i].Name == "FilterName" )
222 0 : nFilterNamePos = i;
223 505 : else if ( pAttribs[i].Name == "Password" )
224 : {
225 0 : nPwdPos = i;
226 0 : pAttribs[i].Value >>= aPwd;
227 : }
228 : }
229 84 : if( xInput.is() )
230 : {
231 84 : uno::Reference< io::XSeekable > xSeek( xInput, uno::UNO_QUERY );
232 84 : if( xSeek.is() )
233 84 : xSeek->seek( 0 );
234 : // read the first 1024 byte (see PDF reference implementation note 12)
235 84 : const sal_Int32 nHeaderSize = 1024;
236 168 : uno::Sequence< sal_Int8 > aBuf( nHeaderSize );
237 84 : sal_uInt64 nBytes = 0;
238 84 : nBytes = xInput->readBytes( aBuf, nHeaderSize );
239 84 : if( nBytes > 5 )
240 : {
241 84 : const sal_Int8* pBytes = aBuf.getConstArray();
242 85680 : for( unsigned int i = 0; i < nBytes-5; i++ )
243 : {
244 85601 : if( pBytes[i] == '%' &&
245 5 : pBytes[i+1] == 'P' &&
246 0 : pBytes[i+2] == 'D' &&
247 0 : pBytes[i+3] == 'F' &&
248 0 : pBytes[i+4] == '-' )
249 : {
250 0 : bSuccess = true;
251 0 : break;
252 : }
253 : }
254 : }
255 :
256 : // check for hybrid PDF
257 84 : oslFileHandle aFile = NULL;
258 84 : if( bSuccess &&
259 0 : ( aURL.isEmpty() || !aURL.startsWith( "file:" ) )
260 : )
261 : {
262 0 : sal_uInt64 nWritten = 0;
263 0 : if( osl_createTempFile( NULL, &aFile, &aURL.pData ) != osl_File_E_None )
264 : {
265 0 : bSuccess = false;
266 : }
267 : else
268 : {
269 : #if OSL_DEBUG_LEVEL > 1
270 : OSL_TRACE( "created temp file %s\n",
271 : OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() );
272 : #endif
273 0 : osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
274 :
275 : OSL_ENSURE( nWritten == nBytes, "writing of header bytes failed" );
276 :
277 0 : if( nWritten == nBytes )
278 : {
279 0 : const sal_uInt32 nBufSize = 4096;
280 0 : aBuf = uno::Sequence<sal_Int8>(nBufSize);
281 : // copy the bytes
282 0 : do
283 : {
284 0 : nBytes = xInput->readBytes( aBuf, nBufSize );
285 0 : if( nBytes > 0 )
286 : {
287 0 : osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
288 0 : if( nWritten != nBytes )
289 : {
290 0 : bSuccess = false;
291 0 : break;
292 : }
293 : }
294 : } while( nBytes == nBufSize );
295 : }
296 : }
297 0 : osl_closeFile( aFile );
298 : }
299 168 : OUString aEmbedMimetype;
300 84 : xEmbedStream = getAdditionalStream( aURL, aEmbedMimetype, aPwd, m_xContext, rFilterData, false );
301 84 : if( aFile )
302 0 : osl_removeFile( aURL.pData );
303 84 : if( !aEmbedMimetype.isEmpty() )
304 : {
305 0 : if( aEmbedMimetype == "application/vnd.oasis.opendocument.text"
306 0 : || aEmbedMimetype == "application/vnd.oasis.opendocument.text-master" )
307 0 : aOutFilterName = "writer_pdf_addstream_import";
308 0 : else if ( aEmbedMimetype == "application/vnd.oasis.opendocument.presentation" )
309 0 : aOutFilterName = "impress_pdf_addstream_import";
310 0 : else if( aEmbedMimetype == "application/vnd.oasis.opendocument.graphics"
311 0 : || aEmbedMimetype == "application/vnd.oasis.opendocument.drawing" )
312 0 : aOutFilterName = "draw_pdf_addstream_import";
313 0 : else if ( aEmbedMimetype == "application/vnd.oasis.opendocument.spreadsheet" )
314 0 : aOutFilterName = "calc_pdf_addstream_import";
315 84 : }
316 : }
317 :
318 84 : if( bSuccess )
319 : {
320 0 : if( !aOutFilterName.isEmpty() )
321 : {
322 0 : if( nFilterNamePos == -1 )
323 : {
324 0 : nFilterNamePos = nAttribs;
325 0 : rFilterData.realloc( ++nAttribs );
326 0 : rFilterData[ nFilterNamePos ].Name = "FilterName";
327 : }
328 0 : aOutTypeName = "pdf_Portable_Document_Format";
329 :
330 : OSL_TRACE( "setting filter name %s, input stream %s\n",
331 : OUStringToOString( aOutFilterName, RTL_TEXTENCODING_UTF8 ).getStr(),
332 : xEmbedStream.is() ? "present" : "not present" );
333 :
334 0 : rFilterData[nFilterNamePos].Value <<= aOutFilterName;
335 0 : if( xEmbedStream.is() )
336 : {
337 0 : rFilterData.realloc( ++nAttribs );
338 0 : rFilterData[nAttribs-1].Name = "EmbeddedSubstream";
339 0 : rFilterData[nAttribs-1].Value <<= xEmbedStream;
340 : }
341 0 : if( !aPwd.isEmpty() )
342 : {
343 0 : if( nPwdPos == -1 )
344 : {
345 0 : nPwdPos = nAttribs;
346 0 : rFilterData.realloc( ++nAttribs );
347 0 : rFilterData[ nPwdPos ].Name = "Password";
348 : }
349 0 : rFilterData[ nPwdPos ].Value <<= aPwd;
350 : }
351 : }
352 : else
353 : {
354 0 : if( nFilterNamePos == -1 )
355 : {
356 0 : nFilterNamePos = nAttribs;
357 0 : rFilterData.realloc( ++nAttribs );
358 0 : rFilterData[ nFilterNamePos ].Name = "FilterName";
359 : }
360 :
361 0 : const sal_Int32 nDocumentType = 0; //const sal_Int32 nDocumentType = queryDocumentTypeDialog(m_xContext,aURL);
362 : if( nDocumentType < 0 )
363 : {
364 : return OUString();
365 : }
366 : else switch( nDocumentType )
367 : {
368 : case 0:
369 0 : rFilterData[nFilterNamePos].Value <<= OUString( "draw_pdf_import" );
370 0 : break;
371 :
372 : case 1:
373 : rFilterData[nFilterNamePos].Value <<= OUString( "impress_pdf_import" );
374 : break;
375 :
376 : case 2:
377 : rFilterData[nFilterNamePos].Value <<= OUString( "writer_pdf_import" );
378 : break;
379 :
380 : default:
381 : OSL_FAIL("Unexpected case");
382 : }
383 :
384 0 : aOutTypeName = "pdf_Portable_Document_Format";
385 : }
386 : }
387 :
388 168 : return aOutTypeName;
389 : }
390 :
391 1 : OUString PDFDetector::getImplementationName()
392 : throw (css::uno::RuntimeException, std::exception)
393 : {
394 1 : return OUString("org.libreoffice.comp.documents.PDFDetector");
395 : }
396 :
397 0 : sal_Bool PDFDetector::supportsService(OUString const & ServiceName)
398 : throw (css::uno::RuntimeException, std::exception)
399 : {
400 0 : return cppu::supportsService(this, ServiceName);
401 : }
402 :
403 1 : css::uno::Sequence<OUString> PDFDetector::getSupportedServiceNames()
404 : throw (css::uno::RuntimeException, std::exception)
405 : {
406 1 : return css::uno::Sequence<OUString>{"com.sun.star.document.ImportFilter"};
407 : }
408 :
409 0 : bool checkDocChecksum( const OUString& rInPDFFileURL,
410 : sal_uInt32 nBytes,
411 : const OUString& rChkSum )
412 : {
413 0 : bool bRet = false;
414 0 : if( rChkSum.getLength() != 2* RTL_DIGEST_LENGTH_MD5 )
415 : {
416 : SAL_INFO(
417 : "sdext.pdfimport",
418 : "checksum of length " << rChkSum.getLength() << ", expected "
419 : << 2*RTL_DIGEST_LENGTH_MD5);
420 0 : return false;
421 : }
422 :
423 : // prepare checksum to test
424 : sal_uInt8 nTestChecksum[ RTL_DIGEST_LENGTH_MD5 ];
425 0 : const sal_Unicode* pChar = rChkSum.getStr();
426 0 : for( unsigned int i = 0; i < RTL_DIGEST_LENGTH_MD5; i++ )
427 : {
428 0 : sal_uInt8 nByte = sal_uInt8( ( (*pChar >= '0' && *pChar <= '9') ? *pChar - '0' :
429 0 : ( (*pChar >= 'A' && *pChar <= 'F') ? *pChar - 'A' + 10 :
430 0 : ( (*pChar >= 'a' && *pChar <= 'f') ? *pChar - 'a' + 10 :
431 0 : 0 ) ) ) );
432 0 : nByte <<= 4;
433 0 : pChar++;
434 0 : nByte |= ( (*pChar >= '0' && *pChar <= '9') ? *pChar - '0' :
435 0 : ( (*pChar >= 'A' && *pChar <= 'F') ? *pChar - 'A' + 10 :
436 0 : ( (*pChar >= 'a' && *pChar <= 'f') ? *pChar - 'a' + 10 :
437 0 : 0 ) ) );
438 0 : pChar++;
439 0 : nTestChecksum[i] = nByte;
440 : }
441 :
442 : // open file and calculate actual checksum up to index nBytes
443 : sal_uInt8 nActualChecksum[ RTL_DIGEST_LENGTH_MD5 ];
444 0 : memset( nActualChecksum, 0, sizeof(nActualChecksum) );
445 0 : rtlDigest aActualDigest = rtl_digest_createMD5();
446 0 : oslFileHandle aRead = NULL;
447 0 : oslFileError aErr = osl_File_E_None;
448 0 : if( (aErr = osl_openFile(rInPDFFileURL.pData,
449 : &aRead,
450 0 : osl_File_OpenFlag_Read )) == osl_File_E_None )
451 : {
452 : sal_Int8 aBuf[4096];
453 0 : sal_uInt32 nCur = 0;
454 0 : sal_uInt64 nBytesRead = 0;
455 0 : while( nCur < nBytes )
456 : {
457 0 : sal_uInt32 nPass = (nBytes - nCur) > sizeof( aBuf ) ? sizeof( aBuf ) : nBytes - nCur;
458 0 : if( (aErr = osl_readFile( aRead, aBuf, nPass, &nBytesRead)) != osl_File_E_None
459 0 : || nBytesRead == 0 )
460 : {
461 0 : break;
462 : }
463 0 : nPass = static_cast<sal_uInt32>(nBytesRead);
464 0 : nCur += nPass;
465 0 : rtl_digest_updateMD5( aActualDigest, aBuf, nPass );
466 : }
467 0 : rtl_digest_getMD5( aActualDigest, nActualChecksum, sizeof(nActualChecksum) );
468 0 : osl_closeFile( aRead );
469 : }
470 0 : rtl_digest_destroyMD5( aActualDigest );
471 :
472 : // compare the contents
473 0 : bRet = (0 == memcmp( nActualChecksum, nTestChecksum, sizeof( nActualChecksum ) ));
474 : #if OSL_DEBUG_LEVEL > 1
475 : OSL_TRACE( "test checksum: " );
476 : for( unsigned int i = 0; i < sizeof(nTestChecksum); i++ )
477 : OSL_TRACE( "%.2X", int(nTestChecksum[i]) );
478 : OSL_TRACE( "\n" );
479 : OSL_TRACE( "file checksum: " );
480 : for( unsigned int i = 0; i < sizeof(nActualChecksum); i++ )
481 : OSL_TRACE( "%.2X", int(nActualChecksum[i]) );
482 : OSL_TRACE( "\n" );
483 : #endif
484 0 : return bRet;
485 : }
486 :
487 84 : uno::Reference< io::XStream > getAdditionalStream( const OUString& rInPDFFileURL,
488 : OUString& rOutMimetype,
489 : OUString& io_rPwd,
490 : const uno::Reference<uno::XComponentContext>& xContext,
491 : const uno::Sequence<beans::PropertyValue>& rFilterData,
492 : bool bMayUseUI )
493 : {
494 84 : uno::Reference< io::XStream > xEmbed;
495 168 : OString aPDFFile;
496 168 : OUString aSysUPath;
497 84 : if( osl_getSystemPathFromFileURL( rInPDFFileURL.pData, &aSysUPath.pData ) != osl_File_E_None )
498 0 : return xEmbed;
499 84 : aPDFFile = OUStringToOString( aSysUPath, osl_getThreadTextEncoding() );
500 :
501 168 : pdfparse::PDFReader aParser;
502 168 : boost::scoped_ptr<pdfparse::PDFEntry> pEntry( pdfparse::PDFReader::read( aPDFFile.getStr() ));
503 84 : if( pEntry )
504 : {
505 0 : pdfparse::PDFFile* pPDFFile = dynamic_cast<pdfparse::PDFFile*>(pEntry.get());
506 0 : if( pPDFFile )
507 : {
508 0 : unsigned int nElements = pPDFFile->m_aSubElements.size();
509 0 : while( nElements-- > 0 )
510 : {
511 0 : pdfparse::PDFTrailer* pTrailer = dynamic_cast<pdfparse::PDFTrailer*>(pPDFFile->m_aSubElements[nElements]);
512 0 : if( pTrailer && pTrailer->m_pDict )
513 : {
514 : // search document checksum entry
515 : std::unordered_map< OString,
516 : pdfparse::PDFEntry*,
517 0 : OStringHash >::iterator chk;
518 0 : chk = pTrailer->m_pDict->m_aMap.find( "DocChecksum" );
519 0 : if( chk == pTrailer->m_pDict->m_aMap.end() )
520 : {
521 : OSL_TRACE( "no DocChecksum entry" );
522 0 : continue;
523 : }
524 0 : pdfparse::PDFName* pChkSumName = dynamic_cast<pdfparse::PDFName*>(chk->second);
525 0 : if( pChkSumName == NULL )
526 : {
527 : OSL_TRACE( "no name for DocChecksum entry" );
528 0 : continue;
529 : }
530 :
531 : // search for AdditionalStreams entry
532 : std::unordered_map< OString,
533 : pdfparse::PDFEntry*,
534 0 : OStringHash >::iterator add_stream;
535 0 : add_stream = pTrailer->m_pDict->m_aMap.find( "AdditionalStreams" );
536 0 : if( add_stream == pTrailer->m_pDict->m_aMap.end() )
537 : {
538 : OSL_TRACE( "no AdditionalStreams entry" );
539 0 : continue;
540 : }
541 0 : pdfparse::PDFArray* pStreams = dynamic_cast<pdfparse::PDFArray*>(add_stream->second);
542 0 : if( ! pStreams || pStreams->m_aSubElements.size() < 2 )
543 : {
544 : OSL_TRACE( "AdditionalStreams array too small" );
545 0 : continue;
546 : }
547 :
548 : // check checksum
549 0 : OUString aChkSum = pChkSumName->getFilteredName();
550 0 : if( ! checkDocChecksum( rInPDFFileURL, pTrailer->m_nOffset, aChkSum ) )
551 0 : continue;
552 :
553 : // extract addstream and mimetype
554 0 : pdfparse::PDFName* pMimeType = dynamic_cast<pdfparse::PDFName*>(pStreams->m_aSubElements[0]);
555 0 : pdfparse::PDFObjectRef* pStreamRef = dynamic_cast<pdfparse::PDFObjectRef*>(pStreams->m_aSubElements[1]);
556 :
557 : OSL_ENSURE( pMimeType, "error: no mimetype element\n" );
558 : OSL_ENSURE( pStreamRef, "error: no stream ref element\n" );
559 :
560 0 : if( pMimeType && pStreamRef )
561 : {
562 0 : pdfparse::PDFObject* pObject = pPDFFile->findObject( pStreamRef->m_nNumber, pStreamRef->m_nGeneration );
563 : OSL_ENSURE( pObject, "object not found\n" );
564 0 : if( pObject )
565 : {
566 0 : if( pPDFFile->isEncrypted() )
567 : {
568 0 : bool bAuthenticated = false;
569 0 : if( !io_rPwd.isEmpty() )
570 : {
571 : OString aIsoPwd = OUStringToOString( io_rPwd,
572 0 : RTL_TEXTENCODING_ISO_8859_1 );
573 0 : bAuthenticated = pPDFFile->setupDecryptionData( aIsoPwd.getStr() );
574 : }
575 0 : if( ! bAuthenticated )
576 : {
577 0 : const beans::PropertyValue* pAttribs = rFilterData.getConstArray();
578 0 : sal_Int32 nAttribs = rFilterData.getLength();
579 0 : uno::Reference< task::XInteractionHandler > xIntHdl;
580 0 : for( sal_Int32 i = 0; i < nAttribs; i++ )
581 : {
582 0 : if ( pAttribs[i].Name == "InteractionHandler" )
583 0 : pAttribs[i].Value >>= xIntHdl;
584 : }
585 0 : if( ! bMayUseUI || ! xIntHdl.is() )
586 : {
587 0 : rOutMimetype = pMimeType->getFilteredName();
588 0 : xEmbed.clear();
589 0 : break;
590 : }
591 :
592 0 : OUString aDocName( rInPDFFileURL.copy( rInPDFFileURL.lastIndexOf( '/' )+1 ) );
593 :
594 0 : bool bEntered = false;
595 0 : do
596 : {
597 0 : bEntered = getPassword( xIntHdl, io_rPwd, ! bEntered, aDocName );
598 : OString aIsoPwd = OUStringToOString( io_rPwd,
599 0 : RTL_TEXTENCODING_ISO_8859_1 );
600 0 : bAuthenticated = pPDFFile->setupDecryptionData( aIsoPwd.getStr() );
601 0 : } while( bEntered && ! bAuthenticated );
602 : }
603 :
604 : OSL_TRACE( "password: %s", bAuthenticated ? "matches" : "does not match" );
605 0 : if( ! bAuthenticated )
606 0 : continue;
607 : }
608 0 : rOutMimetype = pMimeType->getFilteredName();
609 : FileEmitContext aContext( rInPDFFileURL,
610 : xContext,
611 0 : pPDFFile );
612 0 : aContext.m_bDecrypt = pPDFFile->isEncrypted();
613 0 : pObject->writeStream( aContext, pPDFFile );
614 0 : xEmbed = aContext.getContextStream();
615 0 : break; // success
616 : }
617 0 : }
618 : }
619 : }
620 : }
621 : }
622 :
623 : OSL_TRACE( "extracted add stream: mimetype %s\n",
624 : OUStringToOString( rOutMimetype,
625 : RTL_TEXTENCODING_UTF8 ).getStr());
626 84 : return xEmbed;
627 : }
628 :
629 : }
630 :
631 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|