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