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: wrapper.cxx,v $
11 * $Revision: 1.2.4.1 $
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 "contentsink.hxx"
36 #include "pdfparse.hxx"
37 #include "pdfihelper.hxx"
40 #include "osl/thread.h"
41 #include "osl/process.h"
42 #include "osl/diagnose.h"
43 #include "rtl/ustring.hxx"
44 #include "rtl/ustrbuf.hxx"
45 #include "rtl/strbuf.hxx"
46 #include "rtl/byteseq.hxx"
48 #include "cppuhelper/exc_hlp.hxx"
49 #include "com/sun/star/io/XInputStream.hpp"
50 #include "com/sun/star/uno/XComponentContext.hpp"
51 #include "com/sun/star/awt/FontDescriptor.hpp"
52 #include "com/sun/star/deployment/XPackageInformationProvider.hpp"
53 #include "com/sun/star/beans/XMaterialHolder.hpp"
54 #include "com/sun/star/rendering/PathCapType.hpp"
55 #include "com/sun/star/rendering/PathJoinType.hpp"
56 #include "com/sun/star/rendering/XColorSpace.hpp"
57 #include "com/sun/star/rendering/XPolyPolygon2D.hpp"
58 #include "com/sun/star/rendering/XBitmap.hpp"
59 #include "com/sun/star/geometry/Matrix2D.hpp"
60 #include "com/sun/star/geometry/AffineMatrix2D.hpp"
61 #include "com/sun/star/geometry/RealRectangle2D.hpp"
62 #include "com/sun/star/task/XInteractionHandler.hpp"
64 #include "basegfx/point/b2dpoint.hxx"
65 #include "basegfx/polygon/b2dpolypolygon.hxx"
66 #include "basegfx/polygon/b2dpolygon.hxx"
67 #include "basegfx/tools/canvastools.hxx"
68 #include "basegfx/tools/unopolypolygon.hxx"
70 #include <boost/bind.hpp>
71 #include <boost/preprocessor/stringize.hpp>
72 #include <boost/scoped_ptr.hpp>
73 #include <boost/scoped_array.hpp>
78 #include "rtl/bootstrap.h"
80 #include <string.h> // memcmp
82 #ifndef PDFI_IMPL_IDENTIFIER
83 # error define implementation name for pdfi extension, please!
86 using namespace com::sun::star
;
94 // identifier of the strings coming from the out-of-process xpdf
150 typedef std::hash_map
< sal_Int64
,
151 FontAttributes
> FontMapType
;
153 const uno::Reference
<uno::XComponentContext
> m_xContext
;
154 const ContentSinkSharedPtr m_pSink
;
155 const oslFileHandle m_pErr
;
156 ::rtl::OString m_aLine
;
157 FontMapType m_aFontMap
;
158 sal_Int32 m_nNextToken
;
159 sal_Int32 m_nCharIndex
;
162 ::rtl::OString
readNextToken();
163 void readInt32( sal_Int32
& o_Value
);
164 sal_Int32
readInt32();
165 void readInt64( sal_Int64
& o_Value
);
166 void readDouble( double& o_Value
);
168 void readBinaryData( uno::Sequence
<sal_Int8
>& rBuf
);
170 uno::Reference
<rendering::XPolyPolygon2D
> readPath();
176 void readTransformation();
177 rendering::ARGBColor
readColor();
178 void parseFontFamilyName( FontAttributes
& aResult
);
180 uno::Sequence
<beans::PropertyValue
> readImageImpl();
185 void readMaskedImage();
186 void readSoftMaskedImage();
189 Parser( const ContentSinkSharedPtr
& rSink
,
191 const uno::Reference
<uno::XComponentContext
>& xContext
) :
192 m_xContext(xContext
),
201 void parseLine( const ::rtl::OString
& rLine
);
204 ::rtl::OString
Parser::readNextToken()
206 OSL_PRECOND(m_nCharIndex
!=-1,"insufficient input");
207 return m_aLine
.getToken(m_nNextToken
,' ',m_nCharIndex
);
210 void Parser::readInt32( sal_Int32
& o_Value
)
212 o_Value
= readNextToken().toInt32();
215 sal_Int32
Parser::readInt32()
217 return readNextToken().toInt32();
220 void Parser::readInt64( sal_Int64
& o_Value
)
222 o_Value
= readNextToken().toInt64();
225 void Parser::readDouble( double& o_Value
)
227 o_Value
= readNextToken().toDouble();
230 double Parser::readDouble()
232 return readNextToken().toDouble();
235 void Parser::readBinaryData( uno::Sequence
<sal_Int8
>& rBuf
)
237 sal_Int32
nFileLen( rBuf
.getLength() );
238 sal_Int8
* pBuf( rBuf
.getArray() );
239 sal_uInt64
nBytesRead(0);
240 oslFileError nRes
=osl_File_E_None
;
242 osl_File_E_None
== (nRes
=osl_readFile( m_pErr
, pBuf
, nFileLen
, &nBytesRead
)) )
245 nFileLen
-= sal::static_int_cast
<sal_Int32
>(nBytesRead
);
248 OSL_PRECOND(nRes
==osl_File_E_None
, "inconsistent data");
251 uno::Reference
<rendering::XPolyPolygon2D
> Parser::readPath()
253 const rtl::OString
aSubPathMarker( "subpath" );
255 if( 0 != readNextToken().compareTo( aSubPathMarker
) )
256 OSL_PRECOND(false, "broken path");
258 basegfx::B2DPolyPolygon aResult
;
259 while( m_nCharIndex
!= -1 )
261 basegfx::B2DPolygon aSubPath
;
263 sal_Int32 nClosedFlag
;
264 readInt32( nClosedFlag
);
265 aSubPath
.setClosed( nClosedFlag
!= 0 );
267 sal_Int32
nContiguousControlPoints(0);
268 sal_Int32 nDummy
=m_nCharIndex
;
269 rtl::OString
aCurrToken( m_aLine
.getToken(m_nNextToken
,' ',nDummy
) );
271 while( m_nCharIndex
!= -1 && 0 != aCurrToken
.compareTo(aSubPathMarker
) )
273 sal_Int32 nCurveFlag
;
277 readInt32( nCurveFlag
);
279 aSubPath
.append(basegfx::B2DPoint(nX
,nY
));
282 ++nContiguousControlPoints
;
284 else if( nContiguousControlPoints
)
286 OSL_PRECOND(nContiguousControlPoints
==2,"broken bezier path");
288 // have two control points before us. the current one
289 // is a normal point - thus, convert previous points
290 // into bezier segment
291 const sal_uInt32
nPoints( aSubPath
.count() );
292 const basegfx::B2DPoint
aCtrlA( aSubPath
.getB2DPoint(nPoints
-3) );
293 const basegfx::B2DPoint
aCtrlB( aSubPath
.getB2DPoint(nPoints
-2) );
294 const basegfx::B2DPoint
aEnd( aSubPath
.getB2DPoint(nPoints
-1) );
295 aSubPath
.remove(nPoints
-3, 3);
296 aSubPath
.appendBezierSegment(aCtrlA
, aCtrlB
, aEnd
);
298 nContiguousControlPoints
=0;
301 // one token look-ahead (new subpath or more points?
303 aCurrToken
= m_aLine
.getToken(m_nNextToken
,' ',nDummy
);
306 aResult
.append( aSubPath
);
307 if( m_nCharIndex
!= -1 )
311 return static_cast<rendering::XLinePolyPolygon2D
*>(
312 new basegfx::unotools::UnoPolyPolygon(aResult
));
315 void Parser::readChar()
317 geometry::Matrix2D aUnoMatrix
;
318 geometry::RealRectangle2D aRect
;
320 readDouble(aRect
.X1
);
321 readDouble(aRect
.Y1
);
322 readDouble(aRect
.X2
);
323 readDouble(aRect
.Y2
);
324 readDouble(aUnoMatrix
.m00
);
325 readDouble(aUnoMatrix
.m01
);
326 readDouble(aUnoMatrix
.m10
);
327 readDouble(aUnoMatrix
.m11
);
329 rtl::OString aChars
= m_aLine
.copy( m_nCharIndex
);
331 // chars gobble up rest of line
334 m_pSink
->drawGlyphs( rtl::OStringToOUString( aChars
,
335 RTL_TEXTENCODING_UTF8
),
339 void Parser::readLineCap()
341 sal_Int8
nCap(rendering::PathCapType::BUTT
);
342 switch( readInt32() )
345 // FALLTHROUGH intended
346 case 0: nCap
= rendering::PathCapType::BUTT
; break;
347 case 1: nCap
= rendering::PathCapType::ROUND
; break;
348 case 2: nCap
= rendering::PathCapType::SQUARE
; break;
350 m_pSink
->setLineCap(nCap
);
353 void Parser::readLineDash()
355 if( m_nCharIndex
== -1 )
357 m_pSink
->setLineDash( uno::Sequence
<double>(), 0.0 );
361 const double nOffset(readDouble());
362 const sal_Int32
nLen(readInt32());
364 uno::Sequence
<double> aDashArray(nLen
);
365 double* pArray
=aDashArray
.getArray();
366 for( sal_Int32 i
=0; i
<nLen
; ++i
)
367 *pArray
++ = readDouble();
369 m_pSink
->setLineDash( aDashArray
, nOffset
);
372 void Parser::readLineJoin()
374 sal_Int8
nJoin(rendering::PathJoinType::MITER
);
375 switch( readInt32() )
378 // FALLTHROUGH intended
379 case 0: nJoin
= rendering::PathJoinType::MITER
; break;
380 case 1: nJoin
= rendering::PathJoinType::ROUND
; break;
381 case 2: nJoin
= rendering::PathJoinType::BEVEL
; break;
383 m_pSink
->setLineJoin(nJoin
);
386 void Parser::readTransformation()
388 geometry::AffineMatrix2D aMat
;
389 readDouble(aMat
.m00
);
390 readDouble(aMat
.m10
);
391 readDouble(aMat
.m01
);
392 readDouble(aMat
.m11
);
393 readDouble(aMat
.m02
);
394 readDouble(aMat
.m12
);
395 m_pSink
->setTransformation( aMat
);
398 rendering::ARGBColor
Parser::readColor()
400 rendering::ARGBColor aRes
;
401 readDouble(aRes
.Red
);
402 readDouble(aRes
.Green
);
403 readDouble(aRes
.Blue
);
404 readDouble(aRes
.Alpha
);
408 void Parser::parseFontFamilyName( FontAttributes
& aResult
)
410 rtl::OUStringBuffer
aNewFamilyName( aResult
.familyName
.getLength() );
412 const sal_Unicode
* pCopy
= aResult
.familyName
.getStr();
413 sal_Int32 nLen
= aResult
.familyName
.getLength();
414 // parse out truetype subsets (e.g. BAAAAA+Thorndale)
415 if( nLen
> 8 && pCopy
[6] == sal_Unicode('+') )
424 ( *pCopy
== 'i' || *pCopy
== 'I' ) &&
431 aResult
.isItalic
= true;
436 ( *pCopy
== 'B' || *pCopy
== 'b' ) &&
441 aResult
.isBold
= true;
447 ( pCopy
[1] == 'R' || pCopy
[1] == 'r' ) &&
459 aNewFamilyName
.append( *pCopy
);
464 aResult
.familyName
= aNewFamilyName
.makeStringAndClear();
467 void Parser::readFont()
469 ::rtl::OString aFontName
;
471 sal_Int32 nIsEmbedded
, nIsBold
, nIsItalic
, nIsUnderline
, nFileLen
;
475 readInt32(nIsEmbedded
);
477 readInt32(nIsItalic
);
478 readInt32(nIsUnderline
);
482 nSize
= nSize
< 0.0 ? -nSize
: nSize
;
483 aFontName
= m_aLine
.copy( m_nCharIndex
);
485 // name gobbles up rest of line
488 FontMapType::const_iterator
pFont( m_aFontMap
.find(nFontID
) );
489 if( pFont
!= m_aFontMap
.end() )
491 OSL_PRECOND(nFileLen
==0,"font data for known font");
492 FontAttributes
aRes(pFont
->second
);
494 m_pSink
->setFont( aRes
);
499 // yet unknown font - get info and add to map
500 FontAttributes
aResult( rtl::OStringToOUString( aFontName
,
501 RTL_TEXTENCODING_UTF8
),
508 // extract textual attributes (bold, italic in the name, etc.)
509 parseFontFamilyName(aResult
);
511 // need to read font file?
514 uno::Sequence
<sal_Int8
> aFontFile(nFileLen
);
515 readBinaryData( aFontFile
);
517 awt::FontDescriptor aFD
;
518 uno::Sequence
< uno::Any
> aArgs(1);
519 aArgs
[0] <<= aFontFile
;
523 uno::Reference
< beans::XMaterialHolder
> xMat(
524 m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
525 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.FontIdentificator" ) ),
531 uno::Any
aRes( xMat
->getMaterial() );
534 aResult
.familyName
= aFD
.Name
;
535 aResult
.isBold
= (aFD
.Weight
> 100.0);
536 aResult
.isItalic
= (aFD
.Slant
== awt::FontSlant_OBLIQUE
||
537 aFD
.Slant
== awt::FontSlant_ITALIC
);
538 aResult
.isUnderline
= false;
543 catch( uno::Exception
& )
547 if( !aResult
.familyName
.getLength() )
550 aResult
.familyName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Arial" ) );
551 aResult
.isUnderline
= false;
556 m_aFontMap
[nFontID
] = aResult
;
558 aResult
.size
= nSize
;
559 m_pSink
->setFont(aResult
);
562 uno::Sequence
<beans::PropertyValue
> Parser::readImageImpl()
564 static const rtl::OString
aJpegMarker( "JPEG" );
565 static const rtl::OString
aPbmMarker( "PBM" );
566 static const rtl::OString
aPpmMarker( "PPM" );
567 static const rtl::OString
aPngMarker( "PNG" );
568 static const rtl::OUString
aJpegFile(
569 RTL_CONSTASCII_USTRINGPARAM( "DUMMY.JPEG" ));
570 static const rtl::OUString
aPbmFile(
571 RTL_CONSTASCII_USTRINGPARAM( "DUMMY.PBM" ));
572 static const rtl::OUString
aPpmFile(
573 RTL_CONSTASCII_USTRINGPARAM( "DUMMY.PPM" ));
574 static const rtl::OUString
aPngFile(
575 RTL_CONSTASCII_USTRINGPARAM( "DUMMY.PNG" ));
577 rtl::OString aToken
= readNextToken();
578 const sal_Int32
nImageSize( readInt32() );
580 rtl::OUString aFileName
;
581 if( aToken
.compareTo( aPngMarker
) == 0 )
582 aFileName
= aPngFile
;
583 else if( aToken
.compareTo( aJpegMarker
) == 0 )
584 aFileName
= aJpegFile
;
585 else if( aToken
.compareTo( aPbmMarker
) == 0 )
586 aFileName
= aPbmFile
;
589 OSL_PRECOND( aToken
.compareTo( aPpmMarker
) == 0,
590 "Invalid bitmap format" );
591 aFileName
= aPpmFile
;
594 uno::Sequence
<sal_Int8
> aDataSequence(nImageSize
);
595 readBinaryData( aDataSequence
);
597 uno::Sequence
< uno::Any
> aStreamCreationArgs(1);
598 aStreamCreationArgs
[0] <<= aDataSequence
;
600 uno::Reference
< uno::XComponentContext
> xContext( m_xContext
, uno::UNO_SET_THROW
);
601 uno::Reference
< lang::XMultiComponentFactory
> xFactory( xContext
->getServiceManager(), uno::UNO_SET_THROW
);
602 uno::Reference
< io::XInputStream
> xDataStream( xFactory
->createInstanceWithArgumentsAndContext(
603 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.SequenceInputStream" ) ),
604 aStreamCreationArgs
, m_xContext
), uno::UNO_QUERY_THROW
);
606 uno::Sequence
<beans::PropertyValue
> aSequence(3);
607 aSequence
[0] = beans::PropertyValue( ::rtl::OUString::createFromAscii("URL"),
609 uno::makeAny(aFileName
),
610 beans::PropertyState_DIRECT_VALUE
);
611 aSequence
[1] = beans::PropertyValue( ::rtl::OUString::createFromAscii("InputStream"),
613 uno::makeAny( xDataStream
),
614 beans::PropertyState_DIRECT_VALUE
);
615 aSequence
[2] = beans::PropertyValue( ::rtl::OUString::createFromAscii("InputSequence"),
617 uno::makeAny(aDataSequence
),
618 beans::PropertyState_DIRECT_VALUE
);
623 void Parser::readImage()
625 sal_Int32 nWidth
, nHeight
,nMaskColors
;
628 readInt32(nMaskColors
);
630 uno::Sequence
<beans::PropertyValue
> aImg( readImageImpl() );
634 uno::Sequence
<sal_Int8
> aDataSequence(nMaskColors
);
635 readBinaryData( aDataSequence
);
637 uno::Sequence
<uno::Any
> aMaskRanges(2);
639 uno::Sequence
<double> aMinRange(nMaskColors
/2);
640 uno::Sequence
<double> aMaxRange(nMaskColors
/2);
641 for( sal_Int32 i
=0; i
<nMaskColors
/2; ++i
)
643 aMinRange
[i
] = aDataSequence
[i
] / 255.0;
644 aMaxRange
[i
] = aDataSequence
[i
+nMaskColors
/2] / 255.0;
647 aMaskRanges
[0] = uno::makeAny(aMinRange
);
648 aMaskRanges
[1] = uno::makeAny(aMaxRange
);
650 m_pSink
->drawColorMaskedImage( aImg
, aMaskRanges
);
653 m_pSink
->drawImage( aImg
);
656 void Parser::readMask()
658 sal_Int32 nWidth
, nHeight
, nInvert
;
663 m_pSink
->drawMask( readImageImpl(), nInvert
);
666 void Parser::readLink()
668 geometry::RealRectangle2D aBounds
;
669 readDouble(aBounds
.X1
);
670 readDouble(aBounds
.Y1
);
671 readDouble(aBounds
.X2
);
672 readDouble(aBounds
.Y2
);
674 m_pSink
->hyperLink( aBounds
,
675 rtl::OStringToOUString( m_aLine
.copy(m_nCharIndex
),
676 RTL_TEXTENCODING_UTF8
));
677 // name gobbles up rest of line
681 void Parser::readMaskedImage()
683 sal_Int32 nWidth
, nHeight
, nMaskWidth
, nMaskHeight
, nMaskInvert
;
686 readInt32(nMaskWidth
);
687 readInt32(nMaskHeight
);
688 readInt32(nMaskInvert
);
690 const uno::Sequence
<beans::PropertyValue
> aImage( readImageImpl() );
691 const uno::Sequence
<beans::PropertyValue
> aMask ( readImageImpl() );
692 m_pSink
->drawMaskedImage( aImage
, aMask
, nMaskInvert
!= 0 );
695 void Parser::readSoftMaskedImage()
697 sal_Int32 nWidth
, nHeight
, nMaskWidth
, nMaskHeight
;
700 readInt32(nMaskWidth
);
701 readInt32(nMaskHeight
);
703 const uno::Sequence
<beans::PropertyValue
> aImage( readImageImpl() );
704 const uno::Sequence
<beans::PropertyValue
> aMask ( readImageImpl() );
705 m_pSink
->drawAlphaMaskedImage( aImage
, aMask
);
708 void Parser::parseLine( const ::rtl::OString
& rLine
)
710 OSL_PRECOND( m_pSink
, "Invalid sink" );
711 OSL_PRECOND( m_pErr
, "Invalid filehandle" );
712 OSL_PRECOND( m_xContext
.is(), "Invalid service factory" );
714 m_nNextToken
= 0; m_nCharIndex
= 0; m_aLine
= rLine
;
715 uno::Reference
<rendering::XPolyPolygon2D
> xPoly
;
716 const ::rtl::OString
& rCmd
= readNextToken();
717 const hash_entry
* pEntry
= PdfKeywordHash::in_word_set( rCmd
.getStr(),
720 switch( pEntry
->eKey
)
723 m_pSink
->intersectClip(readPath()); break;
732 case DRAWMASKEDIMAGE
:
733 readMaskedImage(); break;
734 case DRAWSOFTMASKEDIMAGE
:
735 readSoftMaskedImage(); break;
737 m_pSink
->endPage(); break;
739 m_pSink
->endText(); break;
741 m_pSink
->intersectEoClip(readPath()); break;
743 m_pSink
->eoFillPath(readPath()); break;
745 m_pSink
->fillPath(readPath()); break;
747 m_pSink
->popState(); break;
749 m_pSink
->pushState(); break;
751 m_pSink
->setPageNum( readInt32() ); break;
754 const double nWidth ( readDouble() );
755 const double nHeight( readDouble() );
756 m_pSink
->startPage( geometry::RealSize2D( nWidth
, nHeight
) );
760 m_pSink
->strokePath(readPath()); break;
762 readTransformation(); break;
763 case UPDATEFILLCOLOR
:
764 m_pSink
->setFillColor( readColor() ); break;
766 m_pSink
->setFlatness( readDouble( ) ); break;
770 readLineCap(); break;
772 readLineDash(); break;
774 readLineJoin(); break;
775 case UPDATELINEWIDTH
:
776 m_pSink
->setLineWidth( readDouble() );break;
777 case UPDATEMITERLIMIT
:
778 m_pSink
->setMiterLimit( readDouble() ); break;
779 case UPDATESTROKECOLOR
:
780 m_pSink
->setStrokeColor( readColor() ); break;
781 case UPDATESTROKEOPACITY
:
783 case SETTEXTRENDERMODE
:
784 m_pSink
->setTextRenderMode( readInt32() ); break;
788 OSL_PRECOND(false,"Unknown input");
793 OSL_POSTCOND(m_nCharIndex
==-1,"leftover scanner input");
796 oslFileError
readLine( oslFileHandle pFile
, ::rtl::OStringBuffer
& line
)
798 OSL_PRECOND( line
.getLength() == 0, "line buf not empty" );
800 // TODO(P3): read larger chunks
801 sal_Char
aChar('\n');
802 sal_uInt64 nBytesRead
;
805 // skip garbage \r \n at start of line
806 while( osl_File_E_None
== (nRes
=osl_readFile(pFile
, &aChar
, 1, &nBytesRead
)) &&
808 (aChar
== '\n' || aChar
== '\r') ) ;
810 if( aChar
!= '\n' && aChar
!= '\r' )
811 line
.append( aChar
);
813 while( osl_File_E_None
== (nRes
=osl_readFile(pFile
, &aChar
, 1, &nBytesRead
)) &&
814 nBytesRead
== 1 && aChar
!= '\n' && aChar
!= '\r' )
816 line
.append( aChar
);
824 static bool checkEncryption( const rtl::OUString
& i_rPath
,
825 const uno::Reference
< task::XInteractionHandler
>& i_xIHdl
,
826 rtl::OUString
& io_rPwd
,
830 bool bSuccess
= false;
831 rtl::OString aPDFFile
;
832 aPDFFile
= rtl::OUStringToOString( i_rPath
, osl_getThreadTextEncoding() );
834 pdfparse::PDFReader aParser
;
835 boost::scoped_ptr
<pdfparse::PDFEntry
> pEntry( aParser
.read( aPDFFile
.getStr() ));
838 pdfparse::PDFFile
* pPDFFile
= dynamic_cast<pdfparse::PDFFile
*>(pEntry
.get());
841 o_rIsEncrypted
= pPDFFile
->isEncrypted();
844 bool bAuthenticated
= false;
845 if( io_rPwd
.getLength() )
847 rtl::OString aIsoPwd
= rtl::OUStringToOString( io_rPwd
,
848 RTL_TEXTENCODING_ISO_8859_1
);
849 bAuthenticated
= pPDFFile
->setupDecryptionData( aIsoPwd
.getStr() );
857 bool bEntered
= false;
860 bEntered
= getPassword( i_xIHdl
, io_rPwd
, ! bEntered
);
861 rtl::OString aIsoPwd
= rtl::OUStringToOString( io_rPwd
,
862 RTL_TEXTENCODING_ISO_8859_1
);
863 bAuthenticated
= pPDFFile
->setupDecryptionData( aIsoPwd
.getStr() );
864 } while( bEntered
&& ! bAuthenticated
);
867 OSL_TRACE( "password: %s\n", bAuthenticated
? "matches" : "does not match" );
868 bSuccess
= bAuthenticated
;
878 bool xpdf_ImportFromFile( const ::rtl::OUString
& rURL
,
879 const ContentSinkSharedPtr
& rSink
,
880 const uno::Reference
< task::XInteractionHandler
>& xIHdl
,
881 const rtl::OUString
& rPwd
,
882 const uno::Reference
< uno::XComponentContext
>& xContext
)
886 ::rtl::OUString aSysUPath
;
887 if( osl_getSystemPathFromFileURL( rURL
.pData
, &aSysUPath
.pData
) != osl_File_E_None
)
890 // check for encryption, if necessary get password
891 rtl::OUString
aPwd( rPwd
);
892 bool bIsEncrypted
= false;
893 if( checkEncryption( aSysUPath
, xIHdl
, aPwd
, bIsEncrypted
) == false )
896 rtl::OUStringBuffer converterURL
= rtl::OUString::createFromAscii("xpdfimport");
898 // retrieve package location url (xpdfimport executable is located there)
899 // ---------------------------------------------------
900 uno::Reference
<deployment::XPackageInformationProvider
> xProvider(
901 xContext
->getValueByName(
902 rtl::OUString::createFromAscii("/singletons/com.sun.star.deployment.PackageInformationProvider" )),
908 rtl::OUString::createFromAscii("/"));
911 xProvider
->getPackageLocation(
912 rtl::OUString::createFromAscii(
913 BOOST_PP_STRINGIZE(PDFI_IMPL_IDENTIFIER
))));
916 // spawn separate process to keep LGPL/GPL code apart.
917 // ---------------------------------------------------
918 rtl_uString
** ppEnv
= NULL
;
921 #if defined UNX && ! defined MACOSX
922 rtl::OUString
aStr( RTL_CONSTASCII_USTRINGPARAM( "$URE_LIB_DIR" ) );
923 rtl_bootstrap_expandMacros( &aStr
.pData
);
924 rtl::OUString aSysPath
;
925 osl_getSystemPathFromFileURL( aStr
.pData
, &aSysPath
.pData
);
926 rtl::OUStringBuffer
aEnvBuf( aStr
.getLength() + 20 );
927 aEnvBuf
.appendAscii( "LD_LIBRARY_PATH=" );
928 aEnvBuf
.append( aSysPath
);
929 aStr
= aEnvBuf
.makeStringAndClear();
934 rtl_uString
* args
[] = { aSysUPath
.pData
};
938 oslFileHandle pIn
= NULL
;
939 oslFileHandle pOut
= NULL
;
940 oslFileHandle pErr
= NULL
;
941 const oslProcessError eErr
=
942 osl_executeProcess_WithRedirectedIO(converterURL
.makeStringAndClear().pData
,
945 osl_Process_SEARCHPATH
|osl_Process_HIDDEN
,
946 osl_getCurrentSecurity(),
948 &aProcess
, &pIn
, &pOut
, &pErr
);
953 if( eErr
!=osl_Process_E_None
)
958 rtl::OStringBuffer
aBuf(256);
960 aBuf
.append( rtl::OUStringToOString( aPwd
, RTL_TEXTENCODING_ISO_8859_1
) );
963 sal_uInt64 nWritten
= 0;
964 osl_writeFile( pIn
, aBuf
.getStr(), sal_uInt64(aBuf
.getLength()), &nWritten
);
969 // read results of PDF parser. One line - one call to
970 // OutputDev. stderr is used for alternate streams, like
971 // embedded fonts and bitmaps
972 Parser
aParser(rSink
,pErr
,xContext
);
973 ::rtl::OStringBuffer line
;
974 while( osl_File_E_None
== readLine(pOut
, line
) && line
.getLength() )
975 aParser
.parseLine(line
.makeStringAndClear());
978 catch( uno::Exception
& )
980 // crappy C file interface. need manual resource dealloc
990 osl_freeProcessHandle(aProcess
);
995 bool xpdf_ImportFromStream( const uno::Reference
< io::XInputStream
>& xInput
,
996 const ContentSinkSharedPtr
& rSink
,
997 const uno::Reference
<task::XInteractionHandler
>& xIHdl
,
998 const rtl::OUString
& rPwd
,
999 const uno::Reference
< uno::XComponentContext
>& xContext
)
1001 OSL_ASSERT(xInput
.is());
1004 // convert XInputStream to local temp file
1005 oslFileHandle aFile
= NULL
;
1007 if( osl_createTempFile( NULL
, &aFile
, &aURL
.pData
) != osl_File_E_None
)
1010 // copy content, buffered...
1011 const sal_uInt32 nBufSize
= 4096;
1012 uno::Sequence
<sal_Int8
> aBuf( nBufSize
);
1013 sal_uInt64 nBytes
= 0;
1014 sal_uInt64 nWritten
= 0;
1015 bool bSuccess
= true;
1020 nBytes
= xInput
->readBytes( aBuf
, nBufSize
);
1022 catch( com::sun::star::uno::Exception
& )
1024 osl_closeFile( aFile
);
1029 osl_writeFile( aFile
, aBuf
.getConstArray(), nBytes
, &nWritten
);
1030 if( nWritten
!= nBytes
)
1037 while( nBytes
== nBufSize
);
1039 osl_closeFile( aFile
);
1041 return bSuccess
&& xpdf_ImportFromFile( aURL
, rSink
, xIHdl
, rPwd
, xContext
);