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