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