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