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 <boost/unordered_map.hpp>
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 6 : class Parser
136 : {
137 : typedef boost::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 : 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 : 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 : sal_Int32 parseFontRemoveSuffix(const sal_Unicode* pCopy, sal_Int32 nCopyLen,
178 : const char* pAttrib, sal_Int32 nAttribLen);
179 :
180 : public:
181 6 : 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 6 : m_nCharIndex(-1)
191 6 : {}
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 696 : OString lcl_unescapeLineFeeds(const OString& i_rStr)
205 : {
206 696 : const size_t nOrigLen(sal::static_int_cast<size_t>(i_rStr.getLength()));
207 696 : const sal_Char* const pOrig(i_rStr.getStr());
208 696 : sal_Char* const pBuffer(new sal_Char[nOrigLen + 1]);
209 :
210 696 : const sal_Char* pRead(pOrig);
211 696 : sal_Char* pWrite(pBuffer);
212 696 : const sal_Char* pCur(pOrig);
213 1392 : 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 696 : if (sal::static_int_cast<size_t>(pRead - pOrig) < nOrigLen)
235 : {
236 696 : const size_t nLen(nOrigLen - (pRead - pOrig));
237 696 : strncpy(pWrite, pRead, nLen);
238 696 : pWrite += nLen;
239 : }
240 696 : *pWrite = '\0';
241 :
242 696 : OString aResult(pBuffer);
243 696 : delete[] pBuffer;
244 696 : return aResult;
245 : }
246 :
247 : }
248 :
249 :
250 8520 : OString Parser::readNextToken()
251 : {
252 : OSL_PRECOND(m_nCharIndex!=-1,"insufficient input");
253 8520 : return m_aLine.getToken(m_nNextToken,' ',m_nCharIndex);
254 : }
255 :
256 540 : void Parser::readInt32( sal_Int32& o_Value )
257 : {
258 540 : o_Value = readNextToken().toInt32();
259 540 : }
260 :
261 54 : sal_Int32 Parser::readInt32()
262 : {
263 54 : return readNextToken().toInt32();
264 : }
265 :
266 66 : void Parser::readInt64( sal_Int64& o_Value )
267 : {
268 66 : o_Value = readNextToken().toInt64();
269 66 : }
270 :
271 6534 : void Parser::readDouble( double& o_Value )
272 : {
273 6534 : o_Value = readNextToken().toDouble();
274 6534 : }
275 :
276 78 : double Parser::readDouble()
277 : {
278 78 : return readNextToken().toDouble();
279 : }
280 :
281 24 : void Parser::readBinaryData( uno::Sequence<sal_Int8>& rBuf )
282 : {
283 24 : sal_Int32 nFileLen( rBuf.getLength() );
284 24 : sal_Int8* pBuf( rBuf.getArray() );
285 24 : sal_uInt64 nBytesRead(0);
286 24 : oslFileError nRes=osl_File_E_None;
287 96 : while( nFileLen &&
288 24 : osl_File_E_None == (nRes=osl_readFile( m_pErr, pBuf, nFileLen, &nBytesRead )) )
289 : {
290 24 : pBuf += nBytesRead;
291 24 : nFileLen -= sal::static_int_cast<sal_Int32>(nBytesRead);
292 : }
293 :
294 : OSL_PRECOND(nRes==osl_File_E_None, "inconsistent data");
295 24 : }
296 :
297 30 : uno::Reference<rendering::XPolyPolygon2D> Parser::readPath()
298 : {
299 30 : const OString aSubPathMarker( "subpath" );
300 :
301 30 : if( readNextToken() != aSubPathMarker )
302 : OSL_PRECOND(false, "broken path");
303 :
304 60 : basegfx::B2DPolyPolygon aResult;
305 90 : while( m_nCharIndex != -1 )
306 : {
307 30 : basegfx::B2DPolygon aSubPath;
308 :
309 : sal_Int32 nClosedFlag;
310 30 : readInt32( nClosedFlag );
311 30 : aSubPath.setClosed( nClosedFlag != 0 );
312 :
313 30 : sal_Int32 nContiguousControlPoints(0);
314 30 : sal_Int32 nDummy=m_nCharIndex;
315 60 : OString aCurrToken( m_aLine.getToken(m_nNextToken,' ',nDummy) );
316 :
317 222 : while( m_nCharIndex != -1 && aCurrToken != aSubPathMarker )
318 : {
319 : sal_Int32 nCurveFlag;
320 : double nX, nY;
321 162 : readDouble( nX );
322 162 : readDouble( nY );
323 162 : readInt32( nCurveFlag );
324 :
325 162 : aSubPath.append(basegfx::B2DPoint(nX,nY));
326 162 : if( nCurveFlag )
327 : {
328 48 : ++nContiguousControlPoints;
329 : }
330 114 : 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 24 : const sal_uInt32 nPoints( aSubPath.count() );
338 24 : const basegfx::B2DPoint aCtrlA( aSubPath.getB2DPoint(nPoints-3) );
339 48 : const basegfx::B2DPoint aCtrlB( aSubPath.getB2DPoint(nPoints-2) );
340 48 : const basegfx::B2DPoint aEnd( aSubPath.getB2DPoint(nPoints-1) );
341 24 : aSubPath.remove(nPoints-3, 3);
342 24 : aSubPath.appendBezierSegment(aCtrlA, aCtrlB, aEnd);
343 :
344 48 : nContiguousControlPoints=0;
345 : }
346 :
347 : // one token look-ahead (new subpath or more points?
348 162 : nDummy=m_nCharIndex;
349 162 : aCurrToken = m_aLine.getToken(m_nNextToken,' ',nDummy);
350 : }
351 :
352 30 : aResult.append( aSubPath );
353 30 : if( m_nCharIndex != -1 )
354 0 : readNextToken();
355 30 : }
356 :
357 : return static_cast<rendering::XLinePolyPolygon2D*>(
358 60 : new basegfx::unotools::UnoPolyPolygon(aResult));
359 : }
360 :
361 624 : void Parser::readChar()
362 : {
363 : double fontSize;
364 624 : geometry::Matrix2D aUnoMatrix;
365 624 : geometry::RealRectangle2D aRect;
366 :
367 624 : readDouble(aRect.X1);
368 624 : readDouble(aRect.Y1);
369 624 : readDouble(aRect.X2);
370 624 : readDouble(aRect.Y2);
371 624 : readDouble(aUnoMatrix.m00);
372 624 : readDouble(aUnoMatrix.m01);
373 624 : readDouble(aUnoMatrix.m10);
374 624 : readDouble(aUnoMatrix.m11);
375 624 : readDouble(fontSize);
376 :
377 624 : OString aChars;
378 :
379 624 : if (m_nCharIndex != -1)
380 624 : aChars = lcl_unescapeLineFeeds( m_aLine.copy( m_nCharIndex ) );
381 :
382 : // chars gobble up rest of line
383 624 : m_nCharIndex = -1;
384 :
385 624 : m_pSink->drawGlyphs(OStringToOUString(aChars, RTL_TEXTENCODING_UTF8),
386 624 : aRect, aUnoMatrix, fontSize);
387 624 : }
388 :
389 18 : void Parser::readLineCap()
390 : {
391 18 : sal_Int8 nCap(rendering::PathCapType::BUTT);
392 18 : switch( readInt32() )
393 : {
394 : default:
395 : // FALLTHROUGH intended
396 18 : 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 18 : m_pSink->setLineCap(nCap);
401 18 : }
402 :
403 12 : void Parser::readLineDash()
404 : {
405 12 : if( m_nCharIndex == -1 )
406 : {
407 6 : m_pSink->setLineDash( uno::Sequence<double>(), 0.0 );
408 18 : return;
409 : }
410 :
411 6 : const double nOffset(readDouble());
412 6 : const sal_Int32 nLen(readInt32());
413 :
414 6 : uno::Sequence<double> aDashArray(nLen);
415 6 : double* pArray=aDashArray.getArray();
416 30 : for( sal_Int32 i=0; i<nLen; ++i )
417 24 : *pArray++ = readDouble();
418 :
419 6 : m_pSink->setLineDash( aDashArray, nOffset );
420 : }
421 :
422 18 : void Parser::readLineJoin()
423 : {
424 18 : sal_Int8 nJoin(rendering::PathJoinType::MITER);
425 18 : switch( readInt32() )
426 : {
427 : default:
428 : // FALLTHROUGH intended
429 6 : case 0: nJoin = rendering::PathJoinType::MITER; break;
430 12 : case 1: nJoin = rendering::PathJoinType::ROUND; break;
431 0 : case 2: nJoin = rendering::PathJoinType::BEVEL; break;
432 : }
433 18 : m_pSink->setLineJoin(nJoin);
434 18 : }
435 :
436 12 : void Parser::readTransformation()
437 : {
438 12 : geometry::AffineMatrix2D aMat;
439 12 : readDouble(aMat.m00);
440 12 : readDouble(aMat.m10);
441 12 : readDouble(aMat.m01);
442 12 : readDouble(aMat.m11);
443 12 : readDouble(aMat.m02);
444 12 : readDouble(aMat.m12);
445 12 : m_pSink->setTransformation( aMat );
446 12 : }
447 :
448 108 : rendering::ARGBColor Parser::readColor()
449 : {
450 108 : rendering::ARGBColor aRes;
451 108 : readDouble(aRes.Red);
452 108 : readDouble(aRes.Green);
453 108 : readDouble(aRes.Blue);
454 108 : readDouble(aRes.Alpha);
455 108 : return aRes;
456 : }
457 :
458 1200 : 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 1200 : if (nCopyLen < nAttribLen)
464 750 : return 0;
465 456 : for (sal_Int32 i = 0; i < nAttribLen; ++i)
466 456 : if (tolower(pCopy[i]) != pAttrib[i]
467 456 : && toupper(pCopy[i]) != pAttrib[i])
468 450 : return 0;
469 0 : rResult.isItalic |= bItalic;
470 0 : rResult.isBold |= bBold;
471 0 : return nAttribLen;
472 : }
473 :
474 300 : sal_Int32 Parser::parseFontRemoveSuffix(
475 : const sal_Unicode* pCopy, sal_Int32 nCopyLen,
476 : const char* pAttrib, sal_Int32 nAttribLen)
477 : {
478 300 : if (nCopyLen < nAttribLen)
479 72 : return 0;
480 228 : for (sal_Int32 i = 0; i < nAttribLen; ++i)
481 228 : if ( pCopy[nCopyLen - nAttribLen + i] != pAttrib[i] )
482 228 : return 0;
483 0 : return nAttribLen;
484 : }
485 :
486 18 : void Parser::parseFontFamilyName( FontAttributes& rResult )
487 : {
488 18 : OUStringBuffer aNewFamilyName( rResult.familyName.getLength() );
489 :
490 18 : const sal_Unicode* pCopy = rResult.familyName.getStr();
491 18 : sal_Int32 nLen = rResult.familyName.getLength();
492 : // parse out truetype subsets (e.g. BAAAAA+Thorndale)
493 18 : if( nLen > 8 && pCopy[6] == '+' )
494 : {
495 18 : pCopy += 7;
496 18 : nLen -= 7;
497 : }
498 :
499 : // TODO: Looks like this block needs to be refactored
500 186 : while( nLen )
501 : {
502 150 : if (parseFontRemoveSuffix(pCopy, nLen, RTL_CONSTASCII_STRINGPARAM("PSMT")))
503 : {
504 0 : nLen -= RTL_CONSTASCII_LENGTH("PSMT");
505 : }
506 150 : else if (parseFontRemoveSuffix(pCopy, nLen, RTL_CONSTASCII_STRINGPARAM("MT")))
507 : {
508 0 : nLen -= RTL_CONSTASCII_LENGTH("MT");
509 : }
510 :
511 150 : 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 150 : 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 150 : 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 150 : 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 150 : 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 150 : 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 150 : 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 150 : 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 150 : else if(nLen > 0)
560 : {
561 150 : if( *pCopy != '-' )
562 150 : aNewFamilyName.append( *pCopy );
563 150 : pCopy++;
564 150 : nLen--;
565 : }
566 : }
567 18 : rResult.familyName = aNewFamilyName.makeStringAndClear();
568 18 : }
569 :
570 66 : void Parser::readFont()
571 : {
572 66 : OString aFontName;
573 : sal_Int64 nFontID;
574 : sal_Int32 nIsEmbedded, nIsBold, nIsItalic, nIsUnderline, nFileLen;
575 : double nSize;
576 :
577 66 : readInt64(nFontID);
578 66 : readInt32(nIsEmbedded);
579 66 : readInt32(nIsBold);
580 66 : readInt32(nIsItalic);
581 66 : readInt32(nIsUnderline);
582 66 : readDouble(nSize);
583 66 : readInt32(nFileLen);
584 :
585 66 : nSize = nSize < 0.0 ? -nSize : nSize;
586 66 : aFontName = lcl_unescapeLineFeeds( m_aLine.copy( m_nCharIndex ) );
587 :
588 : // name gobbles up rest of line
589 66 : m_nCharIndex = -1;
590 :
591 66 : FontMapType::const_iterator pFont( m_aFontMap.find(nFontID) );
592 66 : if( pFont != m_aFontMap.end() )
593 : {
594 : OSL_PRECOND(nFileLen==0,"font data for known font");
595 48 : FontAttributes aRes(pFont->second);
596 48 : aRes.size = nSize;
597 48 : m_pSink->setFont( aRes );
598 :
599 114 : 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 36 : 1.0);
611 :
612 : // extract textual attributes (bold, italic in the name, etc.)
613 18 : parseFontFamilyName(aResult);
614 : // need to read font file?
615 18 : if( nFileLen )
616 : {
617 18 : uno::Sequence<sal_Int8> aFontFile(nFileLen);
618 18 : readBinaryData( aFontFile );
619 :
620 36 : awt::FontDescriptor aFD;
621 36 : uno::Sequence< uno::Any > aArgs(1);
622 18 : aArgs[0] <<= aFontFile;
623 :
624 : try
625 : {
626 : uno::Reference< beans::XMaterialHolder > xMat(
627 36 : m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
628 : OUString( "com.sun.star.awt.FontIdentificator" ),
629 : aArgs,
630 18 : m_xContext ),
631 18 : uno::UNO_QUERY );
632 18 : 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 18 : }
649 : }
650 0 : catch( uno::Exception& )
651 : {
652 : }
653 :
654 18 : if( aResult.familyName.isEmpty() )
655 : {
656 : // last fallback
657 0 : aResult.familyName = "Arial";
658 0 : aResult.isUnderline = false;
659 18 : }
660 :
661 : }
662 :
663 : static VirtualDevice* vDev = 0;
664 18 : if (vDev == 0)
665 2 : vDev = new VirtualDevice;
666 :
667 36 : vcl::Font font(aResult.familyName, Size(0, 1000));
668 18 : vDev->SetFont(font);
669 36 : FontMetric metric(vDev->GetFontMetric());
670 18 : aResult.ascent = metric.GetAscent() / 1000.0;
671 :
672 18 : m_aFontMap[nFontID] = aResult;
673 :
674 18 : aResult.size = nSize;
675 36 : m_pSink->setFont(aResult);
676 : }
677 :
678 6 : uno::Sequence<beans::PropertyValue> Parser::readImageImpl()
679 : {
680 6 : static const OString aJpegMarker( "JPEG" );
681 6 : static const OString aPbmMarker( "PBM" );
682 6 : static const OString aPpmMarker( "PPM" );
683 6 : static const OString aPngMarker( "PNG" );
684 6 : static const OUString aJpegFile( "DUMMY.JPEG" );
685 6 : static const OUString aPbmFile( "DUMMY.PBM" );
686 6 : static const OUString aPpmFile( "DUMMY.PPM" );
687 6 : static const OUString aPngFile( "DUMMY.PNG" );
688 :
689 6 : OString aToken = readNextToken();
690 6 : const sal_Int32 nImageSize( readInt32() );
691 :
692 12 : OUString aFileName;
693 6 : if( aToken == aPngMarker )
694 0 : aFileName = aPngFile;
695 6 : else if( aToken == aJpegMarker )
696 6 : 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 12 : uno::Sequence<sal_Int8> aDataSequence(nImageSize);
706 6 : readBinaryData( aDataSequence );
707 :
708 12 : uno::Sequence< uno::Any > aStreamCreationArgs(1);
709 6 : aStreamCreationArgs[0] <<= aDataSequence;
710 :
711 12 : uno::Reference< uno::XComponentContext > xContext( m_xContext, uno::UNO_SET_THROW );
712 12 : uno::Reference< lang::XMultiComponentFactory > xFactory( xContext->getServiceManager(), uno::UNO_SET_THROW );
713 6 : uno::Reference< io::XInputStream > xDataStream( xFactory->createInstanceWithArgumentsAndContext(
714 : OUString( "com.sun.star.io.SequenceInputStream" ),
715 12 : aStreamCreationArgs, m_xContext ), uno::UNO_QUERY_THROW );
716 :
717 6 : uno::Sequence<beans::PropertyValue> aSequence(3);
718 12 : aSequence[0] = beans::PropertyValue( OUString("URL"),
719 : 0,
720 : uno::makeAny(aFileName),
721 6 : beans::PropertyState_DIRECT_VALUE );
722 12 : aSequence[1] = beans::PropertyValue( OUString("InputStream"),
723 : 0,
724 : uno::makeAny( xDataStream ),
725 6 : beans::PropertyState_DIRECT_VALUE );
726 12 : aSequence[2] = beans::PropertyValue( OUString("InputSequence"),
727 : 0,
728 : uno::makeAny(aDataSequence),
729 6 : beans::PropertyState_DIRECT_VALUE );
730 :
731 12 : return aSequence;
732 : }
733 :
734 6 : void Parser::readImage()
735 : {
736 : sal_Int32 nWidth, nHeight,nMaskColors;
737 6 : readInt32(nWidth);
738 6 : readInt32(nHeight);
739 6 : readInt32(nMaskColors);
740 :
741 6 : uno::Sequence<beans::PropertyValue> aImg( readImageImpl() );
742 :
743 6 : 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 6 : m_pSink->drawImage( aImg );
765 6 : }
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 6 : void Parser::readLink()
778 : {
779 6 : geometry::RealRectangle2D aBounds;
780 6 : readDouble(aBounds.X1);
781 6 : readDouble(aBounds.Y1);
782 6 : readDouble(aBounds.X2);
783 6 : readDouble(aBounds.Y2);
784 :
785 6 : m_pSink->hyperLink( aBounds,
786 : OStringToOUString( lcl_unescapeLineFeeds(
787 : m_aLine.copy(m_nCharIndex) ),
788 6 : RTL_TEXTENCODING_UTF8 ) );
789 : // name gobbles up rest of line
790 6 : m_nCharIndex = -1;
791 6 : }
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 1212 : 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 1212 : m_nNextToken = 0; m_nCharIndex = 0; m_aLine = rLine;
827 1212 : uno::Reference<rendering::XPolyPolygon2D> xPoly;
828 2424 : const OString& rCmd = readNextToken();
829 : const hash_entry* pEntry = PdfKeywordHash::in_word_set( rCmd.getStr(),
830 1212 : rCmd.getLength() );
831 : OSL_ASSERT(pEntry);
832 1212 : switch( pEntry->eKey )
833 : {
834 : case CLIPPATH:
835 6 : m_pSink->intersectClip(readPath()); break;
836 : case DRAWCHAR:
837 624 : readChar(); break;
838 : case DRAWIMAGE:
839 6 : readImage(); break;
840 : case DRAWLINK:
841 6 : 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 6 : m_pSink->endPage(); break;
850 : case ENDTEXTOBJECT:
851 66 : m_pSink->endText(); break;
852 : case EOCLIPPATH:
853 6 : m_pSink->intersectEoClip(readPath()); break;
854 : case EOFILLPATH:
855 6 : m_pSink->eoFillPath(readPath()); break;
856 : case FILLPATH:
857 0 : m_pSink->fillPath(readPath()); break;
858 : case RESTORESTATE:
859 96 : m_pSink->popState(); break;
860 : case SAVESTATE:
861 96 : m_pSink->pushState(); break;
862 : case SETPAGENUM:
863 6 : m_pSink->setPageNum( readInt32() ); break;
864 : case STARTPAGE:
865 : {
866 6 : const double nWidth ( readDouble() );
867 6 : const double nHeight( readDouble() );
868 6 : m_pSink->startPage( geometry::RealSize2D( nWidth, nHeight ) );
869 6 : break;
870 : }
871 : case STROKEPATH:
872 12 : m_pSink->strokePath(readPath()); break;
873 : case UPDATECTM:
874 12 : readTransformation(); break;
875 : case UPDATEFILLCOLOR:
876 84 : m_pSink->setFillColor( readColor() ); break;
877 : case UPDATEFLATNESS:
878 6 : m_pSink->setFlatness( readDouble( ) ); break;
879 : case UPDATEFONT:
880 66 : readFont(); break;
881 : case UPDATELINECAP:
882 18 : readLineCap(); break;
883 : case UPDATELINEDASH:
884 12 : readLineDash(); break;
885 : case UPDATELINEJOIN:
886 18 : readLineJoin(); break;
887 : case UPDATELINEWIDTH:
888 24 : m_pSink->setLineWidth( readDouble() );break;
889 : case UPDATEMITERLIMIT:
890 6 : m_pSink->setMiterLimit( readDouble() ); break;
891 : case UPDATESTROKECOLOR:
892 24 : 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 1212 : SAL_WARN_IF(m_nCharIndex!=-1, "sdext.pdfimport", "leftover scanner input");
906 1212 : }
907 :
908 1218 : oslFileError readLine( oslFileHandle pFile, OStringBuffer& line )
909 : {
910 : OSL_PRECOND( line.isEmpty(), "line buf not empty" );
911 :
912 : // TODO(P3): read larger chunks
913 1218 : sal_Char aChar('\n');
914 : sal_uInt64 nBytesRead;
915 : oslFileError nRes;
916 :
917 : // skip garbage \r \n at start of line
918 3654 : while( osl_File_E_None == (nRes=osl_readFile(pFile, &aChar, 1, &nBytesRead)) &&
919 2430 : nBytesRead == 1 &&
920 2424 : (aChar == '\n' || aChar == '\r') ) ;
921 :
922 1218 : if( aChar != '\n' && aChar != '\r' )
923 1212 : line.append( aChar );
924 :
925 165066 : while( osl_File_E_None == (nRes=osl_readFile(pFile, &aChar, 1, &nBytesRead)) &&
926 163842 : nBytesRead == 1 && aChar != '\n' && aChar != '\r' )
927 : {
928 80706 : line.append( aChar );
929 : }
930 :
931 1218 : return nRes;
932 : }
933 :
934 : } // namespace
935 :
936 6 : 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 6 : bool bSuccess = false;
944 6 : OString aPDFFile;
945 6 : aPDFFile = OUStringToOString( i_rPath, osl_getThreadTextEncoding() );
946 :
947 12 : pdfparse::PDFReader aParser;
948 12 : boost::scoped_ptr<pdfparse::PDFEntry> pEntry( aParser.read( aPDFFile.getStr() ));
949 6 : if( pEntry )
950 : {
951 6 : pdfparse::PDFFile* pPDFFile = dynamic_cast<pdfparse::PDFFile*>(pEntry.get());
952 6 : if( pPDFFile )
953 : {
954 6 : o_rIsEncrypted = pPDFFile->isEncrypted();
955 6 : 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 6 : bSuccess = true;
1005 : }
1006 : }
1007 12 : return bSuccess;
1008 : }
1009 :
1010 6 : 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 : {
1016 : OSL_ASSERT(rSink);
1017 :
1018 6 : OUString aSysUPath;
1019 6 : if( osl_getSystemPathFromFileURL( rURL.pData, &aSysUPath.pData ) != osl_File_E_None )
1020 : {
1021 : SAL_WARN(
1022 : "sdext.pdfimport",
1023 : "getSystemPathFromFileURL(" << rURL << ") failed");
1024 0 : return false;
1025 : }
1026 12 : OUString aDocName( rURL.copy( rURL.lastIndexOf( '/' )+1 ) );
1027 :
1028 : // check for encryption, if necessary get password
1029 12 : OUString aPwd( rPwd );
1030 6 : bool bIsEncrypted = false;
1031 6 : if( checkEncryption( aSysUPath, xIHdl, aPwd, bIsEncrypted, aDocName ) == false )
1032 : {
1033 : SAL_INFO(
1034 : "sdext.pdfimport",
1035 : "checkEncryption(" << aSysUPath << ") failed");
1036 0 : return false;
1037 : }
1038 :
1039 : // Determine xpdfimport executable URL:
1040 12 : OUString converterURL("$BRAND_BASE_DIR/" LIBO_BIN_FOLDER "/xpdfimport");
1041 6 : rtl::Bootstrap::expandMacros(converterURL); //TODO: detect failure
1042 :
1043 : // Determine pathname of xpdfimport_err.pdf:
1044 12 : OUString errPathname("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/xpdfimport/xpdfimport_err.pdf");
1045 6 : rtl::Bootstrap::expandMacros(errPathname); //TODO: detect failure
1046 6 : if (osl::FileBase::getSystemPathFromFileURL(errPathname, errPathname)
1047 : != osl::FileBase::E_None)
1048 : {
1049 : SAL_WARN(
1050 : "sdext.pdfimport",
1051 : "getSystemPathFromFileURL(" << errPathname << ") failed");
1052 0 : return false;
1053 : }
1054 :
1055 : // spawn separate process to keep LGPL/GPL code apart.
1056 :
1057 6 : rtl_uString* args[] = { aSysUPath.pData, errPathname.pData };
1058 6 : sal_Int32 nArgs = 2;
1059 :
1060 : oslProcess aProcess;
1061 6 : oslFileHandle pIn = NULL;
1062 6 : oslFileHandle pOut = NULL;
1063 6 : oslFileHandle pErr = NULL;
1064 6 : oslSecurity pSecurity = osl_getCurrentSecurity ();
1065 : oslProcessError eErr =
1066 : osl_executeProcess_WithRedirectedIO(converterURL.pData,
1067 : args,
1068 : nArgs,
1069 : osl_Process_SEARCHPATH|osl_Process_HIDDEN,
1070 : pSecurity,
1071 : 0, 0, 0,
1072 6 : &aProcess, &pIn, &pOut, &pErr);
1073 6 : osl_freeSecurityHandle(pSecurity);
1074 :
1075 6 : bool bRet=true;
1076 : try
1077 : {
1078 6 : if( eErr!=osl_Process_E_None )
1079 : {
1080 : SAL_WARN(
1081 : "sdext.pdfimport",
1082 : "executeProcess of " << converterURL << " failed with "
1083 : << +eErr);
1084 0 : return false;
1085 : }
1086 :
1087 6 : if( pIn )
1088 : {
1089 6 : OStringBuffer aBuf(256);
1090 6 : if( bIsEncrypted )
1091 0 : aBuf.append( OUStringToOString( aPwd, RTL_TEXTENCODING_ISO_8859_1 ) );
1092 6 : aBuf.append( '\n' );
1093 :
1094 6 : sal_uInt64 nWritten = 0;
1095 6 : osl_writeFile( pIn, aBuf.getStr(), sal_uInt64(aBuf.getLength()), &nWritten );
1096 : }
1097 :
1098 6 : if( pOut && pErr )
1099 : {
1100 : // read results of PDF parser. One line - one call to
1101 : // OutputDev. stderr is used for alternate streams, like
1102 : // embedded fonts and bitmaps
1103 6 : Parser aParser(rSink,pErr,xContext);
1104 12 : OStringBuffer line;
1105 1224 : while( osl_File_E_None == readLine(pOut, line) && !line.isEmpty() )
1106 1218 : aParser.parseLine(line.makeStringAndClear());
1107 : }
1108 : }
1109 0 : catch( uno::Exception& )
1110 : {
1111 : // crappy C file interface. need manual resource dealloc
1112 0 : bRet = false;
1113 : }
1114 :
1115 6 : if( pIn )
1116 6 : osl_closeFile(pIn);
1117 6 : if( pOut )
1118 6 : osl_closeFile(pOut);
1119 6 : if( pErr )
1120 6 : osl_closeFile(pErr);
1121 6 : eErr = osl_joinProcess(aProcess);
1122 6 : if (eErr == osl_Process_E_None)
1123 : {
1124 : oslProcessInfo info;
1125 6 : info.Size = sizeof info;
1126 6 : eErr = osl_getProcessInfo(aProcess, osl_Process_EXITCODE, &info);
1127 6 : if (eErr == osl_Process_E_None)
1128 : {
1129 6 : if (info.Code != 0)
1130 : {
1131 : SAL_WARN(
1132 : "sdext.pdfimport",
1133 : "getProcessInfo of " << converterURL
1134 : << " failed with exit code " << info.Code);
1135 0 : bRet = false;
1136 : }
1137 : }
1138 : else
1139 : {
1140 : SAL_WARN(
1141 : "sdext.pdfimport",
1142 : "getProcessInfo of " << converterURL << " failed with "
1143 : << +eErr);
1144 0 : bRet = false;
1145 : }
1146 : }
1147 : else
1148 : {
1149 : SAL_WARN(
1150 : "sdext.pdfimport",
1151 : "joinProcess of " << converterURL << " failed with " << +eErr);
1152 0 : bRet = false;
1153 : }
1154 6 : osl_freeProcessHandle(aProcess);
1155 12 : return bRet;
1156 : }
1157 :
1158 :
1159 0 : bool xpdf_ImportFromStream( const uno::Reference< io::XInputStream >& xInput,
1160 : const ContentSinkSharedPtr& rSink,
1161 : const uno::Reference<task::XInteractionHandler >& xIHdl,
1162 : const OUString& rPwd,
1163 : const uno::Reference< uno::XComponentContext >& xContext )
1164 : {
1165 : OSL_ASSERT(xInput.is());
1166 : OSL_ASSERT(rSink);
1167 :
1168 : // convert XInputStream to local temp file
1169 0 : oslFileHandle aFile = NULL;
1170 0 : OUString aURL;
1171 0 : if( osl_createTempFile( NULL, &aFile, &aURL.pData ) != osl_File_E_None )
1172 0 : return false;
1173 :
1174 : // copy content, buffered...
1175 0 : const sal_uInt32 nBufSize = 4096;
1176 0 : uno::Sequence<sal_Int8> aBuf( nBufSize );
1177 0 : sal_uInt64 nBytes = 0;
1178 0 : sal_uInt64 nWritten = 0;
1179 0 : bool bSuccess = true;
1180 0 : do
1181 : {
1182 : try
1183 : {
1184 0 : nBytes = xInput->readBytes( aBuf, nBufSize );
1185 : }
1186 0 : catch( com::sun::star::uno::Exception& )
1187 : {
1188 0 : osl_closeFile( aFile );
1189 0 : throw;
1190 : }
1191 0 : if( nBytes > 0 )
1192 : {
1193 0 : osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
1194 0 : if( nWritten != nBytes )
1195 : {
1196 0 : bSuccess = false;
1197 0 : break;
1198 : }
1199 : }
1200 : }
1201 : while( nBytes == nBufSize );
1202 :
1203 0 : osl_closeFile( aFile );
1204 :
1205 0 : if ( bSuccess )
1206 0 : bSuccess = xpdf_ImportFromFile( aURL, rSink, xIHdl, rPwd, xContext );
1207 0 : osl_removeFile( aURL.pData );
1208 :
1209 0 : return bSuccess;
1210 : }
1211 :
1212 6 : }
1213 :
1214 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|