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

Generated by: LCOV version 1.11