1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: filterdet.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_sdext.hxx"
35 #include "filterdet.hxx"
36 #include "inc/pdfparse.hxx"
38 #include <osl/diagnose.h>
40 #include <osl/thread.h>
41 #include <rtl/digest.h>
42 #include <rtl/ref.hxx>
43 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/awt/XWindow.hpp>
46 #include <com/sun/star/awt/XListBox.hpp>
47 #include <com/sun/star/awt/XDialogEventHandler.hpp>
48 #include <com/sun/star/awt/XDialogProvider2.hpp>
49 #include <com/sun/star/awt/XControlContainer.hpp>
50 #include <com/sun/star/uno/RuntimeException.hpp>
51 #include <com/sun/star/io/XInputStream.hpp>
52 #include <com/sun/star/io/XStream.hpp>
53 #include <com/sun/star/io/XSeekable.hpp>
55 #include <boost/scoped_ptr.hpp>
57 using namespace com::sun::star
;
62 // TODO(T3): locking/thread safety
65 typedef ::cppu::WeakComponentImplHelper1
<
66 com::sun::star::awt::XDialogEventHandler
> ChooserDialogHandlerBase
;
67 class ChooserDialogHandler
: private cppu::BaseMutex
,
68 public ChooserDialogHandlerBase
70 uno::Reference
<awt::XListBox
> m_xListbox
;
71 uno::Reference
<awt::XWindow
> m_xWriterText
;
72 uno::Reference
<awt::XWindow
> m_xDrawText
;
73 uno::Reference
<awt::XWindow
> m_xImpressText
;
75 enum{ DRAW_INDEX
=0, IMPRESS_INDEX
=1, WRITER_INDEX
=2 };
76 void selectionChanged( sal_Int32 nIndex
) const
78 sal_Bool
bWriterState(sal_False
);
79 sal_Bool
bDrawState(sal_False
);
80 sal_Bool
bImpressState(sal_False
);
84 OSL_ENSURE(false,"Unexpected case!");
90 bImpressState
=sal_True
;
93 bWriterState
=sal_True
;
96 m_xWriterText
->setVisible(bWriterState
);
97 m_xDrawText
->setVisible(bDrawState
);
98 m_xImpressText
->setVisible(bImpressState
);
101 ChooserDialogHandler() :
102 ChooserDialogHandlerBase(m_aMutex
),
109 void initControls( const uno::Reference
<awt::XControlContainer
>& xControls
,
110 const rtl::OUString
& rFilename
)
112 m_xListbox
.set(xControls
->getControl(
113 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListBox" ))),
114 uno::UNO_QUERY_THROW
);
115 m_xWriterText
.set(xControls
->getControl(
116 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InfoWriter" ))),
117 uno::UNO_QUERY_THROW
);
118 m_xImpressText
.set(xControls
->getControl(
119 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InfoImpress" ))),
120 uno::UNO_QUERY_THROW
);
121 m_xDrawText
.set(xControls
->getControl(
122 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InfoDraw" ))),
123 uno::UNO_QUERY_THROW
);
125 uno::Reference
<awt::XWindow
> xControl
;
126 xControl
.set(xControls
->getControl(
127 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListBoxWriter" ))),
128 uno::UNO_QUERY_THROW
);
129 xControl
->setVisible(sal_False
);
130 xControl
.set(xControls
->getControl(
131 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListBoxImpress" ))),
132 uno::UNO_QUERY_THROW
);
133 xControl
->setVisible(sal_False
);
134 xControl
.set(xControls
->getControl(
135 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ListBoxDraw" ))),
136 uno::UNO_QUERY_THROW
);
137 xControl
->setVisible(sal_False
);
138 uno::Reference
<beans::XPropertySet
> xPropSet(
139 xControls
->getControl(
140 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ComboLabel" )))->getModel(),
141 uno::UNO_QUERY_THROW
);
142 rtl::OUString
aFilename( rFilename
.copy(rFilename
.lastIndexOf('/')+1) );
143 rtl::OUString aLabel
;
144 xPropSet
->getPropertyValue(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Label" ))) >>= aLabel
;
145 const char pFileName
[] = "%FILENAME";
146 aLabel
= aLabel
.replaceAt(
147 aLabel
.indexOfAsciiL(pFileName
,sizeof(pFileName
)/sizeof(*pFileName
)-1),
148 sizeof(pFileName
)/sizeof(*pFileName
)-1,
150 xPropSet
->setPropertyValue(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Label" )),
151 uno::makeAny(aLabel
));
153 uno::Sequence
<rtl::OUString
> aListboxItems(3);
154 aListboxItems
[DRAW_INDEX
] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Drawing" ));
155 aListboxItems
[IMPRESS_INDEX
] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Presentation" ));
156 aListboxItems
[WRITER_INDEX
] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text Document" ));
158 m_xListbox
->addItems(aListboxItems
,0);
159 m_xListbox
->selectItemPos(0,sal_True
);
163 sal_Int32
getSelectedItem() const
165 return m_xListbox
->getSelectedItemPos();
168 virtual ::sal_Bool SAL_CALL
callHandlerMethod( const uno::Reference
< awt::XDialog
>& /*xDialog*/,
169 const uno::Any
& /*EventObject*/,
170 const ::rtl::OUString
& MethodName
) throw (lang::WrappedTargetException
, uno::RuntimeException
)
173 OSL_ENSURE( MethodName
.compareToAscii("SelectionChanged") == 0,
174 "Invalid event name" );
175 selectionChanged(getSelectedItem());
179 virtual uno::Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedMethodNames( ) throw (uno::RuntimeException
)
181 uno::Sequence
< ::rtl::OUString
> aMethods(1);
182 aMethods
[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SelectionChanged" ));
186 #if 0 // code currently unused (see below)
187 sal_Int32
queryDocumentTypeDialog( const uno::Reference
<uno::XComponentContext
>& xContext
,
188 const rtl::OUString
& rFilename
)
190 uno::Reference
<awt::XDialogProvider2
> xDialogProvider(
191 xContext
->getServiceManager()->createInstanceWithContext(
192 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DialogProvider2" ) ),
194 uno::UNO_QUERY_THROW
);
195 rtl::Reference
<ChooserDialogHandler
> xHandler(new ChooserDialogHandler
);
196 uno::Reference
<awt::XDialog
> xDialog
= xDialogProvider
->createDialogWithHandler(
197 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.script:PDFImport.TargetChooser?location=application") ),
198 uno::Reference
<awt::XDialogEventHandler
>(
199 static_cast<cppu::OWeakObject
*>(xHandler
.get()), uno::UNO_QUERY_THROW
));
200 xHandler
->initControls(
201 uno::Reference
<awt::XControlContainer
>(
203 uno::UNO_QUERY_THROW
),
206 if( !xDialog
->execute() )
209 return xHandler
->getSelectedItem();
214 class FileEmitContext
: public pdfparse::EmitContext
217 oslFileHandle m_aReadHandle
;
218 unsigned int m_nReadLen
;
219 uno::Reference
< io::XStream
> m_xContextStream
;
220 uno::Reference
< io::XSeekable
> m_xSeek
;
221 uno::Reference
< io::XOutputStream
> m_xOut
;
224 FileEmitContext( const rtl::OUString
& rOrigFile
,
225 const uno::Reference
< uno::XComponentContext
>& xContext
,
226 const pdfparse::PDFContainer
* pTop
);
227 virtual ~FileEmitContext();
229 virtual bool write( const void* pBuf
, unsigned int nLen
);
230 virtual unsigned int getCurPos();
231 virtual bool copyOrigBytes( unsigned int nOrigOffset
, unsigned int nLen
);
232 virtual unsigned int readOrigBytes( unsigned int nOrigOffset
, unsigned int nLen
, void* pBuf
);
234 const uno::Reference
< io::XStream
>& getContextStream() const { return m_xContextStream
; }
237 FileEmitContext::FileEmitContext( const rtl::OUString
& rOrigFile
,
238 const uno::Reference
< uno::XComponentContext
>& xContext
,
239 const pdfparse::PDFContainer
* pTop
) :
240 pdfparse::EmitContext( pTop
),
247 m_xContextStream
= uno::Reference
< io::XStream
>(
248 xContext
->getServiceManager()->createInstanceWithContext(
249 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ),
250 xContext
), uno::UNO_QUERY_THROW
);
251 m_xOut
= m_xContextStream
->getOutputStream();
252 m_xSeek
= uno::Reference
<io::XSeekable
>(m_xOut
, uno::UNO_QUERY_THROW
);
254 oslFileError aErr
= osl_File_E_None
;
255 if( (aErr
=osl_openFile( rOrigFile
.pData
,
257 osl_File_OpenFlag_Read
)) == osl_File_E_None
)
259 if( (aErr
=osl_setFilePos( m_aReadHandle
,
261 0 )) == osl_File_E_None
)
263 sal_uInt64 nFileSize
= 0;
264 if( (aErr
=osl_getFilePos( m_aReadHandle
,
265 &nFileSize
)) == osl_File_E_None
)
267 m_nReadLen
= static_cast<unsigned int>(nFileSize
);
270 if( aErr
!= osl_File_E_None
)
272 osl_closeFile( m_aReadHandle
);
273 m_aReadHandle
= NULL
;
279 FileEmitContext::~FileEmitContext()
282 osl_closeFile( m_aReadHandle
);
285 bool FileEmitContext::write( const void* pBuf
, unsigned int nLen
)
290 uno::Sequence
< sal_Int8
> aSeq( nLen
);
291 rtl_copyMemory( aSeq
.getArray(), pBuf
, nLen
);
292 m_xOut
->writeBytes( aSeq
);
296 unsigned int FileEmitContext::getCurPos()
298 unsigned int nPos
= 0;
301 nPos
= static_cast<unsigned int>( m_xSeek
->getPosition() );
306 bool FileEmitContext::copyOrigBytes( unsigned int nOrigOffset
, unsigned int nLen
)
308 if( nOrigOffset
+ nLen
> m_nReadLen
)
311 if( osl_setFilePos( m_aReadHandle
, osl_Pos_Absolut
, nOrigOffset
) != osl_File_E_None
)
314 uno::Sequence
< sal_Int8
> aSeq( nLen
);
316 sal_uInt64 nBytesRead
= 0;
317 if( osl_readFile( m_aReadHandle
,
320 &nBytesRead
) != osl_File_E_None
321 || nBytesRead
!= static_cast<sal_uInt64
>(nLen
) )
326 m_xOut
->writeBytes( aSeq
);
330 unsigned int FileEmitContext::readOrigBytes( unsigned int nOrigOffset
, unsigned int nLen
, void* pBuf
)
332 if( nOrigOffset
+ nLen
> m_nReadLen
)
335 if( osl_setFilePos( m_aReadHandle
,
337 nOrigOffset
) != osl_File_E_None
)
342 sal_uInt64 nBytesRead
= 0;
343 if( osl_readFile( m_aReadHandle
,
346 &nBytesRead
) != osl_File_E_None
)
350 return static_cast<unsigned int>(nBytesRead
);
354 ////////////////////////////////////////////////////////////////////////////////
357 PDFDetector::PDFDetector( const uno::Reference
< uno::XComponentContext
>& xContext
) :
358 PDFDetectorBase( m_aMutex
),
359 m_xContext( xContext
)
362 // XExtendedFilterDetection
363 rtl::OUString SAL_CALL
PDFDetector::detect( uno::Sequence
< beans::PropertyValue
>& rFilterData
) throw( uno::RuntimeException
)
365 osl::MutexGuard
const guard( m_aMutex
);
366 bool bSuccess
= false;
368 // get the InputStream carrying the PDF content
369 uno::Reference
< io::XInputStream
> xInput
;
370 uno::Reference
< io::XStream
> xEmbedStream
;
371 rtl::OUString aOutFilterName
, aOutTypeName
;
374 const beans::PropertyValue
* pAttribs
= rFilterData
.getConstArray();
375 sal_Int32 nAttribs
= rFilterData
.getLength();
376 sal_Int32 nFilterNamePos
= -1;
377 sal_Int32 nPwdPos
= -1;
378 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
380 #if OSL_DEBUG_LEVEL > 1
381 rtl::OUString
aVal( RTL_CONSTASCII_USTRINGPARAM( "<no string>" ) );
382 pAttribs
[i
].Value
>>= aVal
;
383 OSL_TRACE( "doDetection: Attrib: %s = %s\n",
384 rtl::OUStringToOString( pAttribs
[i
].Name
, RTL_TEXTENCODING_UTF8
).getStr(),
385 rtl::OUStringToOString( aVal
, RTL_TEXTENCODING_UTF8
).getStr() );
387 if( pAttribs
[i
].Name
.equalsAscii( "InputStream" ) )
388 pAttribs
[i
].Value
>>= xInput
;
389 else if( pAttribs
[i
].Name
.equalsAscii( "URL" ) )
390 pAttribs
[i
].Value
>>= aURL
;
391 else if( pAttribs
[i
].Name
.equalsAscii( "FilterName" ) )
393 else if( pAttribs
[i
].Name
.equalsAscii( "Password" ) )
396 pAttribs
[i
].Value
>>= aPwd
;
401 uno::Reference
< io::XSeekable
> xSeek( xInput
, uno::UNO_QUERY
);
404 // read the first 1024 byte (see PDF reference implementation note 12)
405 const sal_Int32 nHeaderSize
= 1024;
406 uno::Sequence
< sal_Int8
> aBuf( nHeaderSize
);
407 sal_uInt64 nBytes
= 0;
408 nBytes
= xInput
->readBytes( aBuf
, nHeaderSize
);
411 const sal_Int8
* pBytes
= aBuf
.getConstArray();
412 for( unsigned int i
= 0; i
< nBytes
-5; i
++ )
414 if( pBytes
[i
] == '%' &&
415 pBytes
[i
+1] == 'P' &&
416 pBytes
[i
+2] == 'D' &&
417 pBytes
[i
+3] == 'F' &&
426 // check for hybrid PDF
427 oslFileHandle aFile
= NULL
;
429 ( aURL
.getLength() == 0 || aURL
.compareToAscii( "file:", 5 ) != 0 )
432 sal_uInt64 nWritten
= 0;
433 if( osl_createTempFile( NULL
, &aFile
, &aURL
.pData
) != osl_File_E_None
)
439 #if OSL_DEBUG_LEVEL > 1
440 OSL_TRACE( "created temp file %s\n",
441 rtl::OUStringToOString( aURL
, RTL_TEXTENCODING_UTF8
).getStr() );
443 osl_writeFile( aFile
, aBuf
.getConstArray(), nBytes
, &nWritten
);
445 OSL_ENSURE( nWritten
== nBytes
, "writing of header bytes failed" );
447 if( nWritten
== nBytes
)
449 const sal_uInt32 nBufSize
= 4096;
450 aBuf
= uno::Sequence
<sal_Int8
>(nBufSize
);
454 nBytes
= xInput
->readBytes( aBuf
, nBufSize
);
457 osl_writeFile( aFile
, aBuf
.getConstArray(), nBytes
, &nWritten
);
458 if( nWritten
!= nBytes
)
464 } while( nBytes
== nBufSize
);
467 osl_closeFile( aFile
);
469 rtl::OUString aEmbedMimetype
;
470 xEmbedStream
= getAdditionalStream( aURL
, aEmbedMimetype
, aPwd
, m_xContext
, rFilterData
, false );
472 osl_removeFile( aURL
.pData
);
473 if( aEmbedMimetype
.getLength() )
475 if( aEmbedMimetype
.equalsAscii( "application/vnd.oasis.opendocument.text" )
476 || aEmbedMimetype
.equalsAscii( "application/vnd.oasis.opendocument.text-master" ) )
477 aOutFilterName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer_pdf_addstream_import" ) );
478 else if( aEmbedMimetype
.equalsAscii( "application/vnd.oasis.opendocument.presentation" ) )
479 aOutFilterName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress_pdf_addstream_import" ) );
480 else if( aEmbedMimetype
.equalsAscii( "application/vnd.oasis.opendocument.graphics" )
481 || aEmbedMimetype
.equalsAscii( "application/vnd.oasis.opendocument.drawing" ) )
482 aOutFilterName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw_pdf_addstream_import" ) );
483 else if( aEmbedMimetype
.equalsAscii( "application/vnd.oasis.opendocument.spreadsheet" ) )
484 aOutFilterName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc_pdf_addstream_import" ) );
490 if( aOutFilterName
.getLength() )
492 if( nFilterNamePos
== -1 )
494 nFilterNamePos
= nAttribs
;
495 rFilterData
.realloc( ++nAttribs
);
496 rFilterData
[ nFilterNamePos
].Name
=
497 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
499 aOutTypeName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("pdf_Portable_Document_Format") );
501 OSL_TRACE( "setting filter name %s, input stream %s\n",
502 rtl::OUStringToOString( aOutFilterName
, RTL_TEXTENCODING_UTF8
).getStr(),
503 xEmbedStream
.is() ? "present" : "not present" );
505 rFilterData
[nFilterNamePos
].Value
<<= aOutFilterName
;
506 if( xEmbedStream
.is() )
508 rFilterData
.realloc( ++nAttribs
);
509 rFilterData
[nAttribs
-1].Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EmbeddedSubstream" ) );
510 rFilterData
[nAttribs
-1].Value
<<= xEmbedStream
;
512 if( aPwd
.getLength() )
517 rFilterData
.realloc( ++nAttribs
);
518 rFilterData
[ nPwdPos
].Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Password" ) );
520 rFilterData
[ nPwdPos
].Value
<<= aPwd
;
525 if( nFilterNamePos
== -1 )
527 nFilterNamePos
= nAttribs
;
528 rFilterData
.realloc( ++nAttribs
);
529 rFilterData
[ nFilterNamePos
].Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
532 const sal_Int32 nDocumentType
= 0; //const sal_Int32 nDocumentType = queryDocumentTypeDialog(m_xContext,aURL);
533 if( nDocumentType
< 0 )
535 return rtl::OUString();
537 else switch( nDocumentType
)
540 rFilterData
[nFilterNamePos
].Value
<<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw_pdf_import" ) );
544 rFilterData
[nFilterNamePos
].Value
<<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress_pdf_import" ) );
548 rFilterData
[nFilterNamePos
].Value
<<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer_pdf_import" ) );
552 OSL_ENSURE(false,"Unexpected case");
555 aOutTypeName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("pdf_Portable_Document_Format") );
562 bool checkDocChecksum( const rtl::OUString
& rInPDFFileURL
,
564 const rtl::OUString
& rChkSum
)
567 if( rChkSum
.getLength() != 2* RTL_DIGEST_LENGTH_MD5
)
569 OSL_TRACE( "checksum of length %d, expected %d\n",
570 rChkSum
.getLength(), 2*RTL_DIGEST_LENGTH_MD5
);
574 // prepare checksum to test
575 sal_uInt8 nTestChecksum
[ RTL_DIGEST_LENGTH_MD5
];
576 const sal_Unicode
* pChar
= rChkSum
.getStr();
577 for( unsigned int i
= 0; i
< RTL_DIGEST_LENGTH_MD5
; i
++ )
579 sal_uInt8 nByte
= sal_uInt8( ( (*pChar
>= '0' && *pChar
<= '9') ? *pChar
- '0' :
580 ( (*pChar
>= 'A' && *pChar
<= 'F') ? *pChar
- 'A' + 10 :
581 ( (*pChar
>= 'a' && *pChar
<= 'f') ? *pChar
- 'a' + 10 :
585 nByte
|= ( (*pChar
>= '0' && *pChar
<= '9') ? *pChar
- '0' :
586 ( (*pChar
>= 'A' && *pChar
<= 'F') ? *pChar
- 'A' + 10 :
587 ( (*pChar
>= 'a' && *pChar
<= 'f') ? *pChar
- 'a' + 10 :
590 nTestChecksum
[i
] = nByte
;
593 // open file and calculate actual checksum up to index nBytes
594 sal_uInt8 nActualChecksum
[ RTL_DIGEST_LENGTH_MD5
];
595 rtl_zeroMemory( nActualChecksum
, sizeof(nActualChecksum
) );
596 rtlDigest aActualDigest
= rtl_digest_createMD5();
597 oslFileHandle aRead
= NULL
;
598 oslFileError aErr
= osl_File_E_None
;
599 if( (aErr
= osl_openFile(rInPDFFileURL
.pData
,
601 osl_File_OpenFlag_Read
)) == osl_File_E_None
)
605 sal_uInt64 nBytesRead
= 0;
606 while( nCur
< nBytes
)
608 sal_uInt32 nPass
= (nBytes
- nCur
) > sizeof( aBuf
) ? sizeof( aBuf
) : nBytes
- nCur
;
609 if( (aErr
= osl_readFile( aRead
, aBuf
, nPass
, &nBytesRead
)) != osl_File_E_None
614 nPass
= static_cast<sal_uInt32
>(nBytesRead
);
616 rtl_digest_updateMD5( aActualDigest
, aBuf
, nPass
);
618 rtl_digest_getMD5( aActualDigest
, nActualChecksum
, sizeof(nActualChecksum
) );
619 osl_closeFile( aRead
);
621 rtl_digest_destroyMD5( aActualDigest
);
623 // compare the contents
624 bRet
= (0 == rtl_compareMemory( nActualChecksum
, nTestChecksum
, sizeof( nActualChecksum
) ));
625 #if OSL_DEBUG_LEVEL > 1
626 OSL_TRACE( "test checksum: " );
627 for( unsigned int i
= 0; i
< sizeof(nTestChecksum
); i
++ )
628 OSL_TRACE( "%.2X", int(nTestChecksum
[i
]) );
630 OSL_TRACE( "file checksum: " );
631 for( unsigned int i
= 0; i
< sizeof(nActualChecksum
); i
++ )
632 OSL_TRACE( "%.2X", int(nActualChecksum
[i
]) );
638 uno::Reference
< io::XStream
> getAdditionalStream( const rtl::OUString
& rInPDFFileURL
,
639 rtl::OUString
& rOutMimetype
,
640 rtl::OUString
& io_rPwd
,
641 const uno::Reference
<uno::XComponentContext
>& xContext
,
642 const uno::Sequence
<beans::PropertyValue
>& rFilterData
,
645 uno::Reference
< io::XStream
> xEmbed
;
646 rtl::OString aPDFFile
;
647 rtl::OUString aSysUPath
;
648 if( osl_getSystemPathFromFileURL( rInPDFFileURL
.pData
, &aSysUPath
.pData
) != osl_File_E_None
)
650 aPDFFile
= rtl::OUStringToOString( aSysUPath
, osl_getThreadTextEncoding() );
652 pdfparse::PDFReader aParser
;
653 boost::scoped_ptr
<pdfparse::PDFEntry
> pEntry( aParser
.read( aPDFFile
.getStr() ));
656 pdfparse::PDFFile
* pPDFFile
= dynamic_cast<pdfparse::PDFFile
*>(pEntry
.get());
659 unsigned int nElements
= pPDFFile
->m_aSubElements
.size();
660 while( nElements
-- > 0 )
662 pdfparse::PDFTrailer
* pTrailer
= dynamic_cast<pdfparse::PDFTrailer
*>(pPDFFile
->m_aSubElements
[nElements
]);
663 if( pTrailer
&& pTrailer
->m_pDict
)
665 // search document checksum entry
666 std::hash_map
< rtl::OString
,
668 rtl::OStringHash
>::iterator chk
;
669 chk
= pTrailer
->m_pDict
->m_aMap
.find( "DocChecksum" );
670 if( chk
== pTrailer
->m_pDict
->m_aMap
.end() )
672 OSL_TRACE( "no DocChecksum entry\n" );
675 pdfparse::PDFName
* pChkSumName
= dynamic_cast<pdfparse::PDFName
*>(chk
->second
);
676 if( pChkSumName
== NULL
)
678 OSL_TRACE( "no name for DocChecksum entry\n" );
682 // search for AdditionalStreams entry
683 std::hash_map
< rtl::OString
,
685 rtl::OStringHash
>::iterator add_stream
;
686 add_stream
= pTrailer
->m_pDict
->m_aMap
.find( "AdditionalStreams" );
687 if( add_stream
== pTrailer
->m_pDict
->m_aMap
.end() )
689 OSL_TRACE( "no AdditionalStreams entry\n" );
692 pdfparse::PDFArray
* pStreams
= dynamic_cast<pdfparse::PDFArray
*>(add_stream
->second
);
693 if( ! pStreams
|| pStreams
->m_aSubElements
.size() < 2 )
695 OSL_TRACE( "AdditionalStreams array too small\n" );
700 rtl::OUString aChkSum
= pChkSumName
->getFilteredName();
701 if( ! checkDocChecksum( rInPDFFileURL
, pTrailer
->m_nOffset
, aChkSum
) )
704 // extract addstream and mimetype
705 pdfparse::PDFName
* pMimeType
= dynamic_cast<pdfparse::PDFName
*>(pStreams
->m_aSubElements
[0]);
706 pdfparse::PDFObjectRef
* pStreamRef
= dynamic_cast<pdfparse::PDFObjectRef
*>(pStreams
->m_aSubElements
[1]);
708 OSL_ENSURE( pMimeType
, "error: no mimetype element\n" );
709 OSL_ENSURE( pStreamRef
, "error: no stream ref element\n" );
711 if( pMimeType
&& pStreamRef
)
713 pdfparse::PDFObject
* pObject
= pPDFFile
->findObject( pStreamRef
->m_nNumber
, pStreamRef
->m_nGeneration
);
714 OSL_ENSURE( pObject
, "object not found\n" );
717 if( pPDFFile
->isEncrypted() )
719 bool bAuthenticated
= false;
720 if( io_rPwd
.getLength() )
722 rtl::OString aIsoPwd
= rtl::OUStringToOString( io_rPwd
,
723 RTL_TEXTENCODING_ISO_8859_1
);
724 bAuthenticated
= pPDFFile
->setupDecryptionData( aIsoPwd
.getStr() );
726 if( ! bAuthenticated
)
728 const beans::PropertyValue
* pAttribs
= rFilterData
.getConstArray();
729 sal_Int32 nAttribs
= rFilterData
.getLength();
730 uno::Reference
< task::XInteractionHandler
> xIntHdl
;
731 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
733 if( pAttribs
[i
].Name
.equalsAscii( "InteractionHandler" ) )
734 pAttribs
[i
].Value
>>= xIntHdl
;
736 if( ! bMayUseUI
|| ! xIntHdl
.is() )
738 rOutMimetype
= pMimeType
->getFilteredName();
743 bool bEntered
= false;
746 bEntered
= getPassword( xIntHdl
, io_rPwd
, ! bEntered
);
747 rtl::OString aIsoPwd
= rtl::OUStringToOString( io_rPwd
,
748 RTL_TEXTENCODING_ISO_8859_1
);
749 bAuthenticated
= pPDFFile
->setupDecryptionData( aIsoPwd
.getStr() );
750 } while( bEntered
&& ! bAuthenticated
);
753 OSL_TRACE( "password: %s\n", bAuthenticated
? "matches" : "does not match" );
754 if( ! bAuthenticated
)
757 rOutMimetype
= pMimeType
->getFilteredName();
758 FileEmitContext
aContext( rInPDFFileURL
,
761 aContext
.m_bDecrypt
= pPDFFile
->isEncrypted();
762 pObject
->writeStream( aContext
, pPDFFile
);
763 xEmbed
= aContext
.getContextStream();
772 OSL_TRACE( "extracted add stream: mimetype %s\n",
773 rtl::OUStringToOString( rOutMimetype
,
774 RTL_TEXTENCODING_UTF8
).getStr());