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

Generated by: LCOV version 1.10