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 <pdfparse.hxx>
31 : :
32 : : #include <rtl/strbuf.hxx>
33 : : #include <rtl/ustring.hxx>
34 : : #include <rtl/ustrbuf.hxx>
35 : : #include <rtl/alloc.h>
36 : : #include <rtl/digest.h>
37 : : #include <rtl/cipher.h>
38 : : #include <rtl/memory.h>
39 : : #ifdef SYSTEM_ZLIB
40 : : #include "zlib.h"
41 : : #else
42 : : #include <zlib/zlib.h>
43 : : #endif
44 : :
45 : : #include <math.h>
46 : : #include <map>
47 : :
48 : : #include <stdio.h>
49 : :
50 : : using ::rtl::OUString;
51 : : using ::rtl::OString;
52 : : using ::rtl::OStringHash;
53 : : using ::rtl::OStringBuffer;
54 : :
55 : :
56 : : namespace pdfparse
57 : : {
58 : :
59 : : struct EmitImplData
60 : : {
61 : : // xref table: maps object number to a pair of (generation, buffer offset)
62 : : typedef std::map< unsigned int, std::pair< unsigned int, unsigned int > > XRefTable;
63 : : XRefTable m_aXRefTable;
64 : : // container of all indirect objects (usually a PDFFile*)
65 : : const PDFContainer* m_pObjectContainer;
66 : : unsigned int m_nDecryptObject;
67 : : unsigned int m_nDecryptGeneration;
68 : :
69 : : // returns true if the xref table was updated
70 : 0 : bool insertXref( unsigned int nObject, unsigned int nGeneration, unsigned int nOffset )
71 : : {
72 [ # # ]: 0 : XRefTable::iterator it = m_aXRefTable.find( nObject );
73 [ # # ][ # # ]: 0 : if( it == m_aXRefTable.end() )
74 : : {
75 : : // new entry
76 [ # # ][ # # ]: 0 : m_aXRefTable[ nObject ] = std::pair<unsigned int, unsigned int>(nGeneration,nOffset);
77 : 0 : return true;
78 : : }
79 : : // update old entry, if generation number is higher
80 [ # # ][ # # ]: 0 : if( it->second.first < nGeneration )
81 : : {
82 [ # # ][ # # ]: 0 : it->second = std::pair<unsigned int, unsigned int>(nGeneration,nOffset);
83 : 0 : return true;
84 : : }
85 : 0 : return false;
86 : : }
87 : :
88 : 0 : EmitImplData( const PDFContainer* pTopContainer ) :
89 : : m_pObjectContainer( pTopContainer ),
90 : : m_nDecryptObject( 0 ),
91 : 0 : m_nDecryptGeneration( 0 )
92 : 0 : {}
93 : 0 : ~EmitImplData() {}
94 : 0 : bool decrypt( const sal_uInt8* pInBuffer, sal_uInt32 nLen, sal_uInt8* pOutBuffer,
95 : : unsigned int nObject, unsigned int nGeneration ) const
96 : : {
97 [ # # ]: 0 : const PDFFile* pFile = dynamic_cast<const PDFFile*>(m_pObjectContainer);
98 [ # # ]: 0 : return pFile ? pFile->decrypt( pInBuffer, nLen, pOutBuffer, nObject, nGeneration ) : false;
99 : : }
100 : :
101 : 0 : void setDecryptObject( unsigned int nObject, unsigned int nGeneration )
102 : : {
103 : 0 : m_nDecryptObject = nObject;
104 : 0 : m_nDecryptGeneration = nGeneration;
105 : 0 : }
106 : : };
107 : :
108 : : }
109 : :
110 : : using namespace pdfparse;
111 : :
112 : 0 : EmitContext::EmitContext( const PDFContainer* pTop ) :
113 : : m_bDeflate( false ),
114 : : m_bDecrypt( false ),
115 : 0 : m_pImplData( NULL )
116 : : {
117 [ # # ]: 0 : if( pTop )
118 [ # # ]: 0 : m_pImplData = new EmitImplData( pTop );
119 : 0 : }
120 : :
121 : 0 : EmitContext::~EmitContext()
122 : : {
123 [ # # ]: 0 : delete m_pImplData;
124 [ # # ]: 0 : }
125 : :
126 : 5580 : PDFEntry::~PDFEntry()
127 : : {
128 [ - + ]: 5580 : }
129 : :
130 : 0 : EmitImplData* PDFEntry::getEmitData( EmitContext& rContext ) const
131 : : {
132 : 0 : return rContext.m_pImplData;
133 : : }
134 : :
135 : 0 : void PDFEntry::setEmitData( EmitContext& rContext, EmitImplData* pNewEmitData ) const
136 : : {
137 [ # # ][ # # ]: 0 : if( rContext.m_pImplData && rContext.m_pImplData != pNewEmitData )
138 [ # # ]: 0 : delete rContext.m_pImplData;
139 : 0 : rContext.m_pImplData = pNewEmitData;
140 : 0 : }
141 : :
142 : 4440 : PDFValue::~PDFValue()
143 : : {
144 [ - + ]: 4440 : }
145 : :
146 : 15 : PDFComment::~PDFComment()
147 : : {
148 [ - + ]: 30 : }
149 : :
150 : 0 : bool PDFComment::emit( EmitContext& rWriteContext ) const
151 : : {
152 : 0 : return rWriteContext.write( m_aComment.getStr(), m_aComment.getLength() );
153 : : }
154 : :
155 : 0 : PDFEntry* PDFComment::clone() const
156 : : {
157 [ # # ]: 0 : return new PDFComment( m_aComment );
158 : : }
159 : :
160 : 2430 : PDFName::~PDFName()
161 : : {
162 [ - + ]: 4860 : }
163 : :
164 : 0 : bool PDFName::emit( EmitContext& rWriteContext ) const
165 : : {
166 [ # # ]: 0 : if( ! rWriteContext.write( " /", 2 ) )
167 : 0 : return false;
168 : 0 : return rWriteContext.write( m_aName.getStr(), m_aName.getLength() );
169 : : }
170 : :
171 : 0 : PDFEntry* PDFName::clone() const
172 : : {
173 [ # # ]: 0 : return new PDFName( m_aName );
174 : : }
175 : :
176 : 0 : OUString PDFName::getFilteredName() const
177 : : {
178 : 0 : OStringBuffer aFilter( m_aName.getLength() );
179 : 0 : const sal_Char* pStr = m_aName.getStr();
180 : 0 : unsigned int nLen = m_aName.getLength();
181 [ # # ]: 0 : for( unsigned int i = 0; i < nLen; i++ )
182 : : {
183 [ # # ][ # # ]: 0 : if( (i < nLen - 3) && pStr[i] == '#' )
184 : : {
185 : 0 : sal_Char rResult = 0;
186 : 0 : i++;
187 [ # # ][ # # ]: 0 : if( pStr[i] >= '0' && pStr[i] <= '9' )
188 : 0 : rResult = sal_Char( pStr[i]-'0' ) << 4;
189 [ # # ][ # # ]: 0 : else if( pStr[i] >= 'a' && pStr[i] <= 'f' )
190 : 0 : rResult = sal_Char( pStr[i]-'a' + 10 ) << 4;
191 [ # # ][ # # ]: 0 : else if( pStr[i] >= 'A' && pStr[i] <= 'F' )
192 : 0 : rResult = sal_Char( pStr[i]-'A' + 10 ) << 4;
193 : 0 : i++;
194 [ # # ][ # # ]: 0 : if( pStr[i] >= '0' && pStr[i] <= '9' )
195 : 0 : rResult |= sal_Char( pStr[i]-'0' );
196 [ # # ][ # # ]: 0 : else if( pStr[i] >= 'a' && pStr[i] <= 'f' )
197 : 0 : rResult |= sal_Char( pStr[i]-'a' + 10 );
198 [ # # ][ # # ]: 0 : else if( pStr[i] >= 'A' && pStr[i] <= 'F' )
199 : 0 : rResult |= sal_Char( pStr[i]-'A' + 10 );
200 [ # # ]: 0 : aFilter.append( rResult );
201 : : }
202 : : else
203 [ # # ]: 0 : aFilter.append( pStr[i] );
204 : : }
205 [ # # ]: 0 : return OStringToOUString( aFilter.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
206 : : }
207 : :
208 : 90 : PDFString::~PDFString()
209 : : {
210 [ - + ]: 180 : }
211 : :
212 : 0 : bool PDFString::emit( EmitContext& rWriteContext ) const
213 : : {
214 [ # # ]: 0 : if( ! rWriteContext.write( " ", 1 ) )
215 : 0 : return false;
216 : 0 : EmitImplData* pEData = getEmitData( rWriteContext );
217 [ # # ][ # # ]: 0 : if( rWriteContext.m_bDecrypt && pEData && pEData->m_nDecryptObject )
[ # # ]
218 : : {
219 [ # # ]: 0 : OString aFiltered( getFilteredString() );
220 : : // decrypt inplace (evil since OString is supposed to be const
221 : : // however in this case we know that getFilteredString returned a singular string instance
222 : 0 : pEData->decrypt( (sal_uInt8*)aFiltered.getStr(), aFiltered.getLength(),
223 : 0 : (sal_uInt8*)aFiltered.getStr(),
224 [ # # ]: 0 : pEData->m_nDecryptObject, pEData->m_nDecryptGeneration );
225 : : // check for string or hex string
226 : 0 : const sal_Char* pStr = aFiltered.getStr();
227 [ # # ][ # # ]: 0 : if( aFiltered.getLength() > 1 &&
[ # # ][ # # ]
[ # # ][ # # ]
228 : 0 : ( ((unsigned char)pStr[0] == 0xff && (unsigned char)pStr[1] == 0xfe) ||
229 : 0 : ((unsigned char)pStr[0] == 0xfe && (unsigned char)pStr[1] == 0xff) ) )
230 : : {
231 : : static const char pHexTab[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
232 : : '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
233 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( "<", 1 ) )
234 : 0 : return false;
235 [ # # ]: 0 : for( sal_Int32 i = 0; i < aFiltered.getLength(); i++ )
236 : : {
237 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( pHexTab + ((sal_uInt32(pStr[i]) >> 4) & 0x0f), 1 ) )
238 : 0 : return false;
239 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( pHexTab + (sal_uInt32(pStr[i]) & 0x0f), 1 ) )
240 : 0 : return false;
241 : : }
242 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( ">", 1 ) )
243 : 0 : return false;
244 : : }
245 : : else
246 : : {
247 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( "(", 1 ) )
248 : 0 : return false;
249 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( aFiltered.getStr(), aFiltered.getLength() ) )
250 : 0 : return false;
251 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( ")", 1 ) )
252 : 0 : return false;
253 : : }
254 : 0 : return true;
255 : : }
256 : 0 : return rWriteContext.write( m_aString.getStr(), m_aString.getLength() );
257 : : }
258 : :
259 : 0 : PDFEntry* PDFString::clone() const
260 : : {
261 [ # # ]: 0 : return new PDFString( m_aString );
262 : : }
263 : :
264 : 15 : OString PDFString::getFilteredString() const
265 : : {
266 : 15 : int nLen = m_aString.getLength();
267 : 15 : OStringBuffer aBuf( nLen );
268 : :
269 : 15 : const sal_Char* pStr = m_aString.getStr();
270 [ - + ]: 15 : if( *pStr == '(' )
271 : : {
272 : 0 : const sal_Char* pRun = pStr+1;
273 [ # # ]: 0 : while( pRun - pStr < nLen-1 )
274 : : {
275 [ # # ]: 0 : if( *pRun == '\\' )
276 : : {
277 : 0 : pRun++;
278 [ # # ]: 0 : if( pRun - pStr < nLen )
279 : : {
280 : 0 : sal_Char aEsc = 0;
281 [ # # ]: 0 : if( *pRun == 'n' )
282 : 0 : aEsc = '\n';
283 [ # # ]: 0 : else if( *pRun == 'r' )
284 : 0 : aEsc = '\r';
285 [ # # ]: 0 : else if( *pRun == 't' )
286 : 0 : aEsc = '\t';
287 [ # # ]: 0 : else if( *pRun == 'b' )
288 : 0 : aEsc = '\b';
289 [ # # ]: 0 : else if( *pRun == 'f' )
290 : 0 : aEsc = '\f';
291 [ # # ]: 0 : else if( *pRun == '(' )
292 : 0 : aEsc = '(';
293 [ # # ]: 0 : else if( *pRun == ')' )
294 : 0 : aEsc = ')';
295 [ # # ]: 0 : else if( *pRun == '\\' )
296 : 0 : aEsc = '\\';
297 [ # # ]: 0 : else if( *pRun == '\n' )
298 : : {
299 : 0 : pRun++;
300 : 0 : continue;
301 : : }
302 [ # # ]: 0 : else if( *pRun == '\r' )
303 : : {
304 : 0 : pRun++;
305 [ # # ]: 0 : if( *pRun == '\n' )
306 : 0 : pRun++;
307 : 0 : continue;
308 : : }
309 : : else
310 : : {
311 : 0 : int i = 0;
312 [ # # ][ # # ]: 0 : while( i++ < 3 && *pRun >= '0' && *pRun <= '7' )
[ # # ][ # # ]
313 : 0 : aEsc = 8*aEsc + (*pRun++ - '0');
314 : : // move pointer back to last character of octal sequence
315 : 0 : pRun--;
316 : : }
317 [ # # ]: 0 : aBuf.append( aEsc );
318 : : }
319 : : }
320 : : else
321 [ # # ]: 0 : aBuf.append( *pRun );
322 : : // move pointer to next character
323 : 0 : pRun++;
324 : : }
325 : : }
326 [ + - ]: 15 : else if( *pStr == '<' )
327 : : {
328 : 15 : const sal_Char* pRun = pStr+1;
329 [ + + ][ + - ]: 255 : while( *pRun != '>' && pRun - pStr < nLen )
[ + + ]
330 : : {
331 : 240 : sal_Char rResult = 0;
332 [ + - ][ + + ]: 240 : if( *pRun >= '0' && *pRun <= '9' )
333 : 165 : rResult = sal_Char( *pRun-'0' ) << 4;
334 [ - + ][ # # ]: 75 : else if( *pRun >= 'a' && *pRun <= 'f' )
335 : 0 : rResult = sal_Char( *pRun-'a' + 10 ) << 4;
336 [ + - ][ + - ]: 75 : else if( *pRun >= 'A' && *pRun <= 'F' )
337 : 75 : rResult = sal_Char( *pRun-'A' + 10 ) << 4;
338 : 240 : pRun++;
339 [ + - ][ + - ]: 240 : if( *pRun != '>' && pRun - pStr < nLen )
340 : : {
341 [ + - ][ + + ]: 240 : if( *pRun >= '0' && *pRun <= '9' )
342 : 180 : rResult |= sal_Char( *pRun-'0' );
343 [ - + ][ # # ]: 60 : else if( *pRun >= 'a' && *pRun <= 'f' )
344 : 0 : rResult |= sal_Char( *pRun-'a' + 10 );
345 [ + - ][ + - ]: 60 : else if( *pRun >= 'A' && *pRun <= 'F' )
346 : 240 : rResult |= sal_Char( *pRun-'A' + 10 );
347 : : }
348 : 240 : pRun++;
349 [ + - ]: 240 : aBuf.append( rResult );
350 : : }
351 : : }
352 : :
353 : 15 : return aBuf.makeStringAndClear();
354 : : }
355 : :
356 : 1455 : PDFNumber::~PDFNumber()
357 : : {
358 [ - + ]: 2910 : }
359 : :
360 : 0 : bool PDFNumber::emit( EmitContext& rWriteContext ) const
361 : : {
362 : 0 : rtl::OStringBuffer aBuf( 32 );
363 [ # # ]: 0 : aBuf.append( ' ' );
364 : :
365 : 0 : double fValue = m_fValue;
366 : 0 : bool bNeg = false;
367 : 0 : int nPrecision = 5;
368 [ # # ]: 0 : if( fValue < 0.0 )
369 : : {
370 : 0 : bNeg = true;
371 : 0 : fValue=-fValue;
372 : : }
373 : :
374 : 0 : sal_Int64 nInt = (sal_Int64)fValue;
375 : 0 : fValue -= (double)nInt;
376 : : // optimizing hardware may lead to a value of 1.0 after the subtraction
377 [ # # ][ # # ]: 0 : if( fValue == 1.0 || log10( 1.0-fValue ) <= -nPrecision )
[ # # ]
378 : : {
379 : 0 : nInt++;
380 : 0 : fValue = 0.0;
381 : : }
382 : 0 : sal_Int64 nFrac = 0;
383 [ # # ]: 0 : if( fValue )
384 : : {
385 : 0 : fValue *= pow( 10.0, (double)nPrecision );
386 : 0 : nFrac = (sal_Int64)fValue;
387 : : }
388 [ # # ][ # # ]: 0 : if( bNeg && ( nInt || nFrac ) )
[ # # ]
389 [ # # ]: 0 : aBuf.append( '-' );
390 [ # # ]: 0 : aBuf.append( nInt );
391 [ # # ]: 0 : if( nFrac )
392 : : {
393 : : int i;
394 [ # # ]: 0 : aBuf.append( '.' );
395 : 0 : sal_Int64 nBound = (sal_Int64)(pow( 10.0, nPrecision - 1.0 )+0.5);
396 [ # # ][ # # ]: 0 : for ( i = 0; ( i < nPrecision ) && nFrac; i++ )
[ # # ]
397 : : {
398 : 0 : sal_Int64 nNumb = nFrac / nBound;
399 : 0 : nFrac -= nNumb * nBound;
400 [ # # ]: 0 : aBuf.append( nNumb );
401 : 0 : nBound /= 10;
402 : : }
403 : : }
404 : :
405 [ # # ]: 0 : return rWriteContext.write( aBuf.getStr(), aBuf.getLength() );
406 : : }
407 : :
408 : 0 : PDFEntry* PDFNumber::clone() const
409 : : {
410 [ # # ]: 0 : return new PDFNumber( m_fValue );
411 : : }
412 : :
413 : :
414 : 15 : PDFBool::~PDFBool()
415 : : {
416 [ - + ]: 30 : }
417 : :
418 : 0 : bool PDFBool::emit( EmitContext& rWriteContext ) const
419 : : {
420 [ # # ]: 0 : return m_bValue ? rWriteContext.write( " true", 5 ) : rWriteContext.write( " false", 6 );
421 : : }
422 : :
423 : 0 : PDFEntry* PDFBool::clone() const
424 : : {
425 [ # # ]: 0 : return new PDFBool( m_bValue );
426 : : }
427 : :
428 : 30 : PDFNull::~PDFNull()
429 : : {
430 [ - + ]: 60 : }
431 : :
432 : 0 : bool PDFNull::emit( EmitContext& rWriteContext ) const
433 : : {
434 : 0 : return rWriteContext.write( " null", 5 );
435 : : }
436 : :
437 : 0 : PDFEntry* PDFNull::clone() const
438 : : {
439 [ # # ]: 0 : return new PDFNull();
440 : : }
441 : :
442 : :
443 : 420 : PDFObjectRef::~PDFObjectRef()
444 : : {
445 [ - + ]: 840 : }
446 : :
447 : 0 : bool PDFObjectRef::emit( EmitContext& rWriteContext ) const
448 : : {
449 : 0 : OStringBuffer aBuf( 16 );
450 [ # # ]: 0 : aBuf.append( ' ' );
451 [ # # ]: 0 : aBuf.append( sal_Int32( m_nNumber ) );
452 [ # # ]: 0 : aBuf.append( ' ' );
453 [ # # ]: 0 : aBuf.append( sal_Int32( m_nGeneration ) );
454 [ # # ]: 0 : aBuf.append( " R", 2 );
455 [ # # ]: 0 : return rWriteContext.write( aBuf.getStr(), aBuf.getLength() );
456 : : }
457 : :
458 : 0 : PDFEntry* PDFObjectRef::clone() const
459 : : {
460 [ # # ]: 0 : return new PDFObjectRef( m_nNumber, m_nGeneration );
461 : : }
462 : :
463 : 1005 : PDFContainer::~PDFContainer()
464 : : {
465 : 1005 : int nEle = m_aSubElements.size();
466 [ + + ]: 6570 : for( int i = 0; i < nEle; i++ )
467 [ + - ][ + - ]: 5565 : delete m_aSubElements[i];
468 [ - + ]: 1005 : }
469 : :
470 : 0 : bool PDFContainer::emitSubElements( EmitContext& rWriteContext ) const
471 : : {
472 : 0 : int nEle = m_aSubElements.size();
473 [ # # ]: 0 : for( int i = 0; i < nEle; i++ )
474 : : {
475 [ # # ]: 0 : if( rWriteContext.m_bDecrypt )
476 : : {
477 [ # # ]: 0 : const PDFName* pName = dynamic_cast<PDFName*>(m_aSubElements[i]);
478 [ # # ][ # # ]: 0 : if (pName && pName->m_aName.equalsL(RTL_CONSTASCII_STRINGPARAM("Encrypt")))
[ # # ]
479 : : {
480 : 0 : i++;
481 : 0 : continue;
482 : : }
483 : : }
484 [ # # ]: 0 : if( ! m_aSubElements[i]->emit( rWriteContext ) )
485 : 0 : return false;
486 : : }
487 : 0 : return true;
488 : : }
489 : :
490 : 0 : void PDFContainer::cloneSubElements( std::vector<PDFEntry*>& rNewSubElements ) const
491 : : {
492 : 0 : int nEle = m_aSubElements.size();
493 [ # # ]: 0 : for( int i = 0; i < nEle; i++ )
494 [ # # ]: 0 : rNewSubElements.push_back( m_aSubElements[i]->clone() );
495 : 0 : }
496 : :
497 : 0 : PDFObject* PDFContainer::findObject( unsigned int nNumber, unsigned int nGeneration ) const
498 : : {
499 : 0 : unsigned int nEle = m_aSubElements.size();
500 [ # # ]: 0 : for( unsigned int i = 0; i < nEle; i++ )
501 : : {
502 [ # # ]: 0 : PDFObject* pObject = dynamic_cast<PDFObject*>(m_aSubElements[i]);
503 [ # # ][ # # ]: 0 : if( pObject &&
[ # # ]
504 : : pObject->m_nNumber == nNumber &&
505 : : pObject->m_nGeneration == nGeneration )
506 : : {
507 : 0 : return pObject;
508 : : }
509 : : }
510 : 0 : return NULL;
511 : : }
512 : :
513 : 225 : PDFArray::~PDFArray()
514 : : {
515 [ - + ]: 450 : }
516 : :
517 : 0 : bool PDFArray::emit( EmitContext& rWriteContext ) const
518 : : {
519 [ # # ]: 0 : if( ! rWriteContext.write( "[", 1 ) )
520 : 0 : return false;
521 [ # # ]: 0 : if( ! emitSubElements( rWriteContext ) )
522 : 0 : return false;
523 : 0 : return rWriteContext.write( "]", 1 );
524 : : }
525 : :
526 : 0 : PDFEntry* PDFArray::clone() const
527 : : {
528 [ # # ]: 0 : PDFArray* pNewAr = new PDFArray();
529 : 0 : cloneSubElements( pNewAr->m_aSubElements );
530 : 0 : return pNewAr;
531 : : }
532 : :
533 [ + - ]: 375 : PDFDict::~PDFDict()
534 : : {
535 [ - + ]: 750 : }
536 : :
537 : 0 : bool PDFDict::emit( EmitContext& rWriteContext ) const
538 : : {
539 [ # # ]: 0 : if( ! rWriteContext.write( "<<\n", 3 ) )
540 : 0 : return false;
541 [ # # ]: 0 : if( ! emitSubElements( rWriteContext ) )
542 : 0 : return false;
543 : 0 : return rWriteContext.write( "\n>>\n", 4 );
544 : : }
545 : :
546 : 0 : void PDFDict::insertValue( const OString& rName, PDFEntry* pValue )
547 : : {
548 [ # # ]: 0 : if( ! pValue )
549 [ # # ]: 0 : eraseValue( rName );
550 : :
551 [ # # ]: 0 : boost::unordered_map<OString,PDFEntry*,OStringHash>::iterator it = m_aMap.find( rName );
552 [ # # ][ # # ]: 0 : if( it == m_aMap.end() )
553 : : {
554 : : // new name/value, pair, append it
555 [ # # ][ # # ]: 0 : m_aSubElements.push_back( new PDFName( rName ) );
[ # # ]
556 [ # # ]: 0 : m_aSubElements.push_back( pValue );
557 : : }
558 : : else
559 : : {
560 : 0 : unsigned int nSub = m_aSubElements.size();
561 [ # # ]: 0 : for( unsigned int i = 0; i < nSub; i++ )
562 [ # # ][ # # ]: 0 : if( m_aSubElements[i] == it->second )
563 : 0 : m_aSubElements[i] = pValue;
564 [ # # ][ # # ]: 0 : delete it->second;
[ # # ]
565 : : }
566 [ # # ]: 0 : m_aMap[ rName ] = pValue;
567 : 0 : }
568 : :
569 : 0 : void PDFDict::eraseValue( const OString& rName )
570 : : {
571 : 0 : unsigned int nEle = m_aSubElements.size();
572 [ # # ]: 0 : for( unsigned int i = 0; i < nEle; i++ )
573 : : {
574 [ # # ]: 0 : PDFName* pName = dynamic_cast<PDFName*>(m_aSubElements[i]);
575 [ # # ][ # # ]: 0 : if( pName && pName->m_aName.equals( rName ) )
[ # # ]
576 : : {
577 [ # # ]: 0 : for( unsigned int j = i+1; j < nEle; j++ )
578 : : {
579 [ # # ][ # # ]: 0 : if( dynamic_cast<PDFComment*>(m_aSubElements[j]) == NULL )
[ # # ]
580 : : {
581 : : // free name and value
582 [ # # ]: 0 : delete m_aSubElements[j];
583 [ # # ]: 0 : delete m_aSubElements[i];
584 : : // remove subelements from vector
585 [ # # ][ # # ]: 0 : m_aSubElements.erase( m_aSubElements.begin()+j );
586 [ # # ][ # # ]: 0 : m_aSubElements.erase( m_aSubElements.begin()+i );
587 : 0 : buildMap();
588 : 0 : return;
589 : : }
590 : : }
591 : : }
592 : : }
593 : : }
594 : :
595 : 375 : PDFEntry* PDFDict::buildMap()
596 : : {
597 : : // clear map
598 : 375 : m_aMap.clear();
599 : : // build map
600 : 375 : unsigned int nEle = m_aSubElements.size();
601 : 375 : PDFName* pName = NULL;
602 [ + + ]: 3975 : for( unsigned int i = 0; i < nEle; i++ )
603 : : {
604 [ + - ][ + - ]: 3600 : if( dynamic_cast<PDFComment*>(m_aSubElements[i]) == NULL )
[ + - ]
605 : : {
606 [ + + ]: 3600 : if( pName )
607 : : {
608 : 1800 : m_aMap[ pName->m_aName ] = m_aSubElements[i];
609 : 1800 : pName = NULL;
610 : : }
611 [ - + ][ - + ]: 1800 : else if( (pName = dynamic_cast<PDFName*>(m_aSubElements[i])) == NULL )
612 : 0 : return m_aSubElements[i];
613 : : }
614 : : }
615 : 375 : return pName;
616 : : }
617 : :
618 : 0 : PDFEntry* PDFDict::clone() const
619 : : {
620 [ # # ]: 0 : PDFDict* pNewDict = new PDFDict();
621 : 0 : cloneSubElements( pNewDict->m_aSubElements );
622 : 0 : pNewDict->buildMap();
623 : 0 : return pNewDict;
624 : : }
625 : :
626 : 120 : PDFStream::~PDFStream()
627 : : {
628 [ - + ]: 240 : }
629 : :
630 : 0 : bool PDFStream::emit( EmitContext& rWriteContext ) const
631 : : {
632 : 0 : return rWriteContext.copyOrigBytes( m_nBeginOffset, m_nEndOffset-m_nBeginOffset );
633 : : }
634 : :
635 : 0 : PDFEntry* PDFStream::clone() const
636 : : {
637 [ # # ]: 0 : return new PDFStream( m_nBeginOffset, m_nEndOffset, NULL );
638 : : }
639 : :
640 : 0 : unsigned int PDFStream::getDictLength( const PDFContainer* pContainer ) const
641 : : {
642 [ # # ]: 0 : if( ! m_pDict )
643 : 0 : return 0;
644 : : // find /Length entry, can either be a direct or indirect number object
645 : : boost::unordered_map<OString,PDFEntry*,OStringHash>::const_iterator it =
646 [ # # ]: 0 : m_pDict->m_aMap.find( "Length" );
647 [ # # ][ # # ]: 0 : if( it == m_pDict->m_aMap.end() )
648 : 0 : return 0;
649 [ # # ][ # # ]: 0 : PDFNumber* pNum = dynamic_cast<PDFNumber*>(it->second);
650 [ # # ][ # # ]: 0 : if( ! pNum && pContainer )
651 : : {
652 [ # # ][ # # ]: 0 : PDFObjectRef* pRef = dynamic_cast<PDFObjectRef*>(it->second);
653 [ # # ]: 0 : if( pRef )
654 : : {
655 : 0 : int nEle = pContainer->m_aSubElements.size();
656 [ # # ][ # # ]: 0 : for( int i = 0; i < nEle && ! pNum; i++ )
[ # # ]
657 : : {
658 [ # # ]: 0 : PDFObject* pObj = dynamic_cast<PDFObject*>(pContainer->m_aSubElements[i]);
659 [ # # ][ # # ]: 0 : if( pObj &&
[ # # ]
660 : : pObj->m_nNumber == pRef->m_nNumber &&
661 : : pObj->m_nGeneration == pRef->m_nGeneration )
662 : : {
663 [ # # ]: 0 : if( pObj->m_pObject )
664 [ # # ]: 0 : pNum = dynamic_cast<PDFNumber*>(pObj->m_pObject);
665 : 0 : break;
666 : : }
667 : : }
668 : : }
669 : : }
670 [ # # ]: 0 : return pNum ? static_cast<unsigned int>(pNum->m_fValue) : 0;
671 : : }
672 : :
673 : 375 : PDFObject::~PDFObject()
674 : : {
675 [ - + ]: 750 : }
676 : :
677 : 0 : bool PDFObject::getDeflatedStream( char** ppStream, unsigned int* pBytes, const PDFContainer* pObjectContainer, EmitContext& rContext ) const
678 : : {
679 : 0 : bool bIsDeflated = false;
680 [ # # ][ # # ]: 0 : if( m_pStream && m_pStream->m_pDict &&
[ # # ]
681 : : m_pStream->m_nEndOffset > m_pStream->m_nBeginOffset+15
682 : : )
683 : : {
684 : 0 : unsigned int nOuterStreamLen = m_pStream->m_nEndOffset - m_pStream->m_nBeginOffset;
685 : 0 : *ppStream = static_cast<char*>(rtl_allocateMemory( nOuterStreamLen ));
686 [ # # ]: 0 : if( ! ppStream )
687 : : {
688 : 0 : *pBytes = 0;
689 : 0 : return false;
690 : : }
691 [ # # ]: 0 : unsigned int nRead = rContext.readOrigBytes( m_pStream->m_nBeginOffset, nOuterStreamLen, *ppStream );
692 [ # # ]: 0 : if( nRead != nOuterStreamLen )
693 : : {
694 : 0 : rtl_freeMemory( *ppStream );
695 : 0 : *ppStream = NULL;
696 : 0 : *pBytes = 0;
697 : 0 : return false;
698 : : }
699 : : // is there a filter entry ?
700 : : boost::unordered_map<OString,PDFEntry*,OStringHash>::const_iterator it =
701 [ # # ]: 0 : m_pStream->m_pDict->m_aMap.find( "Filter" );
702 [ # # ][ # # ]: 0 : if( it != m_pStream->m_pDict->m_aMap.end() )
703 : : {
704 [ # # ][ # # ]: 0 : PDFName* pFilter = dynamic_cast<PDFName*>(it->second);
705 [ # # ]: 0 : if( ! pFilter )
706 : : {
707 [ # # ][ # # ]: 0 : PDFArray* pArray = dynamic_cast<PDFArray*>(it->second);
708 [ # # ][ # # ]: 0 : if( pArray && ! pArray->m_aSubElements.empty() )
[ # # ]
709 : : {
710 [ # # ][ # # ]: 0 : pFilter = dynamic_cast<PDFName*>(pArray->m_aSubElements.front());
711 : : }
712 : : }
713 : :
714 : : // is the (first) filter FlateDecode ?
715 [ # # ][ # # ]: 0 : if (pFilter && pFilter->m_aName.equalsL(RTL_CONSTASCII_STRINGPARAM("FlateDecode")))
[ # # ]
716 : : {
717 : 0 : bIsDeflated = true;
718 : : }
719 : : }
720 : : // prepare compressed data section
721 : 0 : char* pStream = *ppStream;
722 [ # # ]: 0 : if( pStream[0] == 's' )
723 : 0 : pStream += 6; // skip "stream"
724 : : // skip line end after "stream"
725 [ # # ][ # # ]: 0 : while( *pStream == '\r' || *pStream == '\n' )
[ # # ]
726 : 0 : pStream++;
727 : : // get the compressed length
728 [ # # ]: 0 : *pBytes = m_pStream->getDictLength( pObjectContainer );
729 [ # # ]: 0 : if( pStream != *ppStream )
730 [ # # ]: 0 : rtl_moveMemory( *ppStream, pStream, *pBytes );
731 [ # # ]: 0 : if( rContext.m_bDecrypt )
732 : : {
733 : 0 : EmitImplData* pEData = getEmitData( rContext );
734 : : pEData->decrypt( reinterpret_cast<const sal_uInt8*>(*ppStream),
735 : : *pBytes,
736 : : reinterpret_cast<sal_uInt8*>(*ppStream),
737 : : m_nNumber,
738 : : m_nGeneration
739 [ # # ]: 0 : ); // decrypt inplace
740 : 0 : }
741 : : }
742 : : else
743 : 0 : *ppStream = NULL, *pBytes = 0;
744 : 0 : return bIsDeflated;
745 : : }
746 : :
747 : 0 : static void unzipToBuffer( const char* pBegin, unsigned int nLen,
748 : : sal_uInt8** pOutBuf, sal_uInt32* pOutLen )
749 : : {
750 : : z_stream aZStr;
751 : 0 : aZStr.next_in = (Bytef*)pBegin;
752 : 0 : aZStr.avail_in = nLen;
753 : 0 : aZStr.zalloc = ( alloc_func )0;
754 : 0 : aZStr.zfree = ( free_func )0;
755 : 0 : aZStr.opaque = ( voidpf )0;
756 [ # # ]: 0 : inflateInit(&aZStr);
757 : :
758 : 0 : const unsigned int buf_increment_size = 16384;
759 : :
760 : 0 : *pOutBuf = (sal_uInt8*)rtl_reallocateMemory( *pOutBuf, buf_increment_size );
761 : 0 : aZStr.next_out = (Bytef*)*pOutBuf;
762 : 0 : aZStr.avail_out = buf_increment_size;
763 : 0 : int err = Z_OK;
764 : 0 : *pOutLen = buf_increment_size;
765 [ # # ][ # # ]: 0 : while( err != Z_STREAM_END && err >= Z_OK && aZStr.avail_in )
[ # # ][ # # ]
766 : : {
767 [ # # ]: 0 : err = inflate( &aZStr, Z_NO_FLUSH );
768 [ # # ]: 0 : if( aZStr.avail_out == 0 )
769 : : {
770 [ # # ]: 0 : if( err != Z_STREAM_END )
771 : : {
772 : 0 : const int nNewAlloc = *pOutLen + buf_increment_size;
773 : 0 : *pOutBuf = (sal_uInt8*)rtl_reallocateMemory( *pOutBuf, nNewAlloc );
774 : 0 : aZStr.next_out = (Bytef*)(*pOutBuf + *pOutLen);
775 : 0 : aZStr.avail_out = buf_increment_size;
776 : 0 : *pOutLen = nNewAlloc;
777 : : }
778 : : }
779 : : }
780 [ # # ]: 0 : if( err == Z_STREAM_END )
781 : : {
782 [ # # ]: 0 : if( aZStr.avail_out > 0 )
783 : 0 : *pOutLen -= aZStr.avail_out;;
784 : : }
785 [ # # ]: 0 : inflateEnd(&aZStr);
786 [ # # ]: 0 : if( err < Z_OK )
787 : : {
788 : 0 : rtl_freeMemory( *pOutBuf );
789 : 0 : *pOutBuf = NULL;
790 : 0 : *pOutLen = 0;
791 : : }
792 : 0 : }
793 : :
794 : 0 : bool PDFObject::writeStream( EmitContext& rWriteContext, const PDFFile* pParsedFile ) const
795 : : {
796 : 0 : bool bSuccess = false;
797 [ # # ]: 0 : if( m_pStream )
798 : : {
799 : 0 : char* pStream = NULL;
800 : 0 : unsigned int nBytes = 0;
801 [ # # ][ # # ]: 0 : if( getDeflatedStream( &pStream, &nBytes, pParsedFile, rWriteContext ) && nBytes && rWriteContext.m_bDeflate )
[ # # ][ # # ]
[ # # ]
802 : : {
803 : 0 : sal_uInt8* pOutBytes = NULL;
804 : 0 : sal_uInt32 nOutBytes = 0;
805 [ # # ]: 0 : unzipToBuffer( pStream, nBytes, &pOutBytes, &nOutBytes );
806 [ # # ]: 0 : rWriteContext.write( pOutBytes, nOutBytes );
807 : 0 : rtl_freeMemory( pOutBytes );
808 : : }
809 [ # # ][ # # ]: 0 : else if( pStream && nBytes )
810 [ # # ]: 0 : rWriteContext.write( pStream, nBytes );
811 : 0 : rtl_freeMemory( pStream );
812 : : }
813 : 0 : return bSuccess;
814 : : }
815 : :
816 : 0 : bool PDFObject::emit( EmitContext& rWriteContext ) const
817 : : {
818 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( "\n", 1 ) )
819 : 0 : return false;
820 : :
821 : 0 : EmitImplData* pEData = getEmitData( rWriteContext );
822 [ # # ]: 0 : if( pEData )
823 [ # # ][ # # ]: 0 : pEData->insertXref( m_nNumber, m_nGeneration, rWriteContext.getCurPos() );
824 : :
825 : 0 : OStringBuffer aBuf( 32 );
826 [ # # ]: 0 : aBuf.append( sal_Int32( m_nNumber ) );
827 [ # # ]: 0 : aBuf.append( ' ' );
828 [ # # ]: 0 : aBuf.append( sal_Int32( m_nGeneration ) );
829 [ # # ]: 0 : aBuf.append( " obj\n" );
830 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
831 : 0 : return false;
832 : :
833 [ # # ]: 0 : if( pEData )
834 : 0 : pEData->setDecryptObject( m_nNumber, m_nGeneration );
835 [ # # ][ # # ]: 0 : if( (rWriteContext.m_bDeflate || rWriteContext.m_bDecrypt) && pEData )
[ # # ]
836 : : {
837 : 0 : char* pStream = NULL;
838 : 0 : unsigned int nBytes = 0;
839 [ # # ]: 0 : bool bDeflate = getDeflatedStream( &pStream, &nBytes, pEData->m_pObjectContainer, rWriteContext );
840 [ # # ][ # # ]: 0 : if( pStream && nBytes )
841 : : {
842 : : // unzip the stream
843 : 0 : sal_uInt8* pOutBytes = NULL;
844 : 0 : sal_uInt32 nOutBytes = 0;
845 [ # # ][ # # ]: 0 : if( bDeflate && rWriteContext.m_bDeflate )
846 [ # # ]: 0 : unzipToBuffer( pStream, nBytes, &pOutBytes, &nOutBytes );
847 : : else
848 : : {
849 : : // nothing to deflate, but decryption has happened
850 : 0 : pOutBytes = (sal_uInt8*)pStream;
851 : 0 : nOutBytes = (sal_uInt32)nBytes;
852 : : }
853 : :
854 [ # # ]: 0 : if( nOutBytes )
855 : : {
856 : : // clone this object
857 [ # # ]: 0 : PDFObject* pClone = static_cast<PDFObject*>(clone());
858 : : // set length in the dictionary to new stream length
859 [ # # ][ # # ]: 0 : PDFNumber* pNewLen = new PDFNumber( double(nOutBytes) );
860 [ # # ]: 0 : pClone->m_pStream->m_pDict->insertValue( "Length", pNewLen );
861 : :
862 [ # # ][ # # ]: 0 : if( bDeflate && rWriteContext.m_bDeflate )
863 : : {
864 : : // delete flatedecode filter
865 : : boost::unordered_map<OString,PDFEntry*,OStringHash>::const_iterator it =
866 [ # # ]: 0 : pClone->m_pStream->m_pDict->m_aMap.find( "Filter" );
867 [ # # ][ # # ]: 0 : if( it != pClone->m_pStream->m_pDict->m_aMap.end() )
868 : : {
869 [ # # ][ # # ]: 0 : PDFName* pFilter = dynamic_cast<PDFName*>(it->second);
870 [ # # ][ # # ]: 0 : if (pFilter && pFilter->m_aName.equalsL(RTL_CONSTASCII_STRINGPARAM("FlateDecode")))
[ # # ]
871 [ # # ]: 0 : pClone->m_pStream->m_pDict->eraseValue( "Filter" );
872 : : else
873 : : {
874 [ # # ][ # # ]: 0 : PDFArray* pArray = dynamic_cast<PDFArray*>(it->second);
875 [ # # ][ # # ]: 0 : if( pArray && ! pArray->m_aSubElements.empty() )
[ # # ]
876 : : {
877 [ # # ][ # # ]: 0 : pFilter = dynamic_cast<PDFName*>(pArray->m_aSubElements.front());
878 [ # # ][ # # ]: 0 : if (pFilter && pFilter->m_aName.equalsL(RTL_CONSTASCII_STRINGPARAM("FlateDecode")))
[ # # ]
879 : : {
880 [ # # ][ # # ]: 0 : delete pFilter;
881 [ # # ]: 0 : pArray->m_aSubElements.erase( pArray->m_aSubElements.begin() );
882 : : }
883 : : }
884 : : }
885 : : }
886 : : }
887 : :
888 : : // write sub elements except stream
889 : 0 : bool bRet = true;
890 : 0 : unsigned int nEle = pClone->m_aSubElements.size();
891 [ # # ][ # # ]: 0 : for( unsigned int i = 0; i < nEle && bRet; i++ )
[ # # ]
892 : : {
893 [ # # ]: 0 : if( pClone->m_aSubElements[i] != pClone->m_pStream )
894 [ # # ]: 0 : bRet = pClone->m_aSubElements[i]->emit( rWriteContext );
895 : : }
896 [ # # ][ # # ]: 0 : delete pClone;
897 : : // write stream
898 [ # # ]: 0 : if( bRet )
899 [ # # ]: 0 : rWriteContext.write( "stream\n", 7 );
900 [ # # ]: 0 : if( bRet )
901 [ # # ]: 0 : bRet = rWriteContext.write( pOutBytes, nOutBytes );
902 [ # # ]: 0 : if( bRet )
903 [ # # ]: 0 : bRet = rWriteContext.write( "\nendstream\nendobj\n", 18 );
904 : 0 : rtl_freeMemory( pStream );
905 [ # # ]: 0 : if( pOutBytes != (sal_uInt8*)pStream )
906 : 0 : rtl_freeMemory( pOutBytes );
907 [ # # ]: 0 : if( pEData )
908 : 0 : pEData->setDecryptObject( 0, 0 );
909 : 0 : return bRet;
910 : : }
911 [ # # ]: 0 : if( pOutBytes != (sal_uInt8*)pStream )
912 : 0 : rtl_freeMemory( pOutBytes );
913 : : }
914 : 0 : rtl_freeMemory( pStream );
915 : : }
916 : :
917 [ # # ]: 0 : bool bRet = emitSubElements( rWriteContext ) &&
918 [ # # ][ # # ]: 0 : rWriteContext.write( "\nendobj\n", 8 );
[ # # ]
919 [ # # ]: 0 : if( pEData )
920 : 0 : pEData->setDecryptObject( 0, 0 );
921 : 0 : return bRet;
922 : : }
923 : :
924 : 0 : PDFEntry* PDFObject::clone() const
925 : : {
926 [ # # ]: 0 : PDFObject* pNewOb = new PDFObject( m_nNumber, m_nGeneration );
927 : 0 : cloneSubElements( pNewOb->m_aSubElements );
928 : 0 : unsigned int nEle = m_aSubElements.size();
929 [ # # ]: 0 : for( unsigned int i = 0; i < nEle; i++ )
930 : : {
931 [ # # ]: 0 : if( m_aSubElements[i] == m_pObject )
932 : 0 : pNewOb->m_pObject = pNewOb->m_aSubElements[i];
933 [ # # ][ # # ]: 0 : else if( m_aSubElements[i] == m_pStream && pNewOb->m_pObject )
[ # # ]
934 : : {
935 [ # # ]: 0 : pNewOb->m_pStream = dynamic_cast<PDFStream*>(pNewOb->m_aSubElements[i]);
936 [ # # ]: 0 : PDFDict* pNewDict = dynamic_cast<PDFDict*>(pNewOb->m_pObject);
937 [ # # ]: 0 : if( pNewDict )
938 : 0 : pNewOb->m_pStream->m_pDict = pNewDict;
939 : : }
940 : : }
941 : 0 : return pNewOb;
942 : : }
943 : :
944 : 15 : PDFTrailer::~PDFTrailer()
945 : : {
946 [ - + ]: 30 : }
947 : :
948 : 0 : bool PDFTrailer::emit( EmitContext& rWriteContext ) const
949 : : {
950 : : // get xref offset
951 [ # # ]: 0 : unsigned int nXRefPos = rWriteContext.getCurPos();
952 : : // begin xref section, object 0 is always free
953 [ # # ]: 0 : if( ! rWriteContext.write( "xref\r\n"
954 : : "0 1\r\n"
955 [ # # ]: 0 : "0000000000 65535 f\r\n", 31 ) )
956 : 0 : return false;
957 : : // check if we are emitting a complete PDF file
958 : 0 : EmitImplData* pEData = getEmitData( rWriteContext );
959 [ # # ]: 0 : if( pEData )
960 : : {
961 : : // emit object xrefs
962 : 0 : const EmitImplData::XRefTable& rXRefs = pEData->m_aXRefTable;
963 [ # # ][ # # ]: 0 : EmitImplData::XRefTable::const_iterator section_begin, section_end;
964 : 0 : section_begin = rXRefs.begin();
965 [ # # ][ # # ]: 0 : while( section_begin != rXRefs.end() )
966 : : {
967 : : // find end of continuous object numbers
968 : 0 : section_end = section_begin;
969 [ # # ]: 0 : unsigned int nLast = section_begin->first;
970 [ # # ][ # # ]: 0 : while( (++section_end) != rXRefs.end() &&
[ # # ][ # # ]
[ # # ]
[ # # # # ]
971 [ # # ]: 0 : section_end->first == nLast+1 )
972 [ # # ]: 0 : nLast = section_end->first;
973 : : // write first object number and number of following entries
974 : 0 : OStringBuffer aBuf( 21 );
975 [ # # ][ # # ]: 0 : aBuf.append( sal_Int32( section_begin->first ) );
976 [ # # ]: 0 : aBuf.append( ' ' );
977 [ # # ][ # # ]: 0 : aBuf.append( sal_Int32(nLast - section_begin->first + 1) );
978 [ # # ]: 0 : aBuf.append( "\r\n" );
979 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
980 : 0 : return false;
981 [ # # ][ # # ]: 0 : while( section_begin != section_end )
982 : : {
983 : : // write 20 char entry of form
984 : : // 0000offset 00gen n\r\n
985 [ # # ]: 0 : aBuf.setLength( 0 );
986 [ # # ]: 0 : OString aOffset( OString::valueOf( sal_Int64(section_begin->second.second ) ) );
987 : 0 : int nPad = 10 - aOffset.getLength();
988 [ # # ]: 0 : for( int i = 0; i < nPad; i++ )
989 [ # # ]: 0 : aBuf.append( '0' );
990 [ # # ]: 0 : aBuf.append( aOffset );
991 [ # # ]: 0 : aBuf.append( ' ' );
992 [ # # ]: 0 : OString aGeneration( OString::valueOf( sal_Int32(section_begin->second.first ) ) );
993 : 0 : nPad = 5 - aGeneration.getLength();
994 [ # # ]: 0 : for( int i = 0; i < nPad; i++ )
995 [ # # ]: 0 : aBuf.append( '0' );
996 [ # # ]: 0 : aBuf.append( aGeneration );
997 [ # # ]: 0 : aBuf.append( " n\r\n" );
998 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( aBuf.getStr(), 20 ) )
999 : 0 : return false;
1000 [ # # ][ # # ]: 0 : ++section_begin;
1001 [ # # ]: 0 : }
1002 [ # # ]: 0 : }
1003 : : }
1004 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( "trailer\n", 8 ) )
1005 : 0 : return false;
1006 [ # # ][ # # ]: 0 : if( ! emitSubElements( rWriteContext ) )
1007 : 0 : return false;
1008 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( "startxref\n", 10 ) )
1009 : 0 : return false;
1010 : 0 : rtl::OString aOffset( rtl::OString::valueOf( sal_Int32(nXRefPos) ) );
1011 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( aOffset.getStr(), aOffset.getLength() ) )
1012 : 0 : return false;
1013 [ # # ]: 0 : return rWriteContext.write( "\n%%EOF\n", 7 );
1014 : : }
1015 : :
1016 : 0 : PDFEntry* PDFTrailer::clone() const
1017 : : {
1018 [ # # ]: 0 : PDFTrailer* pNewTr = new PDFTrailer();
1019 : 0 : cloneSubElements( pNewTr->m_aSubElements );
1020 : 0 : unsigned int nEle = m_aSubElements.size();
1021 [ # # ]: 0 : for( unsigned int i = 0; i < nEle; i++ )
1022 : : {
1023 [ # # ]: 0 : if( m_aSubElements[i] == m_pDict )
1024 : : {
1025 [ # # ]: 0 : pNewTr->m_pDict = dynamic_cast<PDFDict*>(pNewTr->m_aSubElements[i]);
1026 : 0 : break;
1027 : : }
1028 : : }
1029 : 0 : return pNewTr;
1030 : : }
1031 : :
1032 : : #define ENCRYPTION_KEY_LEN 16
1033 : : #define ENCRYPTION_BUF_LEN 32
1034 : :
1035 : : namespace pdfparse {
1036 : : struct PDFFileImplData
1037 : : {
1038 : : bool m_bIsEncrypted;
1039 : : bool m_bStandardHandler;
1040 : : sal_uInt32 m_nAlgoVersion;
1041 : : sal_uInt32 m_nStandardRevision;
1042 : : sal_uInt32 m_nKeyLength;
1043 : : sal_uInt8 m_aOEntry[32];
1044 : : sal_uInt8 m_aUEntry[32];
1045 : : sal_uInt32 m_nPEntry;
1046 : : OString m_aDocID;
1047 : : rtlCipher m_aCipher;
1048 : : rtlDigest m_aDigest;
1049 : :
1050 : : sal_uInt8 m_aDecryptionKey[ENCRYPTION_KEY_LEN+5]; // maximum handled key length
1051 : :
1052 : 15 : PDFFileImplData() :
1053 : : m_bIsEncrypted( false ),
1054 : : m_bStandardHandler( false ),
1055 : : m_nAlgoVersion( 0 ),
1056 : : m_nStandardRevision( 0 ),
1057 : : m_nKeyLength( 0 ),
1058 : : m_nPEntry( 0 ),
1059 : : m_aCipher( NULL ),
1060 : 15 : m_aDigest( NULL )
1061 : : {
1062 [ + - ]: 15 : rtl_zeroMemory( m_aOEntry, sizeof( m_aOEntry ) );
1063 [ + - ]: 15 : rtl_zeroMemory( m_aUEntry, sizeof( m_aUEntry ) );
1064 [ + - ]: 15 : rtl_zeroMemory( m_aDecryptionKey, sizeof( m_aDecryptionKey ) );
1065 : 15 : }
1066 : :
1067 : 15 : ~PDFFileImplData()
1068 : 15 : {
1069 [ - + ]: 15 : if( m_aCipher )
1070 : 0 : rtl_cipher_destroyARCFOUR( m_aCipher );
1071 [ - + ]: 15 : if( m_aDigest )
1072 : 0 : rtl_digest_destroyMD5( m_aDigest );
1073 : 15 : }
1074 : : };
1075 : : }
1076 : :
1077 : 15 : PDFFile::~PDFFile()
1078 : : {
1079 [ + - ]: 15 : if( m_pData )
1080 [ + - ]: 15 : delete m_pData;
1081 [ - + ]: 30 : }
1082 : :
1083 : 15 : bool PDFFile::isEncrypted() const
1084 : : {
1085 : 15 : return impl_getData()->m_bIsEncrypted;
1086 : : }
1087 : :
1088 : 0 : bool PDFFile::decrypt( const sal_uInt8* pInBuffer, sal_uInt32 nLen, sal_uInt8* pOutBuffer,
1089 : : unsigned int nObject, unsigned int nGeneration ) const
1090 : : {
1091 [ # # ][ # # ]: 0 : if( ! isEncrypted() )
1092 : 0 : return false;
1093 : :
1094 [ # # ]: 0 : if( ! m_pData->m_aCipher )
1095 : 0 : m_pData->m_aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
1096 : :
1097 : : // modify encryption key
1098 : 0 : sal_uInt32 i = m_pData->m_nKeyLength;
1099 : 0 : m_pData->m_aDecryptionKey[i++] = sal_uInt8(nObject&0xff);
1100 : 0 : m_pData->m_aDecryptionKey[i++] = sal_uInt8((nObject>>8)&0xff);
1101 : 0 : m_pData->m_aDecryptionKey[i++] = sal_uInt8((nObject>>16)&0xff);
1102 : 0 : m_pData->m_aDecryptionKey[i++] = sal_uInt8(nGeneration&0xff);
1103 : 0 : m_pData->m_aDecryptionKey[i++] = sal_uInt8((nGeneration>>8)&0xff);
1104 : :
1105 : : sal_uInt8 aSum[ENCRYPTION_KEY_LEN];
1106 : 0 : rtl_digest_updateMD5( m_pData->m_aDigest, m_pData->m_aDecryptionKey, i );
1107 : 0 : rtl_digest_getMD5( m_pData->m_aDigest, aSum, sizeof( aSum ) );
1108 : :
1109 [ # # ]: 0 : if( i > 16 )
1110 : 0 : i = 16;
1111 : :
1112 : : rtlCipherError aErr = rtl_cipher_initARCFOUR( m_pData->m_aCipher,
1113 : : rtl_Cipher_DirectionDecode,
1114 : : aSum, i,
1115 : 0 : NULL, 0 );
1116 [ # # ]: 0 : if( aErr == rtl_Cipher_E_None )
1117 : : aErr = rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1118 : : pInBuffer, nLen,
1119 : 0 : pOutBuffer, nLen );
1120 : 0 : return aErr == rtl_Cipher_E_None;
1121 : : }
1122 : :
1123 : : static const sal_uInt8 nPadString[32] =
1124 : : {
1125 : : 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
1126 : : 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
1127 : : };
1128 : :
1129 : 0 : static void pad_or_truncate_to_32( const OString& rStr, sal_Char* pBuffer )
1130 : : {
1131 : 0 : int nLen = rStr.getLength();
1132 [ # # ]: 0 : if( nLen > 32 )
1133 : 0 : nLen = 32;
1134 : 0 : const sal_Char* pStr = rStr.getStr();
1135 : 0 : rtl_copyMemory( pBuffer, pStr, nLen );
1136 : 0 : int i = 0;
1137 [ # # ]: 0 : while( nLen < 32 )
1138 : 0 : pBuffer[nLen++] = nPadString[i++];
1139 : 0 : }
1140 : :
1141 : : // pass at least pData->m_nKeyLength bytes in
1142 : 0 : static sal_uInt32 password_to_key( const OString& rPwd, sal_uInt8* pOutKey, PDFFileImplData* pData, bool bComputeO )
1143 : : {
1144 : : // see PDF reference 1.4 Algorithm 3.2
1145 : : // encrypt pad string
1146 : : sal_Char aPadPwd[ENCRYPTION_BUF_LEN];
1147 [ # # ]: 0 : pad_or_truncate_to_32( rPwd, aPadPwd );
1148 : 0 : rtl_digest_updateMD5( pData->m_aDigest, aPadPwd, sizeof( aPadPwd ) );
1149 [ # # ]: 0 : if( ! bComputeO )
1150 : : {
1151 : 0 : rtl_digest_updateMD5( pData->m_aDigest, pData->m_aOEntry, 32 );
1152 : : sal_uInt8 aPEntry[4];
1153 : 0 : aPEntry[0] = static_cast<sal_uInt8>(pData->m_nPEntry & 0xff);
1154 : 0 : aPEntry[1] = static_cast<sal_uInt8>((pData->m_nPEntry >> 8 ) & 0xff);
1155 : 0 : aPEntry[2] = static_cast<sal_uInt8>((pData->m_nPEntry >> 16) & 0xff);
1156 : 0 : aPEntry[3] = static_cast<sal_uInt8>((pData->m_nPEntry >> 24) & 0xff);
1157 : 0 : rtl_digest_updateMD5( pData->m_aDigest, aPEntry, sizeof(aPEntry) );
1158 : 0 : rtl_digest_updateMD5( pData->m_aDigest, pData->m_aDocID.getStr(), pData->m_aDocID.getLength() );
1159 : : }
1160 : : sal_uInt8 nSum[RTL_DIGEST_LENGTH_MD5];
1161 : 0 : rtl_digest_getMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1162 [ # # ]: 0 : if( pData->m_nStandardRevision == 3 )
1163 : : {
1164 [ # # ]: 0 : for( int i = 0; i < 50; i++ )
1165 : : {
1166 : 0 : rtl_digest_updateMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1167 : 0 : rtl_digest_getMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1168 : : }
1169 : : }
1170 : 0 : sal_uInt32 nLen = pData->m_nKeyLength;
1171 [ # # ]: 0 : if( nLen > RTL_DIGEST_LENGTH_MD5 )
1172 : 0 : nLen = RTL_DIGEST_LENGTH_MD5;
1173 [ # # ]: 0 : rtl_copyMemory( pOutKey, nSum, nLen );
1174 : 0 : return nLen;
1175 : : }
1176 : :
1177 : 0 : static bool check_user_password( const OString& rPwd, PDFFileImplData* pData )
1178 : : {
1179 : : // see PDF reference 1.4 Algorithm 3.6
1180 : 0 : bool bValid = false;
1181 : : sal_uInt8 aKey[ENCRYPTION_KEY_LEN];
1182 : : sal_uInt8 nEncryptedEntry[ENCRYPTION_BUF_LEN];
1183 [ # # ]: 0 : rtl_zeroMemory( nEncryptedEntry, sizeof(nEncryptedEntry) );
1184 [ # # ]: 0 : sal_uInt32 nKeyLen = password_to_key( rPwd, aKey, pData, false );
1185 : : // save (at this time potential) decryption key for later use
1186 [ # # ]: 0 : rtl_copyMemory( pData->m_aDecryptionKey, aKey, nKeyLen );
1187 [ # # ]: 0 : if( pData->m_nStandardRevision == 2 )
1188 : : {
1189 : : // see PDF reference 1.4 Algorithm 3.4
1190 : : // encrypt pad string
1191 : : rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1192 : : aKey, nKeyLen,
1193 : 0 : NULL, 0 );
1194 : : rtl_cipher_encodeARCFOUR( pData->m_aCipher, nPadString, sizeof( nPadString ),
1195 : 0 : nEncryptedEntry, sizeof( nEncryptedEntry ) );
1196 [ # # ]: 0 : bValid = (rtl_compareMemory( nEncryptedEntry, pData->m_aUEntry, 32 ) == 0);
1197 : : }
1198 [ # # ]: 0 : else if( pData->m_nStandardRevision == 3 )
1199 : : {
1200 : : // see PDF reference 1.4 Algorithm 3.5
1201 : 0 : rtl_digest_updateMD5( pData->m_aDigest, nPadString, sizeof( nPadString ) );
1202 : 0 : rtl_digest_updateMD5( pData->m_aDigest, pData->m_aDocID.getStr(), pData->m_aDocID.getLength() );
1203 : 0 : rtl_digest_getMD5( pData->m_aDigest, nEncryptedEntry, sizeof(nEncryptedEntry) );
1204 : : rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1205 : 0 : aKey, sizeof(aKey), NULL, 0 );
1206 : : rtl_cipher_encodeARCFOUR( pData->m_aCipher,
1207 : : nEncryptedEntry, 16,
1208 : 0 : nEncryptedEntry, 16 ); // encrypt in place
1209 [ # # ]: 0 : for( int i = 1; i <= 19; i++ ) // do it 19 times, start with 1
1210 : : {
1211 : : sal_uInt8 aTempKey[ENCRYPTION_KEY_LEN];
1212 [ # # ]: 0 : for( sal_uInt32 j = 0; j < sizeof(aTempKey); j++ )
1213 : 0 : aTempKey[j] = static_cast<sal_uInt8>( aKey[j] ^ i );
1214 : :
1215 : : rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1216 : 0 : aTempKey, sizeof(aTempKey), NULL, 0 );
1217 : : rtl_cipher_encodeARCFOUR( pData->m_aCipher,
1218 : : nEncryptedEntry, 16,
1219 : 0 : nEncryptedEntry, 16 ); // encrypt in place
1220 : : }
1221 [ # # ]: 0 : bValid = (rtl_compareMemory( nEncryptedEntry, pData->m_aUEntry, 16 ) == 0);
1222 : : }
1223 : 0 : return bValid;
1224 : : }
1225 : :
1226 : 0 : bool PDFFile::setupDecryptionData( const OString& rPwd ) const
1227 : : {
1228 [ # # ]: 0 : if( !impl_getData()->m_bIsEncrypted )
1229 : 0 : return rPwd.isEmpty();
1230 : :
1231 : : // check if we can handle this encryption at all
1232 [ # # ][ # # ]: 0 : if( ! m_pData->m_bStandardHandler ||
[ # # ][ # # ]
[ # # ]
1233 : : m_pData->m_nAlgoVersion < 1 ||
1234 : : m_pData->m_nAlgoVersion > 2 ||
1235 : : m_pData->m_nStandardRevision < 2 ||
1236 : : m_pData->m_nStandardRevision > 3 )
1237 : 0 : return false;
1238 : :
1239 [ # # ]: 0 : if( ! m_pData->m_aCipher )
1240 : 0 : m_pData->m_aCipher = rtl_cipher_createARCFOUR(rtl_Cipher_ModeStream);
1241 [ # # ]: 0 : if( ! m_pData->m_aDigest )
1242 : 0 : m_pData->m_aDigest = rtl_digest_createMD5();
1243 : :
1244 : : // first try user password
1245 : 0 : bool bValid = check_user_password( rPwd, m_pData );
1246 : :
1247 [ # # ]: 0 : if( ! bValid )
1248 : : {
1249 : : // try owner password
1250 : : // see PDF reference 1.4 Algorithm 3.7
1251 : : sal_uInt8 aKey[ENCRYPTION_KEY_LEN];
1252 : : sal_uInt8 nPwd[ENCRYPTION_BUF_LEN];
1253 [ # # ]: 0 : rtl_zeroMemory( nPwd, sizeof(nPwd) );
1254 [ # # ]: 0 : sal_uInt32 nKeyLen = password_to_key( rPwd, aKey, m_pData, true );
1255 [ # # ]: 0 : if( m_pData->m_nStandardRevision == 2 )
1256 : : {
1257 : : rtl_cipher_initARCFOUR( m_pData->m_aCipher, rtl_Cipher_DirectionDecode,
1258 : 0 : aKey, nKeyLen, NULL, 0 );
1259 : : rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1260 : : m_pData->m_aOEntry, 32,
1261 : 0 : nPwd, 32 );
1262 : : }
1263 [ # # ]: 0 : else if( m_pData->m_nStandardRevision == 3 )
1264 : : {
1265 [ # # ]: 0 : rtl_copyMemory( nPwd, m_pData->m_aOEntry, 32 );
1266 [ # # ]: 0 : for( int i = 19; i >= 0; i-- )
1267 : : {
1268 : : sal_uInt8 nTempKey[ENCRYPTION_KEY_LEN];
1269 [ # # ]: 0 : for( unsigned int j = 0; j < sizeof(nTempKey); j++ )
1270 : 0 : nTempKey[j] = sal_uInt8(aKey[j] ^ i);
1271 : : rtl_cipher_initARCFOUR( m_pData->m_aCipher, rtl_Cipher_DirectionDecode,
1272 : 0 : nTempKey, nKeyLen, NULL, 0 );
1273 : : rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1274 : : nPwd, 32,
1275 : 0 : nPwd, 32 ); // decrypt inplace
1276 : : }
1277 : : }
1278 [ # # ]: 0 : bValid = check_user_password( OString( (sal_Char*)nPwd, 32 ), m_pData );
1279 : : }
1280 : :
1281 : 0 : return bValid;
1282 : : }
1283 : :
1284 : 0 : rtl::OUString PDFFile::getDecryptionKey() const
1285 : : {
1286 : 0 : rtl::OUStringBuffer aBuf( ENCRYPTION_KEY_LEN * 2 );
1287 [ # # ][ # # ]: 0 : if( impl_getData()->m_bIsEncrypted )
1288 : : {
1289 [ # # ]: 0 : for( sal_uInt32 i = 0; i < m_pData->m_nKeyLength; i++ )
1290 : : {
1291 : : static const sal_Unicode pHexTab[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
1292 : : '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1293 [ # # ]: 0 : aBuf.append( pHexTab[(m_pData->m_aDecryptionKey[i] >> 4) & 0x0f] );
1294 [ # # ]: 0 : aBuf.append( pHexTab[(m_pData->m_aDecryptionKey[i] & 0x0f)] );
1295 : : }
1296 : :
1297 : : }
1298 [ # # ]: 0 : return aBuf.makeStringAndClear();
1299 : : }
1300 : :
1301 : 15 : PDFFileImplData* PDFFile::impl_getData() const
1302 : : {
1303 [ - + ]: 15 : if( m_pData )
1304 : 0 : return m_pData;
1305 [ + - ]: 15 : m_pData = new PDFFileImplData();
1306 : : // check for encryption dict in a trailer
1307 : 15 : unsigned int nElements = m_aSubElements.size();
1308 [ + + ]: 420 : while( nElements-- > 0 )
1309 : : {
1310 [ - + ]: 405 : PDFTrailer* pTrailer = dynamic_cast<PDFTrailer*>(m_aSubElements[nElements]);
1311 [ + + ][ + - ]: 405 : if( pTrailer && pTrailer->m_pDict )
1312 : : {
1313 : : // search doc id
1314 [ + - ]: 15 : PDFDict::Map::iterator doc_id = pTrailer->m_pDict->m_aMap.find( "ID" );
1315 [ + - ][ + - ]: 15 : if( doc_id != pTrailer->m_pDict->m_aMap.end() )
1316 : : {
1317 [ + - ][ - + ]: 15 : PDFArray* pArr = dynamic_cast<PDFArray*>(doc_id->second);
1318 [ + - ][ + - ]: 15 : if( pArr && pArr->m_aSubElements.size() > 0 )
[ + - ]
1319 : : {
1320 [ - + ]: 15 : PDFString* pStr = dynamic_cast<PDFString*>(pArr->m_aSubElements[0]);
1321 [ + - ]: 15 : if( pStr )
1322 [ + - ]: 15 : m_pData->m_aDocID = pStr->getFilteredString();
1323 : : #if OSL_DEBUG_LEVEL > 1
1324 : : fprintf( stderr, "DocId is <" );
1325 : : for( int i = 0; i < m_pData->m_aDocID.getLength(); i++ )
1326 : : fprintf( stderr, "%.2x", (unsigned int)sal_uInt8(m_pData->m_aDocID.getStr()[i]) );
1327 : : fprintf( stderr, ">\n" );
1328 : : #endif
1329 : : }
1330 : : }
1331 : : // search Encrypt entry
1332 : : PDFDict::Map::iterator enc =
1333 [ + - ]: 15 : pTrailer->m_pDict->m_aMap.find( "Encrypt" );
1334 [ - + ][ + - ]: 15 : if( enc != pTrailer->m_pDict->m_aMap.end() )
1335 : : {
1336 [ # # ][ # # ]: 0 : PDFDict* pDict = dynamic_cast<PDFDict*>(enc->second);
1337 [ # # ]: 0 : if( ! pDict )
1338 : : {
1339 [ # # ][ # # ]: 0 : PDFObjectRef* pRef = dynamic_cast<PDFObjectRef*>(enc->second);
1340 [ # # ]: 0 : if( pRef )
1341 : : {
1342 [ # # ]: 0 : PDFObject* pObj = findObject( pRef );
1343 [ # # ][ # # ]: 0 : if( pObj && pObj->m_pObject )
1344 [ # # ]: 0 : pDict = dynamic_cast<PDFDict*>(pObj->m_pObject);
1345 : : }
1346 : : }
1347 [ # # ]: 0 : if( pDict )
1348 : : {
1349 [ # # ]: 0 : PDFDict::Map::iterator filter = pDict->m_aMap.find( "Filter" );
1350 [ # # ]: 0 : PDFDict::Map::iterator version = pDict->m_aMap.find( "V" );
1351 [ # # ]: 0 : PDFDict::Map::iterator len = pDict->m_aMap.find( "Length" );
1352 [ # # ]: 0 : PDFDict::Map::iterator o_ent = pDict->m_aMap.find( "O" );
1353 [ # # ]: 0 : PDFDict::Map::iterator u_ent = pDict->m_aMap.find( "U" );
1354 [ # # ]: 0 : PDFDict::Map::iterator r_ent = pDict->m_aMap.find( "R" );
1355 [ # # ]: 0 : PDFDict::Map::iterator p_ent = pDict->m_aMap.find( "P" );
1356 [ # # ][ # # ]: 0 : if( filter != pDict->m_aMap.end() )
1357 : : {
1358 : 0 : m_pData->m_bIsEncrypted = true;
1359 : 0 : m_pData->m_nKeyLength = 5;
1360 [ # # ][ # # ]: 0 : if( version != pDict->m_aMap.end() )
1361 : : {
1362 [ # # ][ # # ]: 0 : PDFNumber* pNum = dynamic_cast<PDFNumber*>(version->second);
1363 [ # # ]: 0 : if( pNum )
1364 : 0 : m_pData->m_nAlgoVersion = static_cast<sal_uInt32>(pNum->m_fValue);
1365 : : }
1366 [ # # ]: 0 : if( m_pData->m_nAlgoVersion >= 3 )
1367 : 0 : m_pData->m_nKeyLength = 16;
1368 [ # # ][ # # ]: 0 : if( len != pDict->m_aMap.end() )
1369 : : {
1370 [ # # ][ # # ]: 0 : PDFNumber* pNum = dynamic_cast<PDFNumber*>(len->second);
1371 [ # # ]: 0 : if( pNum )
1372 : 0 : m_pData->m_nKeyLength = static_cast<sal_uInt32>(pNum->m_fValue) / 8;
1373 : : }
1374 [ # # ][ # # ]: 0 : PDFName* pFilter = dynamic_cast<PDFName*>(filter->second);
1375 [ # # ][ # # ]: 0 : if( pFilter && pFilter->getFilteredName() == "Standard" )
[ # # ][ # # ]
[ # # # # ]
1376 : 0 : m_pData->m_bStandardHandler = true;
1377 [ # # ][ # # ]: 0 : if( o_ent != pDict->m_aMap.end() )
1378 : : {
1379 [ # # ][ # # ]: 0 : PDFString* pString = dynamic_cast<PDFString*>(o_ent->second);
1380 [ # # ]: 0 : if( pString )
1381 : : {
1382 [ # # ]: 0 : OString aEnt = pString->getFilteredString();
1383 [ # # ]: 0 : if( aEnt.getLength() == 32 )
1384 [ # # ]: 0 : rtl_copyMemory( m_pData->m_aOEntry, aEnt.getStr(), 32 );
1385 : : #if OSL_DEBUG_LEVEL > 1
1386 : : else
1387 : : {
1388 : : fprintf( stderr, "O entry has length %d, should be 32 <", (int)aEnt.getLength() );
1389 : : for( int i = 0; i < aEnt.getLength(); i++ )
1390 : : fprintf( stderr, " %.2X", (unsigned int)sal_uInt8(aEnt.getStr()[i]) );
1391 : : fprintf( stderr, ">\n" );
1392 : : }
1393 : : #endif
1394 : : }
1395 : : }
1396 [ # # ][ # # ]: 0 : if( u_ent != pDict->m_aMap.end() )
1397 : : {
1398 [ # # ][ # # ]: 0 : PDFString* pString = dynamic_cast<PDFString*>(u_ent->second);
1399 [ # # ]: 0 : if( pString )
1400 : : {
1401 [ # # ]: 0 : OString aEnt = pString->getFilteredString();
1402 [ # # ]: 0 : if( aEnt.getLength() == 32 )
1403 [ # # ]: 0 : rtl_copyMemory( m_pData->m_aUEntry, aEnt.getStr(), 32 );
1404 : : #if OSL_DEBUG_LEVEL > 1
1405 : : else
1406 : : {
1407 : : fprintf( stderr, "U entry has length %d, should be 32 <", (int)aEnt.getLength() );
1408 : : for( int i = 0; i < aEnt.getLength(); i++ )
1409 : : fprintf( stderr, " %.2X", (unsigned int)sal_uInt8(aEnt.getStr()[i]) );
1410 : : fprintf( stderr, ">\n" );
1411 : : }
1412 : : #endif
1413 : : }
1414 : : }
1415 [ # # ][ # # ]: 0 : if( r_ent != pDict->m_aMap.end() )
1416 : : {
1417 [ # # ][ # # ]: 0 : PDFNumber* pNum = dynamic_cast<PDFNumber*>(r_ent->second);
1418 [ # # ]: 0 : if( pNum )
1419 : 0 : m_pData->m_nStandardRevision = static_cast<sal_uInt32>(pNum->m_fValue);
1420 : : }
1421 [ # # ][ # # ]: 0 : if( p_ent != pDict->m_aMap.end() )
1422 : : {
1423 [ # # ][ # # ]: 0 : PDFNumber* pNum = dynamic_cast<PDFNumber*>(p_ent->second);
1424 [ # # ]: 0 : if( pNum )
1425 : 15 : m_pData->m_nPEntry = static_cast<sal_uInt32>(static_cast<sal_Int32>(pNum->m_fValue));
1426 : : #if OSL_DEBUG_LEVEL > 1
1427 : : fprintf( stderr, "p entry is %" SAL_PRIxUINT32 "\n", m_pData->m_nPEntry );
1428 : : #endif
1429 : : }
1430 : : #if OSL_DEBUG_LEVEL > 1
1431 : : fprintf( stderr, "Encryption dict: sec handler: %s, version = %d, revision = %d, key length = %d\n",
1432 : : pFilter ? OUStringToOString( pFilter->getFilteredName(), RTL_TEXTENCODING_UTF8 ).getStr() : "<unknown>",
1433 : : (int)m_pData->m_nAlgoVersion, (int)m_pData->m_nStandardRevision, (int)m_pData->m_nKeyLength );
1434 : : #endif
1435 : : break;
1436 : : }
1437 : : }
1438 : : }
1439 : : }
1440 : : }
1441 : :
1442 : 15 : return m_pData;
1443 : : }
1444 : :
1445 : 0 : bool PDFFile::emit( EmitContext& rWriteContext ) const
1446 : : {
1447 [ # # ][ # # ]: 0 : setEmitData( rWriteContext, new EmitImplData( this ) );
1448 : :
1449 : 0 : OStringBuffer aBuf( 32 );
1450 [ # # ]: 0 : aBuf.append( "%PDF-" );
1451 [ # # ]: 0 : aBuf.append( sal_Int32( m_nMajor ) );
1452 [ # # ]: 0 : aBuf.append( '.' );
1453 [ # # ]: 0 : aBuf.append( sal_Int32( m_nMinor ) );
1454 [ # # ]: 0 : aBuf.append( "\n" );
1455 [ # # ][ # # ]: 0 : if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
1456 : 0 : return false;
1457 [ # # ]: 0 : return emitSubElements( rWriteContext );
1458 : : }
1459 : :
1460 : 0 : PDFEntry* PDFFile::clone() const
1461 : : {
1462 [ # # ]: 0 : PDFFile* pNewFl = new PDFFile();
1463 : 0 : pNewFl->m_nMajor = m_nMajor;
1464 : 0 : pNewFl->m_nMinor = m_nMinor;
1465 : 0 : cloneSubElements( pNewFl->m_aSubElements );
1466 : 0 : return pNewFl;
1467 : : }
1468 : :
1469 : 0 : PDFPart::~PDFPart()
1470 : : {
1471 [ # # ]: 0 : }
1472 : :
1473 : 0 : bool PDFPart::emit( EmitContext& rWriteContext ) const
1474 : : {
1475 : 0 : return emitSubElements( rWriteContext );
1476 : : }
1477 : :
1478 : 0 : PDFEntry* PDFPart::clone() const
1479 : : {
1480 [ # # ]: 0 : PDFPart* pNewPt = new PDFPart();
1481 : 0 : cloneSubElements( pNewPt->m_aSubElements );
1482 : 0 : return pNewPt;
1483 : : }
1484 : :
1485 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|