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 if( pStream != *ppStream )
723 rtl_moveMemory( *ppStream, pStream, *pBytes );
724 if( rContext.m_bDecrypt )
725 {
726 EmitImplData* pEData = getEmitData( rContext );
727 pEData->decrypt( reinterpret_cast<const sal_uInt8*>(*ppStream),
728 *pBytes,
729 reinterpret_cast<sal_uInt8*>(*ppStream),
730 m_nNumber,
731 m_nGeneration
732 ); // decrypt inplace
733 }
734 }
735 else
736 *ppStream = NULL, *pBytes = 0;
737 return bIsDeflated;
738 }
739
unzipToBuffer(const char * pBegin,unsigned int nLen,sal_uInt8 ** pOutBuf,sal_uInt32 * pOutLen)740 static void unzipToBuffer( const char* pBegin, unsigned int nLen,
741 sal_uInt8** pOutBuf, sal_uInt32* pOutLen )
742 {
743 z_stream aZStr;
744 aZStr.next_in = (Bytef*)pBegin;
745 aZStr.avail_in = nLen;
746 aZStr.zalloc = ( alloc_func )0;
747 aZStr.zfree = ( free_func )0;
748 aZStr.opaque = ( voidpf )0;
749 inflateInit(&aZStr);
750
751 const unsigned int buf_increment_size = 16384;
752
753 *pOutBuf = (sal_uInt8*)rtl_reallocateMemory( *pOutBuf, buf_increment_size );
754 aZStr.next_out = (Bytef*)*pOutBuf;
755 aZStr.avail_out = buf_increment_size;
756 int err = Z_OK;
757 *pOutLen = buf_increment_size;
758 while( err != Z_STREAM_END && err >= Z_OK && aZStr.avail_in )
759 {
760 err = inflate( &aZStr, Z_NO_FLUSH );
761 if( aZStr.avail_out == 0 )
762 {
763 if( err != Z_STREAM_END )
764 {
765 const int nNewAlloc = *pOutLen + buf_increment_size;
766 *pOutBuf = (sal_uInt8*)rtl_reallocateMemory( *pOutBuf, nNewAlloc );
767 aZStr.next_out = (Bytef*)(*pOutBuf + *pOutLen);
768 aZStr.avail_out = buf_increment_size;
769 *pOutLen = nNewAlloc;
770 }
771 }
772 }
773 if( err == Z_STREAM_END )
774 {
775 if( aZStr.avail_out > 0 )
776 *pOutLen -= aZStr.avail_out;;
777 }
778 inflateEnd(&aZStr);
779 if( err < Z_OK )
780 {
781 rtl_freeMemory( *pOutBuf );
782 *pOutBuf = NULL;
783 *pOutLen = 0;
784 }
785 }
786
writeStream(EmitContext & rWriteContext,const PDFFile * pParsedFile) const787 bool PDFObject::writeStream( EmitContext& rWriteContext, const PDFFile* pParsedFile ) const
788 {
789 bool bSuccess = false;
790 if( m_pStream )
791 {
792 char* pStream = NULL;
793 unsigned int nBytes = 0;
794 if( getDeflatedStream( &pStream, &nBytes, pParsedFile, rWriteContext ) && nBytes && rWriteContext.m_bDeflate )
795 {
796 sal_uInt8* pOutBytes = NULL;
797 sal_uInt32 nOutBytes = 0;
798 unzipToBuffer( pStream, nBytes, &pOutBytes, &nOutBytes );
799 rWriteContext.write( pOutBytes, nOutBytes );
800 rtl_freeMemory( pOutBytes );
801 }
802 else if( pStream && nBytes )
803 rWriteContext.write( pStream, nBytes );
804 rtl_freeMemory( pStream );
805 }
806 return bSuccess;
807 }
808
emit(EmitContext & rWriteContext) const809 bool PDFObject::emit( EmitContext& rWriteContext ) const
810 {
811 if( ! rWriteContext.write( "\n", 1 ) )
812 return false;
813
814 EmitImplData* pEData = getEmitData( rWriteContext );
815 if( pEData )
816 pEData->insertXref( m_nNumber, m_nGeneration, rWriteContext.getCurPos() );
817
818 OStringBuffer aBuf( 32 );
819 aBuf.append( sal_Int32( m_nNumber ) );
820 aBuf.append( ' ' );
821 aBuf.append( sal_Int32( m_nGeneration ) );
822 aBuf.append( " obj\n" );
823 if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
824 return false;
825
826 if( pEData )
827 pEData->setDecryptObject( m_nNumber, m_nGeneration );
828 if( (rWriteContext.m_bDeflate || rWriteContext.m_bDecrypt) && pEData )
829 {
830 char* pStream = NULL;
831 unsigned int nBytes = 0;
832 bool bDeflate = getDeflatedStream( &pStream, &nBytes, pEData->m_pObjectContainer, rWriteContext );
833 if( pStream && nBytes )
834 {
835 // unzip the stream
836 sal_uInt8* pOutBytes = NULL;
837 sal_uInt32 nOutBytes = 0;
838 if( bDeflate && rWriteContext.m_bDeflate )
839 unzipToBuffer( pStream, nBytes, &pOutBytes, &nOutBytes );
840 else
841 {
842 // nothing to deflate, but decryption has happened
843 pOutBytes = (sal_uInt8*)pStream;
844 nOutBytes = (sal_uInt32)nBytes;
845 }
846
847 if( nOutBytes )
848 {
849 // clone this object
850 PDFObject* pClone = static_cast<PDFObject*>(clone());
851 // set length in the dictionary to new stream length
852 PDFNumber* pNewLen = new PDFNumber( double(nOutBytes) );
853 pClone->m_pStream->m_pDict->insertValue( "Length", pNewLen );
854
855 if( bDeflate && rWriteContext.m_bDeflate )
856 {
857 // delete flatedecode filter
858 std::hash_map<OString,PDFEntry*,OStringHash>::const_iterator it =
859 pClone->m_pStream->m_pDict->m_aMap.find( "Filter" );
860 if( it != pClone->m_pStream->m_pDict->m_aMap.end() )
861 {
862 PDFName* pFilter = dynamic_cast<PDFName*>(it->second);
863 if( pFilter && pFilter->m_aName.equals( "FlateDecode" ) )
864 pClone->m_pStream->m_pDict->eraseValue( "Filter" );
865 else
866 {
867 PDFArray* pArray = dynamic_cast<PDFArray*>(it->second);
868 if( pArray && ! pArray->m_aSubElements.empty() )
869 {
870 pFilter = dynamic_cast<PDFName*>(pArray->m_aSubElements.front());
871 if( pFilter && pFilter->m_aName.equals( "FlateDecode" ) )
872 {
873 delete pFilter;
874 pArray->m_aSubElements.erase( pArray->m_aSubElements.begin() );
875 }
876 }
877 }
878 }
879 }
880
881 // write sub elements except stream
882 bool bRet = true;
883 unsigned int nEle = pClone->m_aSubElements.size();
884 for( unsigned int i = 0; i < nEle && bRet; i++ )
885 {
886 if( pClone->m_aSubElements[i] != pClone->m_pStream )
887 bRet = pClone->m_aSubElements[i]->emit( rWriteContext );
888 }
889 delete pClone;
890 // write stream
891 if( bRet )
892 rWriteContext.write( "stream\n", 7 );
893 if( bRet )
894 bRet = rWriteContext.write( pOutBytes, nOutBytes );
895 if( bRet )
896 bRet = rWriteContext.write( "\nendstream\nendobj\n", 18 );
897 rtl_freeMemory( pStream );
898 if( pOutBytes != (sal_uInt8*)pStream )
899 rtl_freeMemory( pOutBytes );
900 if( pEData )
901 pEData->setDecryptObject( 0, 0 );
902 return bRet;
903 }
904 if( pOutBytes != (sal_uInt8*)pStream )
905 rtl_freeMemory( pOutBytes );
906 }
907 rtl_freeMemory( pStream );
908 }
909
910 bool bRet = emitSubElements( rWriteContext ) &&
911 rWriteContext.write( "\nendobj\n", 8 );
912 if( pEData )
913 pEData->setDecryptObject( 0, 0 );
914 return bRet;
915 }
916
clone() const917 PDFEntry* PDFObject::clone() const
918 {
919 PDFObject* pNewOb = new PDFObject( m_nNumber, m_nGeneration );
920 cloneSubElements( pNewOb->m_aSubElements );
921 unsigned int nEle = m_aSubElements.size();
922 for( unsigned int i = 0; i < nEle; i++ )
923 {
924 if( m_aSubElements[i] == m_pObject )
925 pNewOb->m_pObject = pNewOb->m_aSubElements[i];
926 else if( m_aSubElements[i] == m_pStream && pNewOb->m_pObject )
927 {
928 pNewOb->m_pStream = dynamic_cast<PDFStream*>(pNewOb->m_aSubElements[i]);
929 PDFDict* pNewDict = dynamic_cast<PDFDict*>(pNewOb->m_pObject);
930 if( pNewDict )
931 pNewOb->m_pStream->m_pDict = pNewDict;
932 }
933 }
934 return pNewOb;
935 }
936
~PDFTrailer()937 PDFTrailer::~PDFTrailer()
938 {
939 }
940
emit(EmitContext & rWriteContext) const941 bool PDFTrailer::emit( EmitContext& rWriteContext ) const
942 {
943 // get xref offset
944 unsigned int nXRefPos = rWriteContext.getCurPos();
945 // begin xref section, object 0 is always free
946 if( ! rWriteContext.write( "xref\r\n"
947 "0 1\r\n"
948 "0000000000 65535 f\r\n", 31 ) )
949 return false;
950 // check if we are emitting a complete PDF file
951 EmitImplData* pEData = getEmitData( rWriteContext );
952 if( pEData )
953 {
954 // emit object xrefs
955 const EmitImplData::XRefTable& rXRefs = pEData->m_aXRefTable;
956 EmitImplData::XRefTable::const_iterator section_begin, section_end;
957 section_begin = rXRefs.begin();
958 while( section_begin != rXRefs.end() )
959 {
960 // find end of continuous object numbers
961 section_end = section_begin;
962 unsigned int nLast = section_begin->first;
963 while( (++section_end) != rXRefs.end() &&
964 section_end->first == nLast+1 )
965 nLast = section_end->first;
966 // write first object number and number of following entries
967 OStringBuffer aBuf( 21 );
968 aBuf.append( sal_Int32( section_begin->first ) );
969 aBuf.append( ' ' );
970 aBuf.append( sal_Int32(nLast - section_begin->first + 1) );
971 aBuf.append( "\r\n" );
972 if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
973 return false;
974 while( section_begin != section_end )
975 {
976 // write 20 char entry of form
977 // 0000offset 00gen n\r\n
978 aBuf.setLength( 0 );
979 OString aOffset( OString::valueOf( sal_Int64(section_begin->second.second ) ) );
980 int nPad = 10 - aOffset.getLength();
981 for( int i = 0; i < nPad; i++ )
982 aBuf.append( '0' );
983 aBuf.append( aOffset );
984 aBuf.append( ' ' );
985 OString aGeneration( OString::valueOf( sal_Int32(section_begin->second.first ) ) );
986 nPad = 5 - aGeneration.getLength();
987 for( int i = 0; i < nPad; i++ )
988 aBuf.append( '0' );
989 aBuf.append( aGeneration );
990 aBuf.append( " n\r\n" );
991 if( ! rWriteContext.write( aBuf.getStr(), 20 ) )
992 return false;
993 ++section_begin;
994 }
995 }
996 }
997 if( ! rWriteContext.write( "trailer\n", 8 ) )
998 return false;
999 if( ! emitSubElements( rWriteContext ) )
1000 return false;
1001 if( ! rWriteContext.write( "startxref\n", 10 ) )
1002 return false;
1003 rtl::OString aOffset( rtl::OString::valueOf( sal_Int32(nXRefPos) ) );
1004 if( ! rWriteContext.write( aOffset.getStr(), aOffset.getLength() ) )
1005 return false;
1006 return rWriteContext.write( "\n%%EOF\n", 7 );
1007 }
1008
clone() const1009 PDFEntry* PDFTrailer::clone() const
1010 {
1011 PDFTrailer* pNewTr = new PDFTrailer();
1012 cloneSubElements( pNewTr->m_aSubElements );
1013 unsigned int nEle = m_aSubElements.size();
1014 for( unsigned int i = 0; i < nEle; i++ )
1015 {
1016 if( m_aSubElements[i] == m_pDict )
1017 {
1018 pNewTr->m_pDict = dynamic_cast<PDFDict*>(pNewTr->m_aSubElements[i]);
1019 break;
1020 }
1021 }
1022 return pNewTr;
1023 }
1024
1025 #define ENCRYPTION_KEY_LEN 16
1026 #define ENCRYPTION_BUF_LEN 32
1027
1028 namespace pdfparse {
1029 struct PDFFileImplData
1030 {
1031 bool m_bIsEncrypted;
1032 bool m_bStandardHandler;
1033 sal_uInt32 m_nAlgoVersion;
1034 sal_uInt32 m_nStandardRevision;
1035 sal_uInt32 m_nKeyLength;
1036 sal_uInt8 m_aOEntry[32];
1037 sal_uInt8 m_aUEntry[32];
1038 sal_uInt32 m_nPEntry;
1039 OString m_aDocID;
1040 rtlCipher m_aCipher;
1041 rtlDigest m_aDigest;
1042
1043 sal_uInt8 m_aDecryptionKey[ENCRYPTION_KEY_LEN+5]; // maximum handled key length
1044
PDFFileImplDatapdfparse::PDFFileImplData1045 PDFFileImplData() :
1046 m_bIsEncrypted( false ),
1047 m_bStandardHandler( false ),
1048 m_nAlgoVersion( 0 ),
1049 m_nStandardRevision( 0 ),
1050 m_nKeyLength( 0 ),
1051 m_nPEntry( 0 ),
1052 m_aCipher( NULL ),
1053 m_aDigest( NULL )
1054 {
1055 rtl_zeroMemory( m_aOEntry, sizeof( m_aOEntry ) );
1056 rtl_zeroMemory( m_aUEntry, sizeof( m_aUEntry ) );
1057 rtl_zeroMemory( m_aDecryptionKey, sizeof( m_aDecryptionKey ) );
1058 }
1059
~PDFFileImplDatapdfparse::PDFFileImplData1060 ~PDFFileImplData()
1061 {
1062 if( m_aCipher )
1063 rtl_cipher_destroyARCFOUR( m_aCipher );
1064 if( m_aDigest )
1065 rtl_digest_destroyMD5( m_aDigest );
1066 }
1067 };
1068 }
1069
~PDFFile()1070 PDFFile::~PDFFile()
1071 {
1072 if( m_pData )
1073 delete m_pData;
1074 }
1075
isEncrypted() const1076 bool PDFFile::isEncrypted() const
1077 {
1078 return impl_getData()->m_bIsEncrypted;
1079 }
1080
decrypt(const sal_uInt8 * pInBuffer,sal_uInt32 nLen,sal_uInt8 * pOutBuffer,unsigned int nObject,unsigned int nGeneration) const1081 bool PDFFile::decrypt( const sal_uInt8* pInBuffer, sal_uInt32 nLen, sal_uInt8* pOutBuffer,
1082 unsigned int nObject, unsigned int nGeneration ) const
1083 {
1084 if( ! isEncrypted() )
1085 return false;
1086
1087 if( ! m_pData->m_aCipher )
1088 m_pData->m_aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
1089
1090 // modify encryption key
1091 sal_uInt32 i = m_pData->m_nKeyLength;
1092 m_pData->m_aDecryptionKey[i++] = sal_uInt8(nObject&0xff);
1093 m_pData->m_aDecryptionKey[i++] = sal_uInt8((nObject>>8)&0xff);
1094 m_pData->m_aDecryptionKey[i++] = sal_uInt8((nObject>>16)&0xff);
1095 m_pData->m_aDecryptionKey[i++] = sal_uInt8(nGeneration&0xff);
1096 m_pData->m_aDecryptionKey[i++] = sal_uInt8((nGeneration>>8)&0xff);
1097
1098 sal_uInt8 aSum[ENCRYPTION_KEY_LEN];
1099 rtl_digest_updateMD5( m_pData->m_aDigest, m_pData->m_aDecryptionKey, i );
1100 rtl_digest_getMD5( m_pData->m_aDigest, aSum, sizeof( aSum ) );
1101
1102 if( i > 16 )
1103 i = 16;
1104
1105 rtlCipherError aErr = rtl_cipher_initARCFOUR( m_pData->m_aCipher,
1106 rtl_Cipher_DirectionDecode,
1107 aSum, i,
1108 NULL, 0 );
1109 if( aErr == rtl_Cipher_E_None )
1110 aErr = rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1111 pInBuffer, nLen,
1112 pOutBuffer, nLen );
1113 return aErr == rtl_Cipher_E_None;
1114 }
1115
1116 static const sal_uInt8 nPadString[32] =
1117 {
1118 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
1119 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
1120 };
1121
pad_or_truncate_to_32(const OString & rStr,sal_Char * pBuffer)1122 static void pad_or_truncate_to_32( const OString& rStr, sal_Char* pBuffer )
1123 {
1124 int nLen = rStr.getLength();
1125 if( nLen > 32 )
1126 nLen = 32;
1127 const sal_Char* pStr = rStr.getStr();
1128 rtl_copyMemory( pBuffer, pStr, nLen );
1129 int i = 0;
1130 while( nLen < 32 )
1131 pBuffer[nLen++] = nPadString[i++];
1132 }
1133
1134 // pass at least pData->m_nKeyLength bytes in
password_to_key(const OString & rPwd,sal_uInt8 * pOutKey,PDFFileImplData * pData,bool bComputeO)1135 static sal_uInt32 password_to_key( const OString& rPwd, sal_uInt8* pOutKey, PDFFileImplData* pData, bool bComputeO )
1136 {
1137 // see PDF reference 1.4 Algorithm 3.2
1138 // encrypt pad string
1139 sal_Char aPadPwd[ENCRYPTION_BUF_LEN];
1140 pad_or_truncate_to_32( rPwd, aPadPwd );
1141 rtl_digest_updateMD5( pData->m_aDigest, aPadPwd, sizeof( aPadPwd ) );
1142 if( ! bComputeO )
1143 {
1144 rtl_digest_updateMD5( pData->m_aDigest, pData->m_aOEntry, 32 );
1145 sal_uInt8 aPEntry[4];
1146 aPEntry[0] = static_cast<sal_uInt8>(pData->m_nPEntry & 0xff);
1147 aPEntry[1] = static_cast<sal_uInt8>((pData->m_nPEntry >> 8 ) & 0xff);
1148 aPEntry[2] = static_cast<sal_uInt8>((pData->m_nPEntry >> 16) & 0xff);
1149 aPEntry[3] = static_cast<sal_uInt8>((pData->m_nPEntry >> 24) & 0xff);
1150 rtl_digest_updateMD5( pData->m_aDigest, aPEntry, sizeof(aPEntry) );
1151 rtl_digest_updateMD5( pData->m_aDigest, pData->m_aDocID.getStr(), pData->m_aDocID.getLength() );
1152 }
1153 sal_uInt8 nSum[RTL_DIGEST_LENGTH_MD5];
1154 rtl_digest_getMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1155 if( pData->m_nStandardRevision == 3 )
1156 {
1157 for( int i = 0; i < 50; i++ )
1158 {
1159 rtl_digest_updateMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1160 rtl_digest_getMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1161 }
1162 }
1163 sal_uInt32 nLen = pData->m_nKeyLength;
1164 if( nLen > RTL_DIGEST_LENGTH_MD5 )
1165 nLen = RTL_DIGEST_LENGTH_MD5;
1166 rtl_copyMemory( pOutKey, nSum, nLen );
1167 return nLen;
1168 }
1169
check_user_password(const OString & rPwd,PDFFileImplData * pData)1170 static bool check_user_password( const OString& rPwd, PDFFileImplData* pData )
1171 {
1172 // see PDF reference 1.4 Algorithm 3.6
1173 bool bValid = false;
1174 sal_uInt8 aKey[ENCRYPTION_KEY_LEN];
1175 sal_uInt8 nEncryptedEntry[ENCRYPTION_BUF_LEN];
1176 rtl_zeroMemory( nEncryptedEntry, sizeof(nEncryptedEntry) );
1177 sal_uInt32 nKeyLen = password_to_key( rPwd, aKey, pData, false );
1178 // save (at this time potential) decryption key for later use
1179 rtl_copyMemory( pData->m_aDecryptionKey, aKey, nKeyLen );
1180 if( pData->m_nStandardRevision == 2 )
1181 {
1182 // see PDF reference 1.4 Algorithm 3.4
1183 // encrypt pad string
1184 rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1185 aKey, nKeyLen,
1186 NULL, 0 );
1187 rtl_cipher_encodeARCFOUR( pData->m_aCipher, nPadString, sizeof( nPadString ),
1188 nEncryptedEntry, sizeof( nEncryptedEntry ) );
1189 bValid = (rtl_compareMemory( nEncryptedEntry, pData->m_aUEntry, 32 ) == 0);
1190 }
1191 else if( pData->m_nStandardRevision == 3 )
1192 {
1193 // see PDF reference 1.4 Algorithm 3.5
1194 rtl_digest_updateMD5( pData->m_aDigest, nPadString, sizeof( nPadString ) );
1195 rtl_digest_updateMD5( pData->m_aDigest, pData->m_aDocID.getStr(), pData->m_aDocID.getLength() );
1196 rtl_digest_getMD5( pData->m_aDigest, nEncryptedEntry, sizeof(nEncryptedEntry) );
1197 rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1198 aKey, sizeof(aKey), NULL, 0 );
1199 rtl_cipher_encodeARCFOUR( pData->m_aCipher,
1200 nEncryptedEntry, 16,
1201 nEncryptedEntry, 16 ); // encrypt in place
1202 for( int i = 1; i <= 19; i++ ) // do it 19 times, start with 1
1203 {
1204 sal_uInt8 aTempKey[ENCRYPTION_KEY_LEN];
1205 for( sal_uInt32 j = 0; j < sizeof(aTempKey); j++ )
1206 aTempKey[j] = static_cast<sal_uInt8>( aKey[j] ^ i );
1207
1208 rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1209 aTempKey, sizeof(aTempKey), NULL, 0 );
1210 rtl_cipher_encodeARCFOUR( pData->m_aCipher,
1211 nEncryptedEntry, 16,
1212 nEncryptedEntry, 16 ); // encrypt in place
1213 }
1214 bValid = (rtl_compareMemory( nEncryptedEntry, pData->m_aUEntry, 16 ) == 0);
1215 }
1216 return bValid;
1217 }
1218
setupDecryptionData(const OString & rPwd) const1219 bool PDFFile::setupDecryptionData( const OString& rPwd ) const
1220 {
1221 if( !impl_getData()->m_bIsEncrypted )
1222 return rPwd.getLength() == 0;
1223
1224 // check if we can handle this encryption at all
1225 if( ! m_pData->m_bStandardHandler ||
1226 m_pData->m_nAlgoVersion < 1 ||
1227 m_pData->m_nAlgoVersion > 2 ||
1228 m_pData->m_nStandardRevision < 2 ||
1229 m_pData->m_nStandardRevision > 3 )
1230 return false;
1231
1232 if( ! m_pData->m_aCipher )
1233 m_pData->m_aCipher = rtl_cipher_createARCFOUR(rtl_Cipher_ModeStream);
1234 if( ! m_pData->m_aDigest )
1235 m_pData->m_aDigest = rtl_digest_createMD5();
1236
1237 // first try user password
1238 bool bValid = check_user_password( rPwd, m_pData );
1239
1240 if( ! bValid )
1241 {
1242 // try owner password
1243 // see PDF reference 1.4 Algorithm 3.7
1244 sal_uInt8 aKey[ENCRYPTION_KEY_LEN];
1245 sal_uInt8 nPwd[ENCRYPTION_BUF_LEN];
1246 rtl_zeroMemory( nPwd, sizeof(nPwd) );
1247 sal_uInt32 nKeyLen = password_to_key( rPwd, aKey, m_pData, true );
1248 if( m_pData->m_nStandardRevision == 2 )
1249 {
1250 rtl_cipher_initARCFOUR( m_pData->m_aCipher, rtl_Cipher_DirectionDecode,
1251 aKey, nKeyLen, NULL, 0 );
1252 rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1253 m_pData->m_aOEntry, 32,
1254 nPwd, 32 );
1255 }
1256 else if( m_pData->m_nStandardRevision == 3 )
1257 {
1258 rtl_copyMemory( nPwd, m_pData->m_aOEntry, 32 );
1259 for( int i = 19; i >= 0; i-- )
1260 {
1261 sal_uInt8 nTempKey[ENCRYPTION_KEY_LEN];
1262 for( unsigned int j = 0; j < sizeof(nTempKey); j++ )
1263 nTempKey[j] = sal_uInt8(aKey[j] ^ i);
1264 rtl_cipher_initARCFOUR( m_pData->m_aCipher, rtl_Cipher_DirectionDecode,
1265 nTempKey, nKeyLen, NULL, 0 );
1266 rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1267 nPwd, 32,
1268 nPwd, 32 ); // decrypt inplace
1269 }
1270 }
1271 bValid = check_user_password( OString( (sal_Char*)nPwd, 32 ), m_pData );
1272 }
1273
1274 return bValid;
1275 }
1276
getDecryptionKey() const1277 rtl::OUString PDFFile::getDecryptionKey() const
1278 {
1279 rtl::OUStringBuffer aBuf( ENCRYPTION_KEY_LEN * 2 );
1280 if( impl_getData()->m_bIsEncrypted )
1281 {
1282 for( sal_uInt32 i = 0; i < m_pData->m_nKeyLength; i++ )
1283 {
1284 static const sal_Unicode pHexTab[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
1285 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1286 aBuf.append( pHexTab[(m_pData->m_aDecryptionKey[i] >> 4) & 0x0f] );
1287 aBuf.append( pHexTab[(m_pData->m_aDecryptionKey[i] & 0x0f)] );
1288 }
1289
1290 }
1291 return aBuf.makeStringAndClear();
1292 }
1293
impl_getData() const1294 PDFFileImplData* PDFFile::impl_getData() const
1295 {
1296 if( m_pData )
1297 return m_pData;
1298 m_pData = new PDFFileImplData();
1299 // check for encryption dict in a trailer
1300 unsigned int nElements = m_aSubElements.size();
1301 while( nElements-- > 0 )
1302 {
1303 PDFTrailer* pTrailer = dynamic_cast<PDFTrailer*>(m_aSubElements[nElements]);
1304 if( pTrailer && pTrailer->m_pDict )
1305 {
1306 // search doc id
1307 PDFDict::Map::iterator doc_id = pTrailer->m_pDict->m_aMap.find( "ID" );
1308 if( doc_id != pTrailer->m_pDict->m_aMap.end() )
1309 {
1310 PDFArray* pArr = dynamic_cast<PDFArray*>(doc_id->second);
1311 if( pArr && pArr->m_aSubElements.size() > 0 )
1312 {
1313 PDFString* pStr = dynamic_cast<PDFString*>(pArr->m_aSubElements[0]);
1314 if( pStr )
1315 m_pData->m_aDocID = pStr->getFilteredString();
1316 #if OSL_DEBUG_LEVEL > 1
1317 fprintf( stderr, "DocId is <" );
1318 for( int i = 0; i < m_pData->m_aDocID.getLength(); i++ )
1319 fprintf( stderr, "%.2x", (unsigned int)sal_uInt8(m_pData->m_aDocID.getStr()[i]) );
1320 fprintf( stderr, ">\n" );
1321 #endif
1322 }
1323 }
1324 // search Encrypt entry
1325 PDFDict::Map::iterator enc =
1326 pTrailer->m_pDict->m_aMap.find( "Encrypt" );
1327 if( enc != pTrailer->m_pDict->m_aMap.end() )
1328 {
1329 PDFDict* pDict = dynamic_cast<PDFDict*>(enc->second);
1330 if( ! pDict )
1331 {
1332 PDFObjectRef* pRef = dynamic_cast<PDFObjectRef*>(enc->second);
1333 if( pRef )
1334 {
1335 PDFObject* pObj = findObject( pRef );
1336 if( pObj && pObj->m_pObject )
1337 pDict = dynamic_cast<PDFDict*>(pObj->m_pObject);
1338 }
1339 }
1340 if( pDict )
1341 {
1342 PDFDict::Map::iterator filter = pDict->m_aMap.find( "Filter" );
1343 PDFDict::Map::iterator version = pDict->m_aMap.find( "V" );
1344 PDFDict::Map::iterator len = pDict->m_aMap.find( "Length" );
1345 PDFDict::Map::iterator o_ent = pDict->m_aMap.find( "O" );
1346 PDFDict::Map::iterator u_ent = pDict->m_aMap.find( "U" );
1347 PDFDict::Map::iterator r_ent = pDict->m_aMap.find( "R" );
1348 PDFDict::Map::iterator p_ent = pDict->m_aMap.find( "P" );
1349 if( filter != pDict->m_aMap.end() )
1350 {
1351 m_pData->m_bIsEncrypted = true;
1352 m_pData->m_nKeyLength = 5;
1353 if( version != pDict->m_aMap.end() )
1354 {
1355 PDFNumber* pNum = dynamic_cast<PDFNumber*>(version->second);
1356 if( pNum )
1357 m_pData->m_nAlgoVersion = static_cast<sal_uInt32>(pNum->m_fValue);
1358 }
1359 if( m_pData->m_nAlgoVersion >= 3 )
1360 m_pData->m_nKeyLength = 16;
1361 if( len != pDict->m_aMap.end() )
1362 {
1363 PDFNumber* pNum = dynamic_cast<PDFNumber*>(len->second);
1364 if( pNum )
1365 m_pData->m_nKeyLength = static_cast<sal_uInt32>(pNum->m_fValue) / 8;
1366 }
1367 PDFName* pFilter = dynamic_cast<PDFName*>(filter->second);
1368 if( pFilter && pFilter->getFilteredName().equalsAscii( "Standard" ) )
1369 m_pData->m_bStandardHandler = true;
1370 if( o_ent != pDict->m_aMap.end() )
1371 {
1372 PDFString* pString = dynamic_cast<PDFString*>(o_ent->second);
1373 if( pString )
1374 {
1375 OString aEnt = pString->getFilteredString();
1376 if( aEnt.getLength() == 32 )
1377 rtl_copyMemory( m_pData->m_aOEntry, aEnt.getStr(), 32 );
1378 #if OSL_DEBUG_LEVEL > 1
1379 else
1380 {
1381 fprintf( stderr, "O entry has length %d, should be 32 <", (int)aEnt.getLength() );
1382 for( int i = 0; i < aEnt.getLength(); i++ )
1383 fprintf( stderr, " %.2X", (unsigned int)sal_uInt8(aEnt.getStr()[i]) );
1384 fprintf( stderr, ">\n" );
1385 }
1386 #endif
1387 }
1388 }
1389 if( u_ent != pDict->m_aMap.end() )
1390 {
1391 PDFString* pString = dynamic_cast<PDFString*>(u_ent->second);
1392 if( pString )
1393 {
1394 OString aEnt = pString->getFilteredString();
1395 if( aEnt.getLength() == 32 )
1396 rtl_copyMemory( m_pData->m_aUEntry, aEnt.getStr(), 32 );
1397 #if OSL_DEBUG_LEVEL > 1
1398 else
1399 {
1400 fprintf( stderr, "U entry has length %d, should be 32 <", (int)aEnt.getLength() );
1401 for( int i = 0; i < aEnt.getLength(); i++ )
1402 fprintf( stderr, " %.2X", (unsigned int)sal_uInt8(aEnt.getStr()[i]) );
1403 fprintf( stderr, ">\n" );
1404 }
1405 #endif
1406 }
1407 }
1408 if( r_ent != pDict->m_aMap.end() )
1409 {
1410 PDFNumber* pNum = dynamic_cast<PDFNumber*>(r_ent->second);
1411 if( pNum )
1412 m_pData->m_nStandardRevision = static_cast<sal_uInt32>(pNum->m_fValue);
1413 }
1414 if( p_ent != pDict->m_aMap.end() )
1415 {
1416 PDFNumber* pNum = dynamic_cast<PDFNumber*>(p_ent->second);
1417 if( pNum )
1418 m_pData->m_nPEntry = static_cast<sal_uInt32>(static_cast<sal_Int32>(pNum->m_fValue));
1419 #if OSL_DEBUG_LEVEL > 1
1420 fprintf( stderr, "p entry is %p\n", (void*)m_pData->m_nPEntry );
1421 #endif
1422 }
1423 #if OSL_DEBUG_LEVEL > 1
1424 fprintf( stderr, "Encryption dict: sec handler: %s, version = %d, revision = %d, key length = %d\n",
1425 pFilter ? OUStringToOString( pFilter->getFilteredName(), RTL_TEXTENCODING_UTF8 ).getStr() : "<unknown>",
1426 (int)m_pData->m_nAlgoVersion, (int)m_pData->m_nStandardRevision, (int)m_pData->m_nKeyLength );
1427 #endif
1428 break;
1429 }
1430 }
1431 }
1432 }
1433 }
1434
1435 return m_pData;
1436 }
1437
emit(EmitContext & rWriteContext) const1438 bool PDFFile::emit( EmitContext& rWriteContext ) const
1439 {
1440 setEmitData( rWriteContext, new EmitImplData( this ) );
1441
1442 OStringBuffer aBuf( 32 );
1443 aBuf.append( "%PDF-" );
1444 aBuf.append( sal_Int32( m_nMajor ) );
1445 aBuf.append( '.' );
1446 aBuf.append( sal_Int32( m_nMinor ) );
1447 aBuf.append( "\n" );
1448 if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
1449 return false;
1450 return emitSubElements( rWriteContext );
1451 }
1452
clone() const1453 PDFEntry* PDFFile::clone() const
1454 {
1455 PDFFile* pNewFl = new PDFFile();
1456 pNewFl->m_nMajor = m_nMajor;
1457 pNewFl->m_nMinor = m_nMinor;
1458 cloneSubElements( pNewFl->m_aSubElements );
1459 return pNewFl;
1460 }
1461
~PDFPart()1462 PDFPart::~PDFPart()
1463 {
1464 }
1465
emit(EmitContext & rWriteContext) const1466 bool PDFPart::emit( EmitContext& rWriteContext ) const
1467 {
1468 return emitSubElements( rWriteContext );
1469 }
1470
clone() const1471 PDFEntry* PDFPart::clone() const
1472 {
1473 PDFPart* pNewPt = new PDFPart();
1474 cloneSubElements( pNewPt->m_aSubElements );
1475 return pNewPt;
1476 }
1477
1478