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