LCOV - code coverage report
Current view: top level - libreoffice/sdext/source/pdfimport/wrapper - wrapper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 331 511 64.8 %
Date: 2012-12-27 Functions: 26 32 81.2 %
Legend: Lines: hit not hit

          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 "contentsink.hxx"
      22             : #include "pdfparse.hxx"
      23             : #include "pdfihelper.hxx"
      24             : 
      25             : #include "osl/file.h"
      26             : #include "osl/file.hxx"
      27             : #include "osl/thread.h"
      28             : #include "osl/process.h"
      29             : #include "osl/diagnose.h"
      30             : #include "rtl/bootstrap.hxx"
      31             : #include "rtl/ustring.hxx"
      32             : #include "rtl/ustrbuf.hxx"
      33             : #include "rtl/strbuf.hxx"
      34             : #include "rtl/byteseq.hxx"
      35             : 
      36             : #include "cppuhelper/exc_hlp.hxx"
      37             : #include "com/sun/star/io/XInputStream.hpp"
      38             : #include "com/sun/star/uno/XComponentContext.hpp"
      39             : #include "com/sun/star/awt/FontDescriptor.hpp"
      40             : #include "com/sun/star/beans/XMaterialHolder.hpp"
      41             : #include "com/sun/star/rendering/PathCapType.hpp"
      42             : #include "com/sun/star/rendering/PathJoinType.hpp"
      43             : #include "com/sun/star/rendering/XColorSpace.hpp"
      44             : #include "com/sun/star/rendering/XPolyPolygon2D.hpp"
      45             : #include "com/sun/star/rendering/XBitmap.hpp"
      46             : #include "com/sun/star/geometry/Matrix2D.hpp"
      47             : #include "com/sun/star/geometry/AffineMatrix2D.hpp"
      48             : #include "com/sun/star/geometry/RealRectangle2D.hpp"
      49             : #include "com/sun/star/task/XInteractionHandler.hpp"
      50             : 
      51             : #include "basegfx/point/b2dpoint.hxx"
      52             : #include "basegfx/polygon/b2dpolypolygon.hxx"
      53             : #include "basegfx/polygon/b2dpolygon.hxx"
      54             : #include "basegfx/tools/canvastools.hxx"
      55             : #include "basegfx/tools/unopolypolygon.hxx"
      56             : 
      57             : #include <boost/scoped_ptr.hpp>
      58             : #include <boost/unordered_map.hpp>
      59             : #include <string.h>
      60             : #ifdef WNT
      61             : #include <stdlib.h>
      62             : #include <ctype.h>
      63             : #endif
      64             : 
      65             : #include "rtl/bootstrap.h"
      66             : 
      67             : #include <string.h> // memcmp
      68             : 
      69             : using namespace com::sun::star;
      70             : 
      71             : namespace pdfi
      72             : {
      73             : 
      74             : namespace
      75             : {
      76             : 
      77             : // identifier of the strings coming from the out-of-process xpdf
      78             : // converter
      79             : enum parseKey {
      80             :     CLIPPATH,
      81             :     DRAWCHAR,
      82             :     DRAWIMAGE,
      83             :     DRAWLINK,
      84             :     DRAWMASK,
      85             :     DRAWMASKEDIMAGE,
      86             :     DRAWSOFTMASKEDIMAGE,
      87             :     ENDPAGE,
      88             :     ENDTEXTOBJECT,
      89             :     EOCLIPPATH,
      90             :     EOFILLPATH,
      91             :     FILLPATH,
      92             :     HYPERLINK,
      93             :     INTERSECTCLIP,
      94             :     INTERSECTEOCLIP,
      95             :     POPSTATE,
      96             :     PUSHSTATE,
      97             :     RESTORESTATE,
      98             :     SAVESTATE,
      99             :     SETBLENDMODE,
     100             :     SETFILLCOLOR,
     101             :     SETFONT,
     102             :     SETLINECAP,
     103             :     SETLINEDASH,
     104             :     SETLINEJOIN,
     105             :     SETLINEWIDTH,
     106             :     SETMITERLIMIT,
     107             :     SETPAGENUM,
     108             :     SETSTROKECOLOR,
     109             :     SETTEXTRENDERMODE,
     110             :     SETTRANSFORMATION,
     111             :     STARTPAGE,
     112             :     STROKEPATH,
     113             :     UPDATEBLENDMODE,
     114             :     UPDATECTM,
     115             :     UPDATEFILLCOLOR,
     116             :     UPDATEFILLOPACITY,
     117             :     UPDATEFLATNESS,
     118             :     UPDATEFONT,
     119             :     UPDATELINECAP,
     120             :     UPDATELINEDASH,
     121             :     UPDATELINEJOIN,
     122             :     UPDATELINEWIDTH,
     123             :     UPDATEMITERLIMIT,
     124             :     UPDATESTROKECOLOR,
     125             :     UPDATESTROKEOPACITY,
     126             :     NONE
     127             : };
     128             : 
     129             : #include "hash.cxx"
     130             : 
     131           3 : class Parser
     132             : {
     133             :     typedef boost::unordered_map< sal_Int64,
     134             :                            FontAttributes > FontMapType;
     135             : 
     136             :     const uno::Reference<uno::XComponentContext> m_xContext;
     137             :     const ContentSinkSharedPtr                   m_pSink;
     138             :     const oslFileHandle                          m_pErr;
     139             :     ::rtl::OString                               m_aLine;
     140             :     FontMapType                                  m_aFontMap;
     141             :     sal_Int32                                    m_nNextToken;
     142             :     sal_Int32                                    m_nCharIndex;
     143             : 
     144             :     const double                                 minAreaThreshold;
     145             :     const double                                 minLineWidth;
     146             : 
     147             :     ::rtl::OString readNextToken();
     148             :     void           readInt32( sal_Int32& o_Value );
     149             :     sal_Int32      readInt32();
     150             :     void           readInt64( sal_Int64& o_Value );
     151             :     void           readDouble( double& o_Value );
     152             :     double         readDouble();
     153             :     void           readBinaryData( uno::Sequence<sal_Int8>& rBuf );
     154             : 
     155             :     uno::Reference<rendering::XPolyPolygon2D> readPath( double* );
     156             : 
     157             :     void                 readChar();
     158             :     void                 readLineCap();
     159             :     void                 readLineDash();
     160             :     void                 readLineJoin();
     161             :     void                 readTransformation();
     162             :     rendering::ARGBColor readColor();
     163             :     void                 parseFontFamilyName( FontAttributes& aResult );
     164             :     void                 readFont();
     165             :     uno::Sequence<beans::PropertyValue> readImageImpl();
     166             : 
     167             :     void                 readImage();
     168             :     void                 readMask();
     169             :     void                 readLink();
     170             :     void                 readMaskedImage();
     171             :     void                 readSoftMaskedImage();
     172             :     int          parseFontCheckForString( const sal_Unicode* pCopy, const char* str, sal_Int32& nLen,
     173             :                     FontAttributes& aResult, bool bItalic, bool bBold);
     174             :     int          parseFontRemoveSuffix( const sal_Unicode* pCopy, const char* s, sal_Int32& nLen);
     175             : 
     176             : 
     177             : public:
     178           3 :     Parser( const ContentSinkSharedPtr&                   rSink,
     179             :             oslFileHandle                                 pErr,
     180             :             const uno::Reference<uno::XComponentContext>& xContext ) :
     181             :         m_xContext(xContext),
     182             :         m_pSink(rSink),
     183             :         m_pErr(pErr),
     184             :         m_aLine(),
     185             :         m_aFontMap(101),
     186             :         m_nNextToken(-1),
     187             :         m_nCharIndex(-1),
     188             :         minAreaThreshold( 300.0 ),
     189           3 :         minLineWidth( 12 )
     190           3 :     {}
     191             : 
     192             :     void parseLine( const ::rtl::OString& rLine );
     193             : };
     194             : 
     195             : 
     196             : namespace
     197             : {
     198             : 
     199             :     /** Unescapes line-ending characters in input string. These
     200             :         characters are encoded as pairs of characters: '\\' 'n', resp.
     201             :         '\\' 'r'. This function converts them back to '\n', resp. '\r'.
     202             :       */
     203         348 :     rtl::OString lcl_unescapeLineFeeds(const rtl::OString& i_rStr)
     204             :     {
     205         348 :         const size_t nOrigLen(sal::static_int_cast<size_t>(i_rStr.getLength()));
     206         348 :         const sal_Char* const pOrig(i_rStr.getStr());
     207         348 :         sal_Char* const pBuffer(new sal_Char[nOrigLen + 1]);
     208             : 
     209         348 :         const sal_Char* pRead(pOrig);
     210         348 :         sal_Char* pWrite(pBuffer);
     211         348 :         const sal_Char* pCur(pOrig);
     212         696 :         while ((pCur = strchr(pCur, '\\')) != 0)
     213             :         {
     214           0 :             const sal_Char cNext(pCur[1]);
     215           0 :             if (cNext == 'n' || cNext == 'r' || cNext == '\\')
     216             :             {
     217           0 :                 const size_t nLen(pCur - pRead);
     218           0 :                 strncpy(pWrite, pRead, nLen);
     219           0 :                 pWrite += nLen;
     220           0 :                 *pWrite = cNext == 'n' ? '\n' : (cNext == 'r' ? '\r' : '\\');
     221           0 :                 ++pWrite;
     222           0 :                 pCur = pRead = pCur + 2;
     223             :             }
     224             :             else
     225             :             {
     226             :                 // Just continue on the next character. The current
     227             :                 // block will be copied the next time it goes through the
     228             :                 // 'if' branch.
     229           0 :                 ++pCur;
     230             :             }
     231             :         }
     232             :         // maybe there are some data to copy yet
     233         348 :         if (sal::static_int_cast<size_t>(pRead - pOrig) < nOrigLen)
     234             :         {
     235         348 :             const size_t nLen(nOrigLen - (pRead - pOrig));
     236         348 :             strncpy(pWrite, pRead, nLen);
     237         348 :             pWrite += nLen;
     238             :         }
     239         348 :         *pWrite = '\0';
     240             : 
     241         348 :         rtl::OString aResult(pBuffer);
     242         348 :         delete[] pBuffer;
     243         348 :         return aResult;
     244             :     }
     245             : 
     246             : }
     247             : 
     248             : 
     249        3930 : ::rtl::OString Parser::readNextToken()
     250             : {
     251             :     OSL_PRECOND(m_nCharIndex!=-1,"insufficient input");
     252        3930 :     return m_aLine.getToken(m_nNextToken,' ',m_nCharIndex);
     253             : }
     254             : 
     255         261 : void Parser::readInt32( sal_Int32& o_Value )
     256             : {
     257         261 :     o_Value = readNextToken().toInt32();
     258         261 : }
     259             : 
     260          24 : sal_Int32 Parser::readInt32()
     261             : {
     262          24 :     return readNextToken().toInt32();
     263             : }
     264             : 
     265          33 : void Parser::readInt64( sal_Int64& o_Value )
     266             : {
     267          33 :     o_Value = readNextToken().toInt64();
     268          33 : }
     269             : 
     270        2955 : void Parser::readDouble( double& o_Value )
     271             : {
     272        2955 :     o_Value = readNextToken().toDouble();
     273        2955 : }
     274             : 
     275          39 : double Parser::readDouble()
     276             : {
     277          39 :     return readNextToken().toDouble();
     278             : }
     279             : 
     280           9 : void Parser::readBinaryData( uno::Sequence<sal_Int8>& rBuf )
     281             : {
     282           9 :     sal_Int32 nFileLen( rBuf.getLength() );
     283           9 :     sal_Int8*           pBuf( rBuf.getArray() );
     284           9 :     sal_uInt64          nBytesRead(0);
     285           9 :     oslFileError        nRes=osl_File_E_None;
     286          36 :     while( nFileLen &&
     287           9 :            osl_File_E_None == (nRes=osl_readFile( m_pErr, pBuf, nFileLen, &nBytesRead )) )
     288             :     {
     289           9 :         pBuf += nBytesRead;
     290           9 :         nFileLen -= sal::static_int_cast<sal_Int32>(nBytesRead);
     291             :     }
     292             : 
     293             :     OSL_PRECOND(nRes==osl_File_E_None, "inconsistent data");
     294           9 : }
     295             : 
     296          15 : uno::Reference<rendering::XPolyPolygon2D> Parser::readPath( double* pArea = NULL )
     297             : {
     298          15 :     const rtl::OString aSubPathMarker( "subpath" );
     299             : 
     300          15 :     if( 0 != readNextToken().compareTo( aSubPathMarker ) )
     301             :         OSL_PRECOND(false, "broken path");
     302             : 
     303          15 :     basegfx::B2DPolyPolygon aResult;
     304          45 :     while( m_nCharIndex != -1 )
     305             :     {
     306          15 :         basegfx::B2DPolygon aSubPath;
     307             : 
     308             :         sal_Int32 nClosedFlag;
     309          15 :         readInt32( nClosedFlag );
     310          15 :         aSubPath.setClosed( nClosedFlag != 0 );
     311             : 
     312          15 :         sal_Int32 nContiguousControlPoints(0);
     313          15 :         sal_Int32 nDummy=m_nCharIndex;
     314          15 :         rtl::OString aCurrToken( m_aLine.getToken(m_nNextToken,' ',nDummy) );
     315             : 
     316         111 :         while( m_nCharIndex != -1 && 0 != aCurrToken.compareTo(aSubPathMarker) )
     317             :         {
     318             :             sal_Int32 nCurveFlag;
     319             :             double    nX, nY;
     320          81 :             readDouble( nX );
     321          81 :             readDouble( nY );
     322          81 :             readInt32(  nCurveFlag );
     323             : 
     324          81 :             aSubPath.append(basegfx::B2DPoint(nX,nY));
     325          81 :             if( nCurveFlag )
     326             :             {
     327          24 :                 ++nContiguousControlPoints;
     328             :             }
     329          57 :             else if( nContiguousControlPoints )
     330             :             {
     331             :                 OSL_PRECOND(nContiguousControlPoints==2,"broken bezier path");
     332             : 
     333             :                 // have two control points before us. the current one
     334             :                 // is a normal point - thus, convert previous points
     335             :                 // into bezier segment
     336          12 :                 const sal_uInt32 nPoints( aSubPath.count() );
     337          12 :                 const basegfx::B2DPoint aCtrlA( aSubPath.getB2DPoint(nPoints-3) );
     338          12 :                 const basegfx::B2DPoint aCtrlB( aSubPath.getB2DPoint(nPoints-2) );
     339          12 :                 const basegfx::B2DPoint aEnd( aSubPath.getB2DPoint(nPoints-1) );
     340          12 :                 aSubPath.remove(nPoints-3, 3);
     341          12 :                 aSubPath.appendBezierSegment(aCtrlA, aCtrlB, aEnd);
     342             : 
     343          12 :                 nContiguousControlPoints=0;
     344             :             }
     345             : 
     346             :             // one token look-ahead (new subpath or more points?
     347          81 :             nDummy=m_nCharIndex;
     348          81 :             aCurrToken = m_aLine.getToken(m_nNextToken,' ',nDummy);
     349             :         }
     350             : 
     351          15 :         aResult.append( aSubPath );
     352          15 :         if( m_nCharIndex != -1 )
     353           0 :             readNextToken();
     354          15 :     }
     355             : 
     356          15 :     if( pArea )
     357             :     {
     358           3 :         basegfx::B2DRange aRange( aResult.getB2DRange() );
     359           3 :         if( aRange.getWidth() <= minLineWidth || aRange.getHeight() <= minLineWidth)
     360           0 :             *pArea = 0.0;
     361             :         else
     362           3 :             *pArea = aRange.getWidth() * aRange.getHeight();
     363             :     }
     364             : 
     365             :     return static_cast<rendering::XLinePolyPolygon2D*>(
     366          15 :         new basegfx::unotools::UnoPolyPolygon(aResult));
     367             : }
     368             : 
     369         312 : void Parser::readChar()
     370             : {
     371         312 :     geometry::Matrix2D aUnoMatrix;
     372         312 :     geometry::RealRectangle2D aRect;
     373             : 
     374         312 :     readDouble(aRect.X1);
     375         312 :     readDouble(aRect.Y1);
     376         312 :     readDouble(aRect.X2);
     377         312 :     readDouble(aRect.Y2);
     378         312 :     readDouble(aUnoMatrix.m00);
     379         312 :     readDouble(aUnoMatrix.m01);
     380         312 :     readDouble(aUnoMatrix.m10);
     381         312 :     readDouble(aUnoMatrix.m11);
     382             : 
     383         312 :     rtl::OString aChars = lcl_unescapeLineFeeds( m_aLine.copy( m_nCharIndex ) );
     384             : 
     385             :     // chars gobble up rest of line
     386         312 :     m_nCharIndex = -1;
     387             : 
     388         312 :     m_pSink->drawGlyphs( rtl::OStringToOUString( aChars,
     389             :                                                  RTL_TEXTENCODING_UTF8 ),
     390         312 :                          aRect, aUnoMatrix );
     391         312 : }
     392             : 
     393           9 : void Parser::readLineCap()
     394             : {
     395           9 :     sal_Int8 nCap(rendering::PathCapType::BUTT);
     396           9 :     switch( readInt32() )
     397             :     {
     398             :         default:
     399             :             // FALLTHROUGH intended
     400           9 :         case 0: nCap = rendering::PathCapType::BUTT; break;
     401           0 :         case 1: nCap = rendering::PathCapType::ROUND; break;
     402           0 :         case 2: nCap = rendering::PathCapType::SQUARE; break;
     403             :     }
     404           9 :     m_pSink->setLineCap(nCap);
     405           9 : }
     406             : 
     407           6 : void Parser::readLineDash()
     408             : {
     409           6 :     if( m_nCharIndex == -1 )
     410             :     {
     411           3 :         m_pSink->setLineDash( uno::Sequence<double>(), 0.0 );
     412           6 :         return;
     413             :     }
     414             : 
     415           3 :     const double nOffset(readDouble());
     416           3 :     const sal_Int32 nLen(readInt32());
     417             : 
     418           3 :     uno::Sequence<double> aDashArray(nLen);
     419           3 :     double* pArray=aDashArray.getArray();
     420          15 :     for( sal_Int32 i=0; i<nLen; ++i )
     421          12 :         *pArray++ = readDouble();
     422             : 
     423           3 :     m_pSink->setLineDash( aDashArray, nOffset );
     424             : }
     425             : 
     426           9 : void Parser::readLineJoin()
     427             : {
     428           9 :     sal_Int8 nJoin(rendering::PathJoinType::MITER);
     429           9 :     switch( readInt32() )
     430             :     {
     431             :         default:
     432             :             // FALLTHROUGH intended
     433           3 :         case 0: nJoin = rendering::PathJoinType::MITER; break;
     434           6 :         case 1: nJoin = rendering::PathJoinType::ROUND; break;
     435           0 :         case 2: nJoin = rendering::PathJoinType::BEVEL; break;
     436             :     }
     437           9 :     m_pSink->setLineJoin(nJoin);
     438           9 : }
     439             : 
     440           6 : void Parser::readTransformation()
     441             : {
     442           6 :     geometry::AffineMatrix2D aMat;
     443           6 :     readDouble(aMat.m00);
     444           6 :     readDouble(aMat.m10);
     445           6 :     readDouble(aMat.m01);
     446           6 :     readDouble(aMat.m11);
     447           6 :     readDouble(aMat.m02);
     448           6 :     readDouble(aMat.m12);
     449           6 :     m_pSink->setTransformation( aMat );
     450           6 : }
     451             : 
     452          54 : rendering::ARGBColor Parser::readColor()
     453             : {
     454          54 :     rendering::ARGBColor aRes;
     455          54 :     readDouble(aRes.Red);
     456          54 :     readDouble(aRes.Green);
     457          54 :     readDouble(aRes.Blue);
     458          54 :     readDouble(aRes.Alpha);
     459          54 :     return aRes;
     460             : }
     461             : 
     462         600 : int Parser::parseFontCheckForString( const sal_Unicode* pCopy, const char* s, sal_Int32& nLen,
     463             :         FontAttributes& aResult, bool bItalic, bool bBold)
     464             : {
     465         600 :     int l = strlen(s);
     466         600 :     if (nLen < l)
     467         375 :         return 0;
     468         228 :     for (int i = 0; i < l; i++)
     469         456 :         if (tolower(pCopy[i]) != s[i]
     470         228 :             && toupper(pCopy[i]) != s[i])
     471         225 :             return 0;
     472           0 :     aResult.isItalic = bItalic;
     473           0 :     aResult.isBold = bBold;
     474           0 :         nLen -= l;
     475           0 :         pCopy += l;
     476           0 :     return l;
     477             : }
     478             : 
     479         150 : int Parser::parseFontRemoveSuffix( const sal_Unicode* pCopy, const char* s, sal_Int32& nLen)
     480             : {
     481         150 :     int l = strlen(s);
     482         150 :     if (nLen < l)
     483          36 :         return 0;
     484         114 :     for (int i = 0; i < l; i++)
     485         114 :         if ( pCopy[nLen - l + i] != s[i] )
     486         114 :             return 0;
     487           0 :         nLen -= l;
     488           0 :     return l;
     489             : }
     490             : 
     491           9 : void Parser::parseFontFamilyName( FontAttributes& aResult )
     492             : {
     493           9 :     rtl::OUStringBuffer aNewFamilyName( aResult.familyName.getLength() );
     494             : 
     495           9 :     const sal_Unicode* pCopy = aResult.familyName.getStr();
     496           9 :     sal_Int32 nLen = aResult.familyName.getLength();
     497             :     // parse out truetype subsets (e.g. BAAAAA+Thorndale)
     498           9 :     if( nLen > 8 && pCopy[6] == sal_Unicode('+') )
     499             :     {
     500           9 :         pCopy += 7;
     501           9 :         nLen -= 7;
     502             :     }
     503             : 
     504          93 :     while( nLen )
     505             :     {
     506          75 :     if (parseFontRemoveSuffix( pCopy, "PSMT", nLen)) {}
     507          75 :     else if (parseFontRemoveSuffix( pCopy, "MT", nLen)) {}
     508             : 
     509          75 :     if (parseFontCheckForString( pCopy, "Italic", nLen, aResult, true, false)) {}
     510          75 :     else if (parseFontCheckForString( pCopy, "-Bold", nLen, aResult, false, true)) {}
     511          75 :     else if (parseFontCheckForString( pCopy, "Bold", nLen, aResult, false, true)) {}
     512          75 :     else if (parseFontCheckForString( pCopy, "-Roman", nLen, aResult, false, false)) {}
     513          75 :     else if (parseFontCheckForString( pCopy, "-LightOblique", nLen, aResult, true, false)) {}
     514          75 :     else if (parseFontCheckForString( pCopy, "-BoldOblique", nLen, aResult, true, true)) {}
     515          75 :     else if (parseFontCheckForString( pCopy, "-Light", nLen, aResult, false, false)) {}
     516          75 :     else if (parseFontCheckForString( pCopy, "-Reg", nLen, aResult, false, false)) {}
     517             :         else
     518             :         {
     519          75 :             if( *pCopy != '-' )
     520          75 :                 aNewFamilyName.append( *pCopy );
     521          75 :             pCopy++;
     522          75 :             nLen--;
     523             :         }
     524             :     }
     525           9 :     aResult.familyName = aNewFamilyName.makeStringAndClear();
     526           9 : }
     527             : 
     528          33 : void Parser::readFont()
     529             : {
     530          33 :     ::rtl::OString aFontName;
     531             :     sal_Int64      nFontID;
     532             :     sal_Int32      nIsEmbedded, nIsBold, nIsItalic, nIsUnderline, nFileLen;
     533             :     double         nSize;
     534             : 
     535          33 :     readInt64(nFontID);
     536          33 :     readInt32(nIsEmbedded);
     537          33 :     readInt32(nIsBold);
     538          33 :     readInt32(nIsItalic);
     539          33 :     readInt32(nIsUnderline);
     540          33 :     readDouble(nSize);
     541          33 :     readInt32(nFileLen);
     542             : 
     543          33 :     nSize = nSize < 0.0 ? -nSize : nSize;
     544          33 :     aFontName = lcl_unescapeLineFeeds( m_aLine.copy( m_nCharIndex ) );
     545             : 
     546             :     // name gobbles up rest of line
     547          33 :     m_nCharIndex = -1;
     548             : 
     549          33 :     FontMapType::const_iterator pFont( m_aFontMap.find(nFontID) );
     550          33 :     if( pFont != m_aFontMap.end() )
     551             :     {
     552             :         OSL_PRECOND(nFileLen==0,"font data for known font");
     553          24 :         FontAttributes aRes(pFont->second);
     554          24 :         aRes.size = nSize;
     555          24 :         m_pSink->setFont( aRes );
     556             : 
     557          57 :         return;
     558             :     }
     559             : 
     560             :     // yet unknown font - get info and add to map
     561             :     FontAttributes aResult( rtl::OStringToOUString( aFontName,
     562             :                                                     RTL_TEXTENCODING_UTF8 ),
     563             :                             nIsBold != 0,
     564             :                             nIsItalic != 0,
     565             :                             nIsUnderline != 0,
     566             :                             false,
     567           9 :                             nSize );
     568             : 
     569             :     // extract textual attributes (bold, italic in the name, etc.)
     570           9 :     parseFontFamilyName(aResult);
     571             :     // need to read font file?
     572           9 :     if( nFileLen )
     573             :     {
     574           9 :         uno::Sequence<sal_Int8> aFontFile(nFileLen);
     575           9 :         readBinaryData( aFontFile );
     576             : 
     577           9 :         awt::FontDescriptor aFD;
     578           9 :         uno::Sequence< uno::Any > aArgs(1);
     579           9 :         aArgs[0] <<= aFontFile;
     580             : 
     581             :         try
     582             :         {
     583             :             uno::Reference< beans::XMaterialHolder > xMat(
     584          18 :                 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
     585             :                     rtl::OUString( "com.sun.star.awt.FontIdentificator"  ),
     586             :                     aArgs,
     587           9 :                     m_xContext ),
     588           9 :                 uno::UNO_QUERY );
     589           9 :             if( xMat.is() )
     590             :             {
     591           0 :                 uno::Any aRes( xMat->getMaterial() );
     592           0 :                 if( aRes >>= aFD )
     593             :                 {
     594           0 :                     aResult.familyName  = aFD.Name;
     595           0 :                 parseFontFamilyName(aResult);
     596           0 :                     aResult.isBold      = (aFD.Weight > 100.0);
     597             :                     aResult.isItalic    = (aFD.Slant == awt::FontSlant_OBLIQUE ||
     598           0 :                                            aFD.Slant == awt::FontSlant_ITALIC );
     599           0 :                     aResult.isUnderline = false;
     600           0 :                     aResult.size        = 0;
     601           0 :                 }
     602           9 :             }
     603             :         }
     604           0 :         catch( uno::Exception& )
     605             :         {
     606             :         }
     607             : 
     608           9 :         if( aResult.familyName.isEmpty() )
     609             :         {
     610             :             // last fallback
     611           0 :             aResult.familyName  = ::rtl::OUString( "Arial"  );
     612           0 :             aResult.isUnderline = false;
     613           9 :         }
     614             : 
     615             :     }
     616           9 :     m_aFontMap[nFontID] = aResult;
     617             : 
     618           9 :     aResult.size = nSize;
     619           9 :     m_pSink->setFont(aResult);
     620             : }
     621             : 
     622           0 : uno::Sequence<beans::PropertyValue> Parser::readImageImpl()
     623             : {
     624           0 :     static const rtl::OString aJpegMarker( "JPEG" );
     625           0 :     static const rtl::OString aPbmMarker( "PBM" );
     626           0 :     static const rtl::OString aPpmMarker( "PPM" );
     627           0 :     static const rtl::OString aPngMarker( "PNG" );
     628           0 :     static const rtl::OUString aJpegFile( "DUMMY.JPEG" );
     629           0 :     static const rtl::OUString aPbmFile( "DUMMY.PBM" );
     630           0 :     static const rtl::OUString aPpmFile( "DUMMY.PPM" );
     631           0 :     static const rtl::OUString aPngFile( "DUMMY.PNG" );
     632             : 
     633           0 :     rtl::OString aToken = readNextToken();
     634           0 :     const sal_Int32 nImageSize( readInt32() );
     635             : 
     636           0 :     rtl::OUString           aFileName;
     637           0 :     if( aToken.compareTo( aPngMarker ) == 0 )
     638           0 :         aFileName = aPngFile;
     639           0 :     else if( aToken.compareTo( aJpegMarker ) == 0 )
     640           0 :         aFileName = aJpegFile;
     641           0 :     else if( aToken.compareTo( aPbmMarker ) == 0 )
     642           0 :         aFileName = aPbmFile;
     643             :     else
     644             :     {
     645             :         OSL_PRECOND( aToken.compareTo( aPpmMarker ) == 0,
     646             :                      "Invalid bitmap format" );
     647           0 :         aFileName = aPpmFile;
     648             :     }
     649             : 
     650           0 :     uno::Sequence<sal_Int8> aDataSequence(nImageSize);
     651           0 :     readBinaryData( aDataSequence );
     652             : 
     653           0 :     uno::Sequence< uno::Any > aStreamCreationArgs(1);
     654           0 :     aStreamCreationArgs[0] <<= aDataSequence;
     655             : 
     656           0 :     uno::Reference< uno::XComponentContext > xContext( m_xContext, uno::UNO_SET_THROW );
     657           0 :     uno::Reference< lang::XMultiComponentFactory > xFactory( xContext->getServiceManager(), uno::UNO_SET_THROW );
     658           0 :     uno::Reference< io::XInputStream > xDataStream( xFactory->createInstanceWithArgumentsAndContext(
     659             :         ::rtl::OUString( "com.sun.star.io.SequenceInputStream"  ),
     660           0 :         aStreamCreationArgs, m_xContext ), uno::UNO_QUERY_THROW );
     661             : 
     662           0 :     uno::Sequence<beans::PropertyValue> aSequence(3);
     663           0 :     aSequence[0] = beans::PropertyValue( ::rtl::OUString("URL"),
     664             :                                          0,
     665             :                                          uno::makeAny(aFileName),
     666           0 :                                          beans::PropertyState_DIRECT_VALUE );
     667           0 :     aSequence[1] = beans::PropertyValue( ::rtl::OUString("InputStream"),
     668             :                                          0,
     669             :                                          uno::makeAny( xDataStream ),
     670           0 :                                          beans::PropertyState_DIRECT_VALUE );
     671           0 :     aSequence[2] = beans::PropertyValue( ::rtl::OUString("InputSequence"),
     672             :                                          0,
     673             :                                          uno::makeAny(aDataSequence),
     674           0 :                                          beans::PropertyState_DIRECT_VALUE );
     675             : 
     676           0 :     return aSequence;
     677             : }
     678             : 
     679           0 : void Parser::readImage()
     680             : {
     681             :     sal_Int32 nWidth, nHeight,nMaskColors;
     682           0 :     readInt32(nWidth);
     683           0 :     readInt32(nHeight);
     684           0 :     readInt32(nMaskColors);
     685             : 
     686           0 :     uno::Sequence<beans::PropertyValue> aImg( readImageImpl() );
     687             : 
     688           0 :     if( nMaskColors )
     689             :     {
     690           0 :         uno::Sequence<sal_Int8> aDataSequence(nMaskColors);
     691           0 :         readBinaryData( aDataSequence );
     692             : 
     693           0 :         uno::Sequence<uno::Any> aMaskRanges(2);
     694             : 
     695           0 :         uno::Sequence<double> aMinRange(nMaskColors/2);
     696           0 :         uno::Sequence<double> aMaxRange(nMaskColors/2);
     697           0 :         for( sal_Int32 i=0; i<nMaskColors/2; ++i )
     698             :         {
     699           0 :             aMinRange[i] = aDataSequence[i] / 255.0;
     700           0 :             aMaxRange[i] = aDataSequence[i+nMaskColors/2] / 255.0;
     701             :         }
     702             : 
     703           0 :         aMaskRanges[0] = uno::makeAny(aMinRange);
     704           0 :         aMaskRanges[1] = uno::makeAny(aMaxRange);
     705             : 
     706           0 :         m_pSink->drawColorMaskedImage( aImg, aMaskRanges );
     707             :     }
     708             :     else
     709           0 :         m_pSink->drawImage( aImg );
     710           0 : }
     711             : 
     712           0 : void Parser::readMask()
     713             : {
     714             :     sal_Int32 nWidth, nHeight, nInvert;
     715           0 :     readInt32(nWidth);
     716           0 :     readInt32(nHeight);
     717           0 :     readInt32(nInvert);
     718             : 
     719           0 :     m_pSink->drawMask( readImageImpl(), nInvert );
     720           0 : }
     721             : 
     722           3 : void Parser::readLink()
     723             : {
     724           3 :     geometry::RealRectangle2D aBounds;
     725           3 :     readDouble(aBounds.X1);
     726           3 :     readDouble(aBounds.Y1);
     727           3 :     readDouble(aBounds.X2);
     728           3 :     readDouble(aBounds.Y2);
     729             : 
     730           3 :     m_pSink->hyperLink( aBounds,
     731             :                         rtl::OStringToOUString( lcl_unescapeLineFeeds(
     732             :                                 m_aLine.copy(m_nCharIndex) ),
     733           3 :                                 RTL_TEXTENCODING_UTF8 ) );
     734             :     // name gobbles up rest of line
     735           3 :     m_nCharIndex = -1;
     736           3 : }
     737             : 
     738           0 : void Parser::readMaskedImage()
     739             : {
     740             :     sal_Int32 nWidth, nHeight, nMaskWidth, nMaskHeight, nMaskInvert;
     741           0 :     readInt32(nWidth);
     742           0 :     readInt32(nHeight);
     743           0 :     readInt32(nMaskWidth);
     744           0 :     readInt32(nMaskHeight);
     745           0 :     readInt32(nMaskInvert);
     746             : 
     747           0 :     const uno::Sequence<beans::PropertyValue> aImage( readImageImpl() );
     748           0 :     const uno::Sequence<beans::PropertyValue> aMask ( readImageImpl() );
     749           0 :     m_pSink->drawMaskedImage( aImage, aMask, nMaskInvert != 0 );
     750           0 : }
     751             : 
     752           0 : void Parser::readSoftMaskedImage()
     753             : {
     754             :     sal_Int32 nWidth, nHeight, nMaskWidth, nMaskHeight;
     755           0 :     readInt32(nWidth);
     756           0 :     readInt32(nHeight);
     757           0 :     readInt32(nMaskWidth);
     758           0 :     readInt32(nMaskHeight);
     759             : 
     760           0 :     const uno::Sequence<beans::PropertyValue> aImage( readImageImpl() );
     761           0 :     const uno::Sequence<beans::PropertyValue> aMask ( readImageImpl() );
     762           0 :     m_pSink->drawAlphaMaskedImage( aImage, aMask );
     763           0 : }
     764             : 
     765         603 : void Parser::parseLine( const ::rtl::OString& rLine )
     766             : {
     767             :     OSL_PRECOND( m_pSink,         "Invalid sink" );
     768             :     OSL_PRECOND( m_pErr,          "Invalid filehandle" );
     769             :     OSL_PRECOND( m_xContext.is(), "Invalid service factory" );
     770             : 
     771         603 :     m_nNextToken = 0; m_nCharIndex = 0; m_aLine = rLine;
     772         603 :     uno::Reference<rendering::XPolyPolygon2D> xPoly;
     773         603 :     const ::rtl::OString& rCmd = readNextToken();
     774             :     const hash_entry* pEntry = PdfKeywordHash::in_word_set( rCmd.getStr(),
     775         603 :                                                             rCmd.getLength() );
     776             :     OSL_ASSERT(pEntry);
     777         603 :     switch( pEntry->eKey )
     778             :     {
     779             :         case CLIPPATH:
     780           3 :             m_pSink->intersectClip(readPath()); break;
     781             :         case DRAWCHAR:
     782         312 :             readChar(); break;
     783             :         case DRAWIMAGE:
     784           0 :             readImage(); break;
     785             :         case DRAWLINK:
     786           3 :             readLink(); break;
     787             :         case DRAWMASK:
     788           0 :             readMask(); break;
     789             :         case DRAWMASKEDIMAGE:
     790           0 :             readMaskedImage(); break;
     791             :         case DRAWSOFTMASKEDIMAGE:
     792           0 :             readSoftMaskedImage(); break;
     793             :         case ENDPAGE:
     794           3 :             m_pSink->endPage(); break;
     795             :         case ENDTEXTOBJECT:
     796          33 :             m_pSink->endText(); break;
     797             :         case EOCLIPPATH:
     798           3 :             m_pSink->intersectEoClip(readPath()); break;
     799             :         case EOFILLPATH:
     800             :         {
     801           3 :             double area = 0.0;
     802           3 :             uno::Reference<rendering::XPolyPolygon2D> path = readPath( &area );
     803           3 :             m_pSink->eoFillPath(path);
     804             :             // if area is smaller than required, add borders.
     805           3 :             if(area < minAreaThreshold)
     806           0 :                 m_pSink->strokePath(path);
     807             :         }
     808           3 :         break;
     809             :         case FILLPATH:
     810             :         {
     811           0 :             double area = 0.0;
     812           0 :             uno::Reference<rendering::XPolyPolygon2D> path = readPath( &area );
     813           0 :             m_pSink->fillPath(path);
     814             :             // if area is smaller than required, add borders.
     815           0 :             if(area < minAreaThreshold)
     816           0 :                 m_pSink->strokePath(path);
     817             :         }
     818           0 :         break;
     819             :         case RESTORESTATE:
     820          48 :             m_pSink->popState(); break;
     821             :         case SAVESTATE:
     822          48 :             m_pSink->pushState(); break;
     823             :         case SETPAGENUM:
     824           3 :             m_pSink->setPageNum( readInt32() ); break;
     825             :         case STARTPAGE:
     826             :         {
     827           3 :             const double nWidth ( readDouble() );
     828           3 :             const double nHeight( readDouble() );
     829           3 :             m_pSink->startPage( geometry::RealSize2D( nWidth, nHeight ) );
     830             :             break;
     831             :         }
     832             :         case STROKEPATH:
     833           6 :             m_pSink->strokePath(readPath()); break;
     834             :         case UPDATECTM:
     835           6 :             readTransformation(); break;
     836             :         case UPDATEFILLCOLOR:
     837          42 :             m_pSink->setFillColor( readColor() ); break;
     838             :         case UPDATEFLATNESS:
     839           3 :             m_pSink->setFlatness( readDouble( ) ); break;
     840             :         case UPDATEFONT:
     841          33 :             readFont(); break;
     842             :         case UPDATELINECAP:
     843           9 :             readLineCap(); break;
     844             :         case UPDATELINEDASH:
     845           6 :             readLineDash(); break;
     846             :         case UPDATELINEJOIN:
     847           9 :             readLineJoin(); break;
     848             :         case UPDATELINEWIDTH:
     849          12 :             m_pSink->setLineWidth( readDouble() );break;
     850             :         case UPDATEMITERLIMIT:
     851           3 :             m_pSink->setMiterLimit( readDouble() ); break;
     852             :         case UPDATESTROKECOLOR:
     853          12 :             m_pSink->setStrokeColor( readColor() ); break;
     854             :         case UPDATESTROKEOPACITY:
     855           0 :             break;
     856             :         case SETTEXTRENDERMODE:
     857           0 :             m_pSink->setTextRenderMode( readInt32() ); break;
     858             : 
     859             :         case NONE:
     860             :         default:
     861             :             OSL_PRECOND(false,"Unknown input");
     862           0 :             break;
     863             :     }
     864             : 
     865             :     // all consumed?
     866         603 :     OSL_POSTCOND(m_nCharIndex==-1,"leftover scanner input");
     867         603 : }
     868             : 
     869         606 : oslFileError readLine( oslFileHandle pFile, ::rtl::OStringBuffer& line )
     870             : {
     871             :     OSL_PRECOND( line.getLength() == 0, "line buf not empty" );
     872             : 
     873             :     // TODO(P3): read larger chunks
     874         606 :     sal_Char aChar('\n');
     875             :     sal_uInt64 nBytesRead;
     876             :     oslFileError nRes;
     877             : 
     878             :     // skip garbage \r \n at start of line
     879         606 :     while( osl_File_E_None == (nRes=osl_readFile(pFile, &aChar, 1, &nBytesRead)) &&
     880             :            nBytesRead == 1 &&
     881             :            (aChar == '\n' || aChar == '\r') ) ;
     882             : 
     883         606 :     if( aChar != '\n' && aChar != '\r' )
     884         603 :         line.append( aChar );
     885             : 
     886       38358 :     while( osl_File_E_None == (nRes=osl_readFile(pFile, &aChar, 1, &nBytesRead)) &&
     887             :            nBytesRead == 1 && aChar != '\n' && aChar != '\r' )
     888             :     {
     889       37146 :         line.append( aChar );
     890             :     }
     891             : 
     892         606 :     return nRes;
     893             : }
     894             : 
     895             : } // namespace
     896             : 
     897           3 : static bool checkEncryption( const rtl::OUString&                               i_rPath,
     898             :                              const uno::Reference< task::XInteractionHandler >& i_xIHdl,
     899             :                              rtl::OUString&                                     io_rPwd,
     900             :                              bool&                                              o_rIsEncrypted,
     901             :                              const rtl::OUString&                               i_rDocName
     902             :                              )
     903             : {
     904           3 :     bool bSuccess = false;
     905           3 :     rtl::OString aPDFFile;
     906           3 :     aPDFFile = rtl::OUStringToOString( i_rPath, osl_getThreadTextEncoding() );
     907             : 
     908           3 :     pdfparse::PDFReader aParser;
     909           3 :     boost::scoped_ptr<pdfparse::PDFEntry> pEntry( aParser.read( aPDFFile.getStr() ));
     910           3 :     if( pEntry )
     911             :     {
     912           3 :         pdfparse::PDFFile* pPDFFile = dynamic_cast<pdfparse::PDFFile*>(pEntry.get());
     913           3 :         if( pPDFFile )
     914             :         {
     915           3 :             o_rIsEncrypted = pPDFFile->isEncrypted();
     916           3 :             if( o_rIsEncrypted )
     917             :             {
     918           0 :                 if( pPDFFile->usesSupportedEncryptionFormat() )
     919             :                 {
     920           0 :                     bool bAuthenticated = false;
     921           0 :                     if( !io_rPwd.isEmpty() )
     922             :                     {
     923             :                         rtl::OString aIsoPwd = rtl::OUStringToOString( io_rPwd,
     924           0 :                                                                        RTL_TEXTENCODING_ISO_8859_1 );
     925           0 :                         bAuthenticated = pPDFFile->setupDecryptionData( aIsoPwd.getStr() );
     926             :                     }
     927           0 :                     if( bAuthenticated )
     928           0 :                         bSuccess = true;
     929             :                     else
     930             :                     {
     931           0 :                         if( i_xIHdl.is() )
     932             :                         {
     933           0 :                             bool bEntered = false;
     934           0 :                             do
     935             :                             {
     936           0 :                                 bEntered = getPassword( i_xIHdl, io_rPwd, ! bEntered, i_rDocName );
     937             :                                 rtl::OString aIsoPwd = rtl::OUStringToOString( io_rPwd,
     938           0 :                                                                                RTL_TEXTENCODING_ISO_8859_1 );
     939           0 :                                 bAuthenticated = pPDFFile->setupDecryptionData( aIsoPwd.getStr() );
     940           0 :                             } while( bEntered && ! bAuthenticated );
     941             :                         }
     942             : 
     943             :                         OSL_TRACE( "password: %s", bAuthenticated ? "matches" : "does not match" );
     944           0 :                         bSuccess = bAuthenticated;
     945             :                     }
     946           0 :                     if( bAuthenticated )
     947             :                     {
     948           0 :                         rtl::OUStringBuffer aBuf( 128 );
     949           0 :                         aBuf.appendAscii( "_OOO_pdfi_Credentials_" );
     950           0 :                         aBuf.append( pPDFFile->getDecryptionKey() );
     951           0 :                         io_rPwd = aBuf.makeStringAndClear();
     952             :                     }
     953             :                 }
     954           0 :                 else if( i_xIHdl.is() )
     955             :                 {
     956           0 :                     reportUnsupportedEncryptionFormat( i_xIHdl );
     957             :                         //TODO: this should either be handled further down the
     958             :                         // call stack, or else information that this has already
     959             :                         // been handled should be passed down the call stack, so
     960             :                         // that SfxBaseModel::load does not show an additional
     961             :                         // "General Error" message box
     962             :                 }
     963             :             }
     964             :             else
     965           3 :                 bSuccess = true;
     966             :         }
     967             :     }
     968           3 :     return bSuccess;
     969             : }
     970             : 
     971           3 : bool xpdf_ImportFromFile( const ::rtl::OUString&                             rURL,
     972             :                           const ContentSinkSharedPtr&                        rSink,
     973             :                           const uno::Reference< task::XInteractionHandler >& xIHdl,
     974             :                           const rtl::OUString&                               rPwd,
     975             :                           const uno::Reference< uno::XComponentContext >&    xContext )
     976             : {
     977             :     OSL_ASSERT(rSink);
     978             : 
     979           3 :     ::rtl::OUString aSysUPath;
     980           3 :     if( osl_getSystemPathFromFileURL( rURL.pData, &aSysUPath.pData ) != osl_File_E_None )
     981             :     {
     982             :         SAL_WARN(
     983             :             "sdext.pdfimport",
     984             :             "getSystemPathFromFileURL(" << rURL << ") failed");
     985           0 :         return false;
     986             :     }
     987           3 :     rtl::OUString aDocName( rURL.copy( rURL.lastIndexOf( sal_Unicode('/') )+1 ) );
     988             : 
     989             :     // check for encryption, if necessary get password
     990           3 :     rtl::OUString aPwd( rPwd );
     991           3 :     bool bIsEncrypted = false;
     992           3 :     if( checkEncryption( aSysUPath, xIHdl, aPwd, bIsEncrypted, aDocName ) == false )
     993             :     {
     994             :         SAL_INFO(
     995             :             "sdext.pdfimport",
     996             :             "checkEncryption(" << aSysUPath << ") failed");
     997           0 :         return false;
     998             :     }
     999             : 
    1000             :     // Determine xpdfimport executable URL:
    1001           3 :     OUString converterURL("$BRAND_BASE_DIR/program/xpdfimport");
    1002           3 :     rtl::Bootstrap::expandMacros(converterURL); //TODO: detect failure
    1003             : 
    1004             :     // Determine pathname of xpdfimport_err.pdf:
    1005           3 :     OUString errPathname("$BRAND_BASE_DIR/share/xpdfimport/xpdfimport_err.pdf");
    1006           3 :     rtl::Bootstrap::expandMacros(errPathname); //TODO: detect failure
    1007           3 :     if (osl::FileBase::getSystemPathFromFileURL(errPathname, errPathname)
    1008             :         != osl::FileBase::E_None)
    1009             :     {
    1010             :         SAL_WARN(
    1011             :             "sdext.pdfimport",
    1012             :             "getSystemPathFromFileURL(" << errPathname << ") failed");
    1013           0 :         return false;
    1014             :     }
    1015             : 
    1016             :     // spawn separate process to keep LGPL/GPL code apart.
    1017             :     // ---------------------------------------------------
    1018           3 :     rtl_uString** ppEnv = NULL;
    1019           3 :     sal_uInt32 nEnv = 0;
    1020             : 
    1021             :     #if defined UNX && ! defined MACOSX
    1022           3 :     rtl::OUString aStr( "$URE_LIB_DIR"  );
    1023           3 :     rtl_bootstrap_expandMacros( &aStr.pData );
    1024           3 :     rtl::OUString aSysPath;
    1025           3 :     osl_getSystemPathFromFileURL( aStr.pData, &aSysPath.pData );
    1026           3 :     rtl::OUStringBuffer aEnvBuf( aStr.getLength() + 20 );
    1027           3 :     aEnvBuf.appendAscii( "LD_LIBRARY_PATH=" );
    1028           3 :     aEnvBuf.append( aSysPath );
    1029           3 :     aStr = aEnvBuf.makeStringAndClear();
    1030           3 :     ppEnv = &aStr.pData;
    1031           3 :     nEnv = 1;
    1032             :     #endif
    1033             : 
    1034           3 :     rtl_uString*  args[] = { aSysUPath.pData, errPathname.pData };
    1035           3 :     sal_Int32 nArgs = 2;
    1036             : 
    1037             :     oslProcess    aProcess;
    1038           3 :     oslFileHandle pIn  = NULL;
    1039           3 :     oslFileHandle pOut = NULL;
    1040           3 :     oslFileHandle pErr = NULL;
    1041             :     const oslProcessError eErr =
    1042             :         osl_executeProcess_WithRedirectedIO(converterURL.pData,
    1043             :                                             args,
    1044             :                                             nArgs,
    1045             :                                             osl_Process_SEARCHPATH|osl_Process_HIDDEN,
    1046             :                                             osl_getCurrentSecurity(),
    1047             :                                             0, ppEnv, nEnv,
    1048           3 :                                             &aProcess, &pIn, &pOut, &pErr);
    1049             : 
    1050           3 :     bool bRet=true;
    1051             :     try
    1052             :     {
    1053           3 :         if( eErr!=osl_Process_E_None )
    1054             :         {
    1055             :             SAL_WARN(
    1056             :                 "sdext.pdfimport",
    1057             :                 "executeProcess of " << converterURL << " failed with "
    1058             :                     << +eErr);
    1059           0 :             return false;
    1060             :         }
    1061             : 
    1062           3 :         if( pIn )
    1063             :         {
    1064           3 :             rtl::OStringBuffer aBuf(256);
    1065           3 :             if( bIsEncrypted )
    1066           0 :                 aBuf.append( rtl::OUStringToOString( aPwd, RTL_TEXTENCODING_ISO_8859_1 ) );
    1067           3 :             aBuf.append( '\n' );
    1068             : 
    1069           3 :             sal_uInt64 nWritten = 0;
    1070           3 :             osl_writeFile( pIn, aBuf.getStr(), sal_uInt64(aBuf.getLength()), &nWritten );
    1071             :         }
    1072             : 
    1073           3 :         if( pOut && pErr )
    1074             :         {
    1075             :             // read results of PDF parser. One line - one call to
    1076             :             // OutputDev. stderr is used for alternate streams, like
    1077             :             // embedded fonts and bitmaps
    1078           3 :             Parser aParser(rSink,pErr,xContext);
    1079           3 :             ::rtl::OStringBuffer line;
    1080         609 :             while( osl_File_E_None == readLine(pOut, line) && line.getLength() )
    1081         606 :                 aParser.parseLine(line.makeStringAndClear());
    1082             :         }
    1083             :     }
    1084           0 :     catch( uno::Exception& )
    1085             :     {
    1086             :         // crappy C file interface. need manual resource dealloc
    1087           0 :         bRet = false;
    1088             :     }
    1089             : 
    1090           3 :     if( pIn )
    1091           3 :         osl_closeFile(pIn);
    1092           3 :     if( pOut )
    1093           3 :         osl_closeFile(pOut);
    1094           3 :     if( pErr )
    1095           3 :         osl_closeFile(pErr);
    1096           3 :     osl_freeProcessHandle(aProcess);
    1097           3 :     return bRet;
    1098             : }
    1099             : 
    1100             : 
    1101           0 : bool xpdf_ImportFromStream( const uno::Reference< io::XInputStream >&         xInput,
    1102             :                             const ContentSinkSharedPtr&                       rSink,
    1103             :                             const uno::Reference<task::XInteractionHandler >& xIHdl,
    1104             :                             const rtl::OUString&                              rPwd,
    1105             :                             const uno::Reference< uno::XComponentContext >&   xContext )
    1106             : {
    1107             :     OSL_ASSERT(xInput.is());
    1108             :     OSL_ASSERT(rSink);
    1109             : 
    1110             :     // convert XInputStream to local temp file
    1111           0 :     oslFileHandle aFile = NULL;
    1112           0 :     rtl::OUString aURL;
    1113           0 :     if( osl_createTempFile( NULL, &aFile, &aURL.pData ) != osl_File_E_None )
    1114           0 :         return false;
    1115             : 
    1116             :     // copy content, buffered...
    1117           0 :     const sal_uInt32 nBufSize = 4096;
    1118           0 :     uno::Sequence<sal_Int8> aBuf( nBufSize );
    1119           0 :     sal_uInt64 nBytes = 0;
    1120           0 :     sal_uInt64 nWritten = 0;
    1121           0 :     bool bSuccess = true;
    1122           0 :     do
    1123             :     {
    1124             :         try
    1125             :         {
    1126           0 :             nBytes = xInput->readBytes( aBuf, nBufSize );
    1127             :         }
    1128           0 :         catch( com::sun::star::uno::Exception& )
    1129             :         {
    1130           0 :             osl_closeFile( aFile );
    1131           0 :             throw;
    1132             :         }
    1133           0 :         if( nBytes > 0 )
    1134             :         {
    1135           0 :             osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
    1136           0 :             if( nWritten != nBytes )
    1137             :             {
    1138           0 :                 bSuccess = false;
    1139           0 :                 break;
    1140             :             }
    1141             :         }
    1142             :     }
    1143             :     while( nBytes == nBufSize );
    1144             : 
    1145           0 :     osl_closeFile( aFile );
    1146             : 
    1147           0 :     if ( bSuccess )
    1148           0 :         bSuccess = xpdf_ImportFromFile( aURL, rSink, xIHdl, rPwd, xContext );
    1149           0 :     osl_removeFile( aURL.pData );
    1150             : 
    1151           0 :     return bSuccess;
    1152             : }
    1153             : 
    1154             : }
    1155             : 
    1156             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10