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