fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sdext / source / pdfimport / pdfparse / pdfentries.cxx
bloba01bec327ac92155bbdd3fdf41ca1c602e6116a0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <pdfparse.hxx>
23 #include <rtl/strbuf.hxx>
24 #include <rtl/ustring.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <rtl/alloc.h>
27 #include <rtl/digest.h>
28 #include <rtl/cipher.h>
30 #include <zlib.h>
32 #include <math.h>
33 #include <map>
35 #include <string.h>
39 namespace pdfparse
42 struct EmitImplData
44 // xref table: maps object number to a pair of (generation, buffer offset)
45 typedef std::map< unsigned int, std::pair< unsigned int, unsigned int > > XRefTable;
46 XRefTable m_aXRefTable;
47 // container of all indirect objects (usually a PDFFile*)
48 const PDFContainer* m_pObjectContainer;
49 unsigned int m_nDecryptObject;
50 unsigned int m_nDecryptGeneration;
52 // returns true if the xref table was updated
53 bool insertXref( unsigned int nObject, unsigned int nGeneration, unsigned int nOffset )
55 XRefTable::iterator it = m_aXRefTable.find( nObject );
56 if( it == m_aXRefTable.end() )
58 // new entry
59 m_aXRefTable[ nObject ] = std::pair<unsigned int, unsigned int>(nGeneration,nOffset);
60 return true;
62 // update old entry, if generation number is higher
63 if( it->second.first < nGeneration )
65 it->second = std::pair<unsigned int, unsigned int>(nGeneration,nOffset);
66 return true;
68 return false;
71 EmitImplData( const PDFContainer* pTopContainer ) :
72 m_pObjectContainer( pTopContainer ),
73 m_nDecryptObject( 0 ),
74 m_nDecryptGeneration( 0 )
76 ~EmitImplData() {}
77 bool decrypt( const sal_uInt8* pInBuffer, sal_uInt32 nLen, sal_uInt8* pOutBuffer,
78 unsigned int nObject, unsigned int nGeneration ) const
80 const PDFFile* pFile = dynamic_cast<const PDFFile*>(m_pObjectContainer);
81 return pFile && pFile->decrypt( pInBuffer, nLen, pOutBuffer, nObject, nGeneration );
84 void setDecryptObject( unsigned int nObject, unsigned int nGeneration )
86 m_nDecryptObject = nObject;
87 m_nDecryptGeneration = nGeneration;
93 using namespace pdfparse;
95 EmitContext::EmitContext( const PDFContainer* pTop ) :
96 m_bDeflate( false ),
97 m_bDecrypt( false ),
98 m_pImplData( NULL )
100 if( pTop )
101 m_pImplData = new EmitImplData( pTop );
104 EmitContext::~EmitContext()
106 delete m_pImplData;
109 PDFEntry::~PDFEntry()
113 EmitImplData* PDFEntry::getEmitData( EmitContext& rContext )
115 return rContext.m_pImplData;
118 void PDFEntry::setEmitData( EmitContext& rContext, EmitImplData* pNewEmitData )
120 if( rContext.m_pImplData && rContext.m_pImplData != pNewEmitData )
121 delete rContext.m_pImplData;
122 rContext.m_pImplData = pNewEmitData;
125 PDFValue::~PDFValue()
129 PDFComment::~PDFComment()
133 bool PDFComment::emit( EmitContext& rWriteContext ) const
135 return rWriteContext.write( m_aComment.getStr(), m_aComment.getLength() );
138 PDFEntry* PDFComment::clone() const
140 return new PDFComment( m_aComment );
143 PDFName::~PDFName()
147 bool PDFName::emit( EmitContext& rWriteContext ) const
149 if( ! rWriteContext.write( " /", 2 ) )
150 return false;
151 return rWriteContext.write( m_aName.getStr(), m_aName.getLength() );
154 PDFEntry* PDFName::clone() const
156 return new PDFName( m_aName );
159 OUString PDFName::getFilteredName() const
161 OStringBuffer aFilter( m_aName.getLength() );
162 const sal_Char* pStr = m_aName.getStr();
163 unsigned int nLen = m_aName.getLength();
164 for( unsigned int i = 0; i < nLen; i++ )
166 if( (i < nLen - 3) && pStr[i] == '#' )
168 sal_Char rResult = 0;
169 i++;
170 if( pStr[i] >= '0' && pStr[i] <= '9' )
171 rResult = sal_Char( pStr[i]-'0' ) << 4;
172 else if( pStr[i] >= 'a' && pStr[i] <= 'f' )
173 rResult = sal_Char( pStr[i]-'a' + 10 ) << 4;
174 else if( pStr[i] >= 'A' && pStr[i] <= 'F' )
175 rResult = sal_Char( pStr[i]-'A' + 10 ) << 4;
176 i++;
177 if( pStr[i] >= '0' && pStr[i] <= '9' )
178 rResult |= sal_Char( pStr[i]-'0' );
179 else if( pStr[i] >= 'a' && pStr[i] <= 'f' )
180 rResult |= sal_Char( pStr[i]-'a' + 10 );
181 else if( pStr[i] >= 'A' && pStr[i] <= 'F' )
182 rResult |= sal_Char( pStr[i]-'A' + 10 );
183 aFilter.append( rResult );
185 else
186 aFilter.append( pStr[i] );
188 return OStringToOUString( aFilter.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
191 PDFString::~PDFString()
195 bool PDFString::emit( EmitContext& rWriteContext ) const
197 if( ! rWriteContext.write( " ", 1 ) )
198 return false;
199 EmitImplData* pEData = getEmitData( rWriteContext );
200 if( rWriteContext.m_bDecrypt && pEData && pEData->m_nDecryptObject )
202 OString aFiltered( getFilteredString() );
203 // decrypt inplace (evil since OString is supposed to be const
204 // however in this case we know that getFilteredString returned a singular string instance
205 pEData->decrypt( reinterpret_cast<sal_uInt8 const *>(aFiltered.getStr()), aFiltered.getLength(),
206 reinterpret_cast<sal_uInt8 *>(const_cast<char *>(aFiltered.getStr())),
207 pEData->m_nDecryptObject, pEData->m_nDecryptGeneration );
208 // check for string or hex string
209 const sal_Char* pStr = aFiltered.getStr();
210 if( aFiltered.getLength() > 1 &&
211 ( ((unsigned char)pStr[0] == 0xff && (unsigned char)pStr[1] == 0xfe) ||
212 ((unsigned char)pStr[0] == 0xfe && (unsigned char)pStr[1] == 0xff) ) )
214 static const char pHexTab[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
215 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
216 if( ! rWriteContext.write( "<", 1 ) )
217 return false;
218 for( sal_Int32 i = 0; i < aFiltered.getLength(); i++ )
220 if( ! rWriteContext.write( pHexTab + ((sal_uInt32(pStr[i]) >> 4) & 0x0f), 1 ) )
221 return false;
222 if( ! rWriteContext.write( pHexTab + (sal_uInt32(pStr[i]) & 0x0f), 1 ) )
223 return false;
225 if( ! rWriteContext.write( ">", 1 ) )
226 return false;
228 else
230 if( ! rWriteContext.write( "(", 1 ) )
231 return false;
232 if( ! rWriteContext.write( aFiltered.getStr(), aFiltered.getLength() ) )
233 return false;
234 if( ! rWriteContext.write( ")", 1 ) )
235 return false;
237 return true;
239 return rWriteContext.write( m_aString.getStr(), m_aString.getLength() );
242 PDFEntry* PDFString::clone() const
244 return new PDFString( m_aString );
247 OString PDFString::getFilteredString() const
249 int nLen = m_aString.getLength();
250 OStringBuffer aBuf( nLen );
252 const sal_Char* pStr = m_aString.getStr();
253 if( *pStr == '(' )
255 const sal_Char* pRun = pStr+1;
256 while( pRun - pStr < nLen-1 )
258 if( *pRun == '\\' )
260 pRun++;
261 if( pRun - pStr < nLen )
263 sal_Char aEsc = 0;
264 if( *pRun == 'n' )
265 aEsc = '\n';
266 else if( *pRun == 'r' )
267 aEsc = '\r';
268 else if( *pRun == 't' )
269 aEsc = '\t';
270 else if( *pRun == 'b' )
271 aEsc = '\b';
272 else if( *pRun == 'f' )
273 aEsc = '\f';
274 else if( *pRun == '(' )
275 aEsc = '(';
276 else if( *pRun == ')' )
277 aEsc = ')';
278 else if( *pRun == '\\' )
279 aEsc = '\\';
280 else if( *pRun == '\n' )
282 pRun++;
283 continue;
285 else if( *pRun == '\r' )
287 pRun++;
288 if( *pRun == '\n' )
289 pRun++;
290 continue;
292 else
294 int i = 0;
295 while( i++ < 3 && *pRun >= '0' && *pRun <= '7' )
296 aEsc = 8*aEsc + (*pRun++ - '0');
297 // move pointer back to last character of octal sequence
298 pRun--;
300 aBuf.append( aEsc );
303 else
304 aBuf.append( *pRun );
305 // move pointer to next character
306 pRun++;
309 else if( *pStr == '<' )
311 const sal_Char* pRun = pStr+1;
312 while( *pRun != '>' && pRun - pStr < nLen )
314 sal_Char rResult = 0;
315 if( *pRun >= '0' && *pRun <= '9' )
316 rResult = sal_Char( *pRun-'0' ) << 4;
317 else if( *pRun >= 'a' && *pRun <= 'f' )
318 rResult = sal_Char( *pRun-'a' + 10 ) << 4;
319 else if( *pRun >= 'A' && *pRun <= 'F' )
320 rResult = sal_Char( *pRun-'A' + 10 ) << 4;
321 pRun++;
322 if( *pRun != '>' && pRun - pStr < nLen )
324 if( *pRun >= '0' && *pRun <= '9' )
325 rResult |= sal_Char( *pRun-'0' );
326 else if( *pRun >= 'a' && *pRun <= 'f' )
327 rResult |= sal_Char( *pRun-'a' + 10 );
328 else if( *pRun >= 'A' && *pRun <= 'F' )
329 rResult |= sal_Char( *pRun-'A' + 10 );
331 pRun++;
332 aBuf.append( rResult );
336 return aBuf.makeStringAndClear();
339 PDFNumber::~PDFNumber()
343 bool PDFNumber::emit( EmitContext& rWriteContext ) const
345 OStringBuffer aBuf( 32 );
346 aBuf.append( ' ' );
348 double fValue = m_fValue;
349 bool bNeg = false;
350 int nPrecision = 5;
351 if( fValue < 0.0 )
353 bNeg = true;
354 fValue=-fValue;
357 sal_Int64 nInt = (sal_Int64)fValue;
358 fValue -= (double)nInt;
359 // optimizing hardware may lead to a value of 1.0 after the subtraction
360 if( fValue == 1.0 || log10( 1.0-fValue ) <= -nPrecision )
362 nInt++;
363 fValue = 0.0;
365 sal_Int64 nFrac = 0;
366 if( fValue )
368 fValue *= pow( 10.0, (double)nPrecision );
369 nFrac = (sal_Int64)fValue;
371 if( bNeg && ( nInt || nFrac ) )
372 aBuf.append( '-' );
373 aBuf.append( nInt );
374 if( nFrac )
376 int i;
377 aBuf.append( '.' );
378 sal_Int64 nBound = (sal_Int64)(pow( 10.0, nPrecision - 1.0 )+0.5);
379 for ( i = 0; ( i < nPrecision ) && nFrac; i++ )
381 sal_Int64 nNumb = nFrac / nBound;
382 nFrac -= nNumb * nBound;
383 aBuf.append( nNumb );
384 nBound /= 10;
388 return rWriteContext.write( aBuf.getStr(), aBuf.getLength() );
391 PDFEntry* PDFNumber::clone() const
393 return new PDFNumber( m_fValue );
397 PDFBool::~PDFBool()
401 bool PDFBool::emit( EmitContext& rWriteContext ) const
403 return m_bValue ? rWriteContext.write( " true", 5 ) : rWriteContext.write( " false", 6 );
406 PDFEntry* PDFBool::clone() const
408 return new PDFBool( m_bValue );
411 PDFNull::~PDFNull()
415 bool PDFNull::emit( EmitContext& rWriteContext ) const
417 return rWriteContext.write( " null", 5 );
420 PDFEntry* PDFNull::clone() const
422 return new PDFNull();
426 PDFObjectRef::~PDFObjectRef()
430 bool PDFObjectRef::emit( EmitContext& rWriteContext ) const
432 OStringBuffer aBuf( 16 );
433 aBuf.append( ' ' );
434 aBuf.append( sal_Int32( m_nNumber ) );
435 aBuf.append( ' ' );
436 aBuf.append( sal_Int32( m_nGeneration ) );
437 aBuf.append( " R", 2 );
438 return rWriteContext.write( aBuf.getStr(), aBuf.getLength() );
441 PDFEntry* PDFObjectRef::clone() const
443 return new PDFObjectRef( m_nNumber, m_nGeneration );
446 PDFContainer::~PDFContainer()
448 int nEle = m_aSubElements.size();
449 for( int i = 0; i < nEle; i++ )
450 delete m_aSubElements[i];
453 bool PDFContainer::emitSubElements( EmitContext& rWriteContext ) const
455 int nEle = m_aSubElements.size();
456 for( int i = 0; i < nEle; i++ )
458 if( rWriteContext.m_bDecrypt )
460 const PDFName* pName = dynamic_cast<PDFName*>(m_aSubElements[i]);
461 if (pName && pName->m_aName == "Encrypt")
463 i++;
464 continue;
467 if( ! m_aSubElements[i]->emit( rWriteContext ) )
468 return false;
470 return true;
473 void PDFContainer::cloneSubElements( std::vector<PDFEntry*>& rNewSubElements ) const
475 int nEle = m_aSubElements.size();
476 for( int i = 0; i < nEle; i++ )
477 rNewSubElements.push_back( m_aSubElements[i]->clone() );
480 PDFObject* PDFContainer::findObject( unsigned int nNumber, unsigned int nGeneration ) const
482 unsigned int nEle = m_aSubElements.size();
483 for( unsigned int i = 0; i < nEle; i++ )
485 PDFObject* pObject = dynamic_cast<PDFObject*>(m_aSubElements[i]);
486 if( pObject &&
487 pObject->m_nNumber == nNumber &&
488 pObject->m_nGeneration == nGeneration )
490 return pObject;
493 return NULL;
496 PDFArray::~PDFArray()
500 bool PDFArray::emit( EmitContext& rWriteContext ) const
502 if( ! rWriteContext.write( "[", 1 ) )
503 return false;
504 if( ! emitSubElements( rWriteContext ) )
505 return false;
506 return rWriteContext.write( "]", 1 );
509 PDFEntry* PDFArray::clone() const
511 PDFArray* pNewAr = new PDFArray();
512 cloneSubElements( pNewAr->m_aSubElements );
513 return pNewAr;
516 PDFDict::~PDFDict()
520 bool PDFDict::emit( EmitContext& rWriteContext ) const
522 if( ! rWriteContext.write( "<<\n", 3 ) )
523 return false;
524 if( ! emitSubElements( rWriteContext ) )
525 return false;
526 return rWriteContext.write( "\n>>\n", 4 );
529 void PDFDict::insertValue( const OString& rName, PDFEntry* pValue )
531 if( ! pValue )
532 eraseValue( rName );
534 std::unordered_map<OString,PDFEntry*,OStringHash>::iterator it = m_aMap.find( rName );
535 if( it == m_aMap.end() )
537 // new name/value, pair, append it
538 m_aSubElements.push_back( new PDFName( rName ) );
539 m_aSubElements.push_back( pValue );
541 else
543 unsigned int nSub = m_aSubElements.size();
544 for( unsigned int i = 0; i < nSub; i++ )
545 if( m_aSubElements[i] == it->second )
546 m_aSubElements[i] = pValue;
547 delete it->second;
549 m_aMap[ rName ] = pValue;
552 void PDFDict::eraseValue( const OString& rName )
554 unsigned int nEle = m_aSubElements.size();
555 for( unsigned int i = 0; i < nEle; i++ )
557 PDFName* pName = dynamic_cast<PDFName*>(m_aSubElements[i]);
558 if( pName && pName->m_aName.equals( rName ) )
560 for( unsigned int j = i+1; j < nEle; j++ )
562 if( dynamic_cast<PDFComment*>(m_aSubElements[j]) == NULL )
564 // free name and value
565 delete m_aSubElements[j];
566 delete m_aSubElements[i];
567 // remove subelements from vector
568 m_aSubElements.erase( m_aSubElements.begin()+j );
569 m_aSubElements.erase( m_aSubElements.begin()+i );
570 buildMap();
571 return;
578 PDFEntry* PDFDict::buildMap()
580 // clear map
581 m_aMap.clear();
582 // build map
583 unsigned int nEle = m_aSubElements.size();
584 PDFName* pName = NULL;
585 for( unsigned int i = 0; i < nEle; i++ )
587 if( dynamic_cast<PDFComment*>(m_aSubElements[i]) == NULL )
589 if( pName )
591 m_aMap[ pName->m_aName ] = m_aSubElements[i];
592 pName = NULL;
594 else if( (pName = dynamic_cast<PDFName*>(m_aSubElements[i])) == NULL )
595 return m_aSubElements[i];
598 return pName;
601 PDFEntry* PDFDict::clone() const
603 PDFDict* pNewDict = new PDFDict();
604 cloneSubElements( pNewDict->m_aSubElements );
605 pNewDict->buildMap();
606 return pNewDict;
609 PDFStream::~PDFStream()
613 bool PDFStream::emit( EmitContext& rWriteContext ) const
615 return rWriteContext.copyOrigBytes( m_nBeginOffset, m_nEndOffset-m_nBeginOffset );
618 PDFEntry* PDFStream::clone() const
620 return new PDFStream( m_nBeginOffset, m_nEndOffset, NULL );
623 unsigned int PDFStream::getDictLength( const PDFContainer* pContainer ) const
625 if( ! m_pDict )
626 return 0;
627 // find /Length entry, can either be a direct or indirect number object
628 std::unordered_map<OString,PDFEntry*,OStringHash>::const_iterator it =
629 m_pDict->m_aMap.find( "Length" );
630 if( it == m_pDict->m_aMap.end() )
631 return 0;
632 PDFNumber* pNum = dynamic_cast<PDFNumber*>(it->second);
633 if( ! pNum && pContainer )
635 PDFObjectRef* pRef = dynamic_cast<PDFObjectRef*>(it->second);
636 if( pRef )
638 int nEle = pContainer->m_aSubElements.size();
639 for( int i = 0; i < nEle && ! pNum; i++ )
641 PDFObject* pObj = dynamic_cast<PDFObject*>(pContainer->m_aSubElements[i]);
642 if( pObj &&
643 pObj->m_nNumber == pRef->m_nNumber &&
644 pObj->m_nGeneration == pRef->m_nGeneration )
646 if( pObj->m_pObject )
647 pNum = dynamic_cast<PDFNumber*>(pObj->m_pObject);
648 break;
653 return pNum ? static_cast<unsigned int>(pNum->m_fValue) : 0;
656 PDFObject::~PDFObject()
660 bool PDFObject::getDeflatedStream( char** ppStream, unsigned int* pBytes, const PDFContainer* pObjectContainer, EmitContext& rContext ) const
662 bool bIsDeflated = false;
663 if( m_pStream && m_pStream->m_pDict &&
664 m_pStream->m_nEndOffset > m_pStream->m_nBeginOffset+15
667 unsigned int nOuterStreamLen = m_pStream->m_nEndOffset - m_pStream->m_nBeginOffset;
668 *ppStream = static_cast<char*>(rtl_allocateMemory( nOuterStreamLen ));
669 unsigned int nRead = rContext.readOrigBytes( m_pStream->m_nBeginOffset, nOuterStreamLen, *ppStream );
670 if( nRead != nOuterStreamLen )
672 rtl_freeMemory( *ppStream );
673 *ppStream = NULL;
674 *pBytes = 0;
675 return false;
677 // is there a filter entry ?
678 std::unordered_map<OString,PDFEntry*,OStringHash>::const_iterator it =
679 m_pStream->m_pDict->m_aMap.find( "Filter" );
680 if( it != m_pStream->m_pDict->m_aMap.end() )
682 PDFName* pFilter = dynamic_cast<PDFName*>(it->second);
683 if( ! pFilter )
685 PDFArray* pArray = dynamic_cast<PDFArray*>(it->second);
686 if( pArray && ! pArray->m_aSubElements.empty() )
688 pFilter = dynamic_cast<PDFName*>(pArray->m_aSubElements.front());
692 // is the (first) filter FlateDecode ?
693 if (pFilter && pFilter->m_aName == "FlateDecode")
695 bIsDeflated = true;
698 // prepare compressed data section
699 char* pStream = *ppStream;
700 if( pStream[0] == 's' )
701 pStream += 6; // skip "stream"
702 // skip line end after "stream"
703 while( *pStream == '\r' || *pStream == '\n' )
704 pStream++;
705 // get the compressed length
706 *pBytes = m_pStream->getDictLength( pObjectContainer );
707 if( pStream != *ppStream )
708 memmove( *ppStream, pStream, *pBytes );
709 if( rContext.m_bDecrypt )
711 EmitImplData* pEData = getEmitData( rContext );
712 pEData->decrypt( reinterpret_cast<const sal_uInt8*>(*ppStream),
713 *pBytes,
714 reinterpret_cast<sal_uInt8*>(*ppStream),
715 m_nNumber,
716 m_nGeneration
717 ); // decrypt inplace
720 else
721 *ppStream = NULL, *pBytes = 0;
722 return bIsDeflated;
725 static void unzipToBuffer( char* pBegin, unsigned int nLen,
726 sal_uInt8** pOutBuf, sal_uInt32* pOutLen )
728 z_stream aZStr;
729 aZStr.next_in = reinterpret_cast<Bytef *>(pBegin);
730 aZStr.avail_in = nLen;
731 aZStr.zalloc = ( alloc_func )0;
732 aZStr.zfree = ( free_func )0;
733 aZStr.opaque = ( voidpf )0;
735 int err = inflateInit(&aZStr);
737 const unsigned int buf_increment_size = 16384;
739 *pOutBuf = static_cast<sal_uInt8*>(rtl_reallocateMemory( *pOutBuf, buf_increment_size ));
740 aZStr.next_out = (Bytef*)*pOutBuf;
741 aZStr.avail_out = buf_increment_size;
742 *pOutLen = buf_increment_size;
743 while( err != Z_STREAM_END && err >= Z_OK && aZStr.avail_in )
745 err = inflate( &aZStr, Z_NO_FLUSH );
746 if( aZStr.avail_out == 0 )
748 if( err != Z_STREAM_END )
750 const int nNewAlloc = *pOutLen + buf_increment_size;
751 *pOutBuf = static_cast<sal_uInt8*>(rtl_reallocateMemory( *pOutBuf, nNewAlloc ));
752 aZStr.next_out = (Bytef*)(*pOutBuf + *pOutLen);
753 aZStr.avail_out = buf_increment_size;
754 *pOutLen = nNewAlloc;
758 if( err == Z_STREAM_END )
760 if( aZStr.avail_out > 0 )
761 *pOutLen -= aZStr.avail_out;
763 inflateEnd(&aZStr);
764 if( err < Z_OK )
766 rtl_freeMemory( *pOutBuf );
767 *pOutBuf = NULL;
768 *pOutLen = 0;
772 bool PDFObject::writeStream( EmitContext& rWriteContext, const PDFFile* pParsedFile ) const
774 bool bSuccess = false;
775 if( m_pStream )
777 char* pStream = NULL;
778 unsigned int nBytes = 0;
779 if( getDeflatedStream( &pStream, &nBytes, pParsedFile, rWriteContext ) && nBytes && rWriteContext.m_bDeflate )
781 sal_uInt8* pOutBytes = NULL;
782 sal_uInt32 nOutBytes = 0;
783 unzipToBuffer( pStream, nBytes, &pOutBytes, &nOutBytes );
784 rWriteContext.write( pOutBytes, nOutBytes );
785 rtl_freeMemory( pOutBytes );
787 else if( pStream && nBytes )
788 rWriteContext.write( pStream, nBytes );
789 rtl_freeMemory( pStream );
791 return bSuccess;
794 bool PDFObject::emit( EmitContext& rWriteContext ) const
796 if( ! rWriteContext.write( "\n", 1 ) )
797 return false;
799 EmitImplData* pEData = getEmitData( rWriteContext );
800 if( pEData )
801 pEData->insertXref( m_nNumber, m_nGeneration, rWriteContext.getCurPos() );
803 OStringBuffer aBuf( 32 );
804 aBuf.append( sal_Int32( m_nNumber ) );
805 aBuf.append( ' ' );
806 aBuf.append( sal_Int32( m_nGeneration ) );
807 aBuf.append( " obj\n" );
808 if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
809 return false;
811 if( pEData )
812 pEData->setDecryptObject( m_nNumber, m_nGeneration );
813 if( (rWriteContext.m_bDeflate || rWriteContext.m_bDecrypt) && pEData )
815 char* pStream = NULL;
816 unsigned int nBytes = 0;
817 bool bDeflate = getDeflatedStream( &pStream, &nBytes, pEData->m_pObjectContainer, rWriteContext );
818 if( pStream && nBytes )
820 // unzip the stream
821 sal_uInt8* pOutBytes = NULL;
822 sal_uInt32 nOutBytes = 0;
823 if( bDeflate && rWriteContext.m_bDeflate )
824 unzipToBuffer( pStream, nBytes, &pOutBytes, &nOutBytes );
825 else
827 // nothing to deflate, but decryption has happened
828 pOutBytes = reinterpret_cast<sal_uInt8*>(pStream);
829 nOutBytes = (sal_uInt32)nBytes;
832 if( nOutBytes )
834 // clone this object
835 PDFObject* pClone = static_cast<PDFObject*>(clone());
836 // set length in the dictionary to new stream length
837 PDFNumber* pNewLen = new PDFNumber( double(nOutBytes) );
838 pClone->m_pStream->m_pDict->insertValue( "Length", pNewLen );
840 if( bDeflate && rWriteContext.m_bDeflate )
842 // delete flatedecode filter
843 std::unordered_map<OString,PDFEntry*,OStringHash>::const_iterator it =
844 pClone->m_pStream->m_pDict->m_aMap.find( "Filter" );
845 if( it != pClone->m_pStream->m_pDict->m_aMap.end() )
847 PDFName* pFilter = dynamic_cast<PDFName*>(it->second);
848 if (pFilter && pFilter->m_aName == "FlateDecode")
849 pClone->m_pStream->m_pDict->eraseValue( "Filter" );
850 else
852 PDFArray* pArray = dynamic_cast<PDFArray*>(it->second);
853 if( pArray && ! pArray->m_aSubElements.empty() )
855 pFilter = dynamic_cast<PDFName*>(pArray->m_aSubElements.front());
856 if (pFilter && pFilter->m_aName == "FlateDecode")
858 delete pFilter;
859 pArray->m_aSubElements.erase( pArray->m_aSubElements.begin() );
866 // write sub elements except stream
867 bool bRet = true;
868 unsigned int nEle = pClone->m_aSubElements.size();
869 for( unsigned int i = 0; i < nEle && bRet; i++ )
871 if( pClone->m_aSubElements[i] != pClone->m_pStream )
872 bRet = pClone->m_aSubElements[i]->emit( rWriteContext );
874 delete pClone;
875 // write stream
876 if( bRet )
877 rWriteContext.write( "stream\n", 7 );
878 if( bRet )
879 bRet = rWriteContext.write( pOutBytes, nOutBytes );
880 if( bRet )
881 bRet = rWriteContext.write( "\nendstream\nendobj\n", 18 );
882 if( pOutBytes != reinterpret_cast<sal_uInt8*>(pStream) )
883 rtl_freeMemory( pOutBytes );
884 rtl_freeMemory( pStream );
885 if( pEData )
886 pEData->setDecryptObject( 0, 0 );
887 return bRet;
889 if( pOutBytes != reinterpret_cast<sal_uInt8*>(pStream) )
890 rtl_freeMemory( pOutBytes );
892 rtl_freeMemory( pStream );
895 bool bRet = emitSubElements( rWriteContext ) &&
896 rWriteContext.write( "\nendobj\n", 8 );
897 if( pEData )
898 pEData->setDecryptObject( 0, 0 );
899 return bRet;
902 PDFEntry* PDFObject::clone() const
904 PDFObject* pNewOb = new PDFObject( m_nNumber, m_nGeneration );
905 cloneSubElements( pNewOb->m_aSubElements );
906 unsigned int nEle = m_aSubElements.size();
907 for( unsigned int i = 0; i < nEle; i++ )
909 if( m_aSubElements[i] == m_pObject )
910 pNewOb->m_pObject = pNewOb->m_aSubElements[i];
911 else if( m_aSubElements[i] == m_pStream && pNewOb->m_pObject )
913 pNewOb->m_pStream = dynamic_cast<PDFStream*>(pNewOb->m_aSubElements[i]);
914 PDFDict* pNewDict = dynamic_cast<PDFDict*>(pNewOb->m_pObject);
915 if (pNewDict && pNewOb->m_pStream)
916 pNewOb->m_pStream->m_pDict = pNewDict;
919 return pNewOb;
922 PDFTrailer::~PDFTrailer()
926 bool PDFTrailer::emit( EmitContext& rWriteContext ) const
928 // get xref offset
929 unsigned int nXRefPos = rWriteContext.getCurPos();
930 // begin xref section, object 0 is always free
931 if( ! rWriteContext.write( "xref\r\n"
932 "0 1\r\n"
933 "0000000000 65535 f\r\n", 31 ) )
934 return false;
935 // check if we are emitting a complete PDF file
936 EmitImplData* pEData = getEmitData( rWriteContext );
937 if( pEData )
939 // emit object xrefs
940 const EmitImplData::XRefTable& rXRefs = pEData->m_aXRefTable;
941 EmitImplData::XRefTable::const_iterator section_begin, section_end;
942 section_begin = rXRefs.begin();
943 while( section_begin != rXRefs.end() )
945 // find end of continuous object numbers
946 section_end = section_begin;
947 unsigned int nLast = section_begin->first;
948 while( (++section_end) != rXRefs.end() &&
949 section_end->first == nLast+1 )
950 nLast = section_end->first;
951 // write first object number and number of following entries
952 OStringBuffer aBuf( 21 );
953 aBuf.append( sal_Int32( section_begin->first ) );
954 aBuf.append( ' ' );
955 aBuf.append( sal_Int32(nLast - section_begin->first + 1) );
956 aBuf.append( "\r\n" );
957 if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
958 return false;
959 while( section_begin != section_end )
961 // write 20 char entry of form
962 // 0000offset 00gen n\r\n
963 aBuf.setLength( 0 );
964 OString aOffset( OString::number( section_begin->second.second ) );
965 int nPad = 10 - aOffset.getLength();
966 for( int i = 0; i < nPad; i++ )
967 aBuf.append( '0' );
968 aBuf.append( aOffset );
969 aBuf.append( ' ' );
970 OString aGeneration( OString::number( section_begin->second.first ) );
971 nPad = 5 - aGeneration.getLength();
972 for( int i = 0; i < nPad; i++ )
973 aBuf.append( '0' );
974 aBuf.append( aGeneration );
975 aBuf.append( " n\r\n" );
976 if( ! rWriteContext.write( aBuf.getStr(), 20 ) )
977 return false;
978 ++section_begin;
982 if( ! rWriteContext.write( "trailer\n", 8 ) )
983 return false;
984 if( ! emitSubElements( rWriteContext ) )
985 return false;
986 if( ! rWriteContext.write( "startxref\n", 10 ) )
987 return false;
988 OString aOffset( OString::number( nXRefPos ) );
989 if( ! rWriteContext.write( aOffset.getStr(), aOffset.getLength() ) )
990 return false;
991 return rWriteContext.write( "\n%%EOF\n", 7 );
994 PDFEntry* PDFTrailer::clone() const
996 PDFTrailer* pNewTr = new PDFTrailer();
997 cloneSubElements( pNewTr->m_aSubElements );
998 unsigned int nEle = m_aSubElements.size();
999 for( unsigned int i = 0; i < nEle; i++ )
1001 if( m_aSubElements[i] == m_pDict )
1003 pNewTr->m_pDict = dynamic_cast<PDFDict*>(pNewTr->m_aSubElements[i]);
1004 break;
1007 return pNewTr;
1010 #define ENCRYPTION_KEY_LEN 16
1011 #define ENCRYPTION_BUF_LEN 32
1013 namespace pdfparse {
1014 struct PDFFileImplData
1016 bool m_bIsEncrypted;
1017 bool m_bStandardHandler;
1018 sal_uInt32 m_nAlgoVersion;
1019 sal_uInt32 m_nStandardRevision;
1020 sal_uInt32 m_nKeyLength;
1021 sal_uInt8 m_aOEntry[32];
1022 sal_uInt8 m_aUEntry[32];
1023 sal_uInt32 m_nPEntry;
1024 OString m_aDocID;
1025 rtlCipher m_aCipher;
1026 rtlDigest m_aDigest;
1028 sal_uInt8 m_aDecryptionKey[ENCRYPTION_KEY_LEN+5]; // maximum handled key length
1030 PDFFileImplData() :
1031 m_bIsEncrypted( false ),
1032 m_bStandardHandler( false ),
1033 m_nAlgoVersion( 0 ),
1034 m_nStandardRevision( 0 ),
1035 m_nKeyLength( 0 ),
1036 m_nPEntry( 0 ),
1037 m_aCipher( NULL ),
1038 m_aDigest( NULL )
1040 memset( m_aOEntry, 0, sizeof( m_aOEntry ) );
1041 memset( m_aUEntry, 0, sizeof( m_aUEntry ) );
1042 memset( m_aDecryptionKey, 0, sizeof( m_aDecryptionKey ) );
1045 ~PDFFileImplData()
1047 if( m_aCipher )
1048 rtl_cipher_destroyARCFOUR( m_aCipher );
1049 if( m_aDigest )
1050 rtl_digest_destroyMD5( m_aDigest );
1055 PDFFile::~PDFFile()
1057 if( m_pData )
1058 delete m_pData;
1061 bool PDFFile::isEncrypted() const
1063 return impl_getData()->m_bIsEncrypted;
1066 bool PDFFile::decrypt( const sal_uInt8* pInBuffer, sal_uInt32 nLen, sal_uInt8* pOutBuffer,
1067 unsigned int nObject, unsigned int nGeneration ) const
1069 if( ! isEncrypted() )
1070 return false;
1072 if( ! m_pData->m_aCipher )
1073 m_pData->m_aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
1075 // modify encryption key
1076 sal_uInt32 i = m_pData->m_nKeyLength;
1077 m_pData->m_aDecryptionKey[i++] = sal_uInt8(nObject&0xff);
1078 m_pData->m_aDecryptionKey[i++] = sal_uInt8((nObject>>8)&0xff);
1079 m_pData->m_aDecryptionKey[i++] = sal_uInt8((nObject>>16)&0xff);
1080 m_pData->m_aDecryptionKey[i++] = sal_uInt8(nGeneration&0xff);
1081 m_pData->m_aDecryptionKey[i++] = sal_uInt8((nGeneration>>8)&0xff);
1083 sal_uInt8 aSum[ENCRYPTION_KEY_LEN];
1084 rtl_digest_updateMD5( m_pData->m_aDigest, m_pData->m_aDecryptionKey, i );
1085 rtl_digest_getMD5( m_pData->m_aDigest, aSum, sizeof( aSum ) );
1087 if( i > 16 )
1088 i = 16;
1090 rtlCipherError aErr = rtl_cipher_initARCFOUR( m_pData->m_aCipher,
1091 rtl_Cipher_DirectionDecode,
1092 aSum, i,
1093 NULL, 0 );
1094 if( aErr == rtl_Cipher_E_None )
1095 aErr = rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1096 pInBuffer, nLen,
1097 pOutBuffer, nLen );
1098 return aErr == rtl_Cipher_E_None;
1101 static const sal_uInt8 nPadString[32] =
1103 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
1104 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
1107 static void pad_or_truncate_to_32( const OString& rStr, sal_Char* pBuffer )
1109 int nLen = rStr.getLength();
1110 if( nLen > 32 )
1111 nLen = 32;
1112 const sal_Char* pStr = rStr.getStr();
1113 memcpy( pBuffer, pStr, nLen );
1114 int i = 0;
1115 while( nLen < 32 )
1116 pBuffer[nLen++] = nPadString[i++];
1119 // pass at least pData->m_nKeyLength bytes in
1120 static sal_uInt32 password_to_key( const OString& rPwd, sal_uInt8* pOutKey, PDFFileImplData* pData, bool bComputeO )
1122 // see PDF reference 1.4 Algorithm 3.2
1123 // encrypt pad string
1124 sal_Char aPadPwd[ENCRYPTION_BUF_LEN];
1125 pad_or_truncate_to_32( rPwd, aPadPwd );
1126 rtl_digest_updateMD5( pData->m_aDigest, aPadPwd, sizeof( aPadPwd ) );
1127 if( ! bComputeO )
1129 rtl_digest_updateMD5( pData->m_aDigest, pData->m_aOEntry, 32 );
1130 sal_uInt8 aPEntry[4];
1131 aPEntry[0] = static_cast<sal_uInt8>(pData->m_nPEntry & 0xff);
1132 aPEntry[1] = static_cast<sal_uInt8>((pData->m_nPEntry >> 8 ) & 0xff);
1133 aPEntry[2] = static_cast<sal_uInt8>((pData->m_nPEntry >> 16) & 0xff);
1134 aPEntry[3] = static_cast<sal_uInt8>((pData->m_nPEntry >> 24) & 0xff);
1135 rtl_digest_updateMD5( pData->m_aDigest, aPEntry, sizeof(aPEntry) );
1136 rtl_digest_updateMD5( pData->m_aDigest, pData->m_aDocID.getStr(), pData->m_aDocID.getLength() );
1138 sal_uInt8 nSum[RTL_DIGEST_LENGTH_MD5];
1139 rtl_digest_getMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1140 if( pData->m_nStandardRevision == 3 )
1142 for( int i = 0; i < 50; i++ )
1144 rtl_digest_updateMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1145 rtl_digest_getMD5( pData->m_aDigest, nSum, sizeof(nSum) );
1148 sal_uInt32 nLen = pData->m_nKeyLength;
1149 if( nLen > RTL_DIGEST_LENGTH_MD5 )
1150 nLen = RTL_DIGEST_LENGTH_MD5;
1151 memcpy( pOutKey, nSum, nLen );
1152 return nLen;
1155 static bool check_user_password( const OString& rPwd, PDFFileImplData* pData )
1157 // see PDF reference 1.4 Algorithm 3.6
1158 bool bValid = false;
1159 sal_uInt8 aKey[ENCRYPTION_KEY_LEN];
1160 sal_uInt8 nEncryptedEntry[ENCRYPTION_BUF_LEN];
1161 memset( nEncryptedEntry, 0, sizeof(nEncryptedEntry) );
1162 sal_uInt32 nKeyLen = password_to_key( rPwd, aKey, pData, false );
1163 // save (at this time potential) decryption key for later use
1164 memcpy( pData->m_aDecryptionKey, aKey, nKeyLen );
1165 if( pData->m_nStandardRevision == 2 )
1167 // see PDF reference 1.4 Algorithm 3.4
1168 // encrypt pad string
1169 rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1170 aKey, nKeyLen,
1171 NULL, 0 );
1172 rtl_cipher_encodeARCFOUR( pData->m_aCipher, nPadString, sizeof( nPadString ),
1173 nEncryptedEntry, sizeof( nEncryptedEntry ) );
1174 bValid = (memcmp( nEncryptedEntry, pData->m_aUEntry, 32 ) == 0);
1176 else if( pData->m_nStandardRevision == 3 )
1178 // see PDF reference 1.4 Algorithm 3.5
1179 rtl_digest_updateMD5( pData->m_aDigest, nPadString, sizeof( nPadString ) );
1180 rtl_digest_updateMD5( pData->m_aDigest, pData->m_aDocID.getStr(), pData->m_aDocID.getLength() );
1181 rtl_digest_getMD5( pData->m_aDigest, nEncryptedEntry, sizeof(nEncryptedEntry) );
1182 rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1183 aKey, sizeof(aKey), NULL, 0 );
1184 rtl_cipher_encodeARCFOUR( pData->m_aCipher,
1185 nEncryptedEntry, 16,
1186 nEncryptedEntry, 16 ); // encrypt in place
1187 for( int i = 1; i <= 19; i++ ) // do it 19 times, start with 1
1189 sal_uInt8 aTempKey[ENCRYPTION_KEY_LEN];
1190 for( sal_uInt32 j = 0; j < sizeof(aTempKey); j++ )
1191 aTempKey[j] = static_cast<sal_uInt8>( aKey[j] ^ i );
1193 rtl_cipher_initARCFOUR( pData->m_aCipher, rtl_Cipher_DirectionEncode,
1194 aTempKey, sizeof(aTempKey), NULL, 0 );
1195 rtl_cipher_encodeARCFOUR( pData->m_aCipher,
1196 nEncryptedEntry, 16,
1197 nEncryptedEntry, 16 ); // encrypt in place
1199 bValid = (memcmp( nEncryptedEntry, pData->m_aUEntry, 16 ) == 0);
1201 return bValid;
1204 bool PDFFile::usesSupportedEncryptionFormat() const
1206 return m_pData->m_bStandardHandler &&
1207 m_pData->m_nAlgoVersion >= 1 &&
1208 m_pData->m_nAlgoVersion <= 2 &&
1209 m_pData->m_nStandardRevision >= 2 &&
1210 m_pData->m_nStandardRevision <= 3;
1213 bool PDFFile::setupDecryptionData( const OString& rPwd ) const
1215 if( !impl_getData()->m_bIsEncrypted )
1216 return rPwd.isEmpty();
1218 // check if we can handle this encryption at all
1219 if( ! usesSupportedEncryptionFormat() )
1220 return false;
1222 if( ! m_pData->m_aCipher )
1223 m_pData->m_aCipher = rtl_cipher_createARCFOUR(rtl_Cipher_ModeStream);
1224 if( ! m_pData->m_aDigest )
1225 m_pData->m_aDigest = rtl_digest_createMD5();
1227 // first try user password
1228 bool bValid = check_user_password( rPwd, m_pData );
1230 if( ! bValid )
1232 // try owner password
1233 // see PDF reference 1.4 Algorithm 3.7
1234 sal_uInt8 aKey[ENCRYPTION_KEY_LEN];
1235 sal_uInt8 nPwd[ENCRYPTION_BUF_LEN];
1236 memset( nPwd, 0, sizeof(nPwd) );
1237 sal_uInt32 nKeyLen = password_to_key( rPwd, aKey, m_pData, true );
1238 if( m_pData->m_nStandardRevision == 2 )
1240 rtl_cipher_initARCFOUR( m_pData->m_aCipher, rtl_Cipher_DirectionDecode,
1241 aKey, nKeyLen, NULL, 0 );
1242 rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1243 m_pData->m_aOEntry, 32,
1244 nPwd, 32 );
1246 else if( m_pData->m_nStandardRevision == 3 )
1248 memcpy( nPwd, m_pData->m_aOEntry, 32 );
1249 for( int i = 19; i >= 0; i-- )
1251 sal_uInt8 nTempKey[ENCRYPTION_KEY_LEN];
1252 for( unsigned int j = 0; j < sizeof(nTempKey); j++ )
1253 nTempKey[j] = sal_uInt8(aKey[j] ^ i);
1254 rtl_cipher_initARCFOUR( m_pData->m_aCipher, rtl_Cipher_DirectionDecode,
1255 nTempKey, nKeyLen, NULL, 0 );
1256 rtl_cipher_decodeARCFOUR( m_pData->m_aCipher,
1257 nPwd, 32,
1258 nPwd, 32 ); // decrypt inplace
1261 bValid = check_user_password( OString( reinterpret_cast<char*>(nPwd), 32 ), m_pData );
1264 return bValid;
1267 OUString PDFFile::getDecryptionKey() const
1269 OUStringBuffer aBuf( ENCRYPTION_KEY_LEN * 2 );
1270 if( impl_getData()->m_bIsEncrypted )
1272 for( sal_uInt32 i = 0; i < m_pData->m_nKeyLength; i++ )
1274 static const sal_Unicode pHexTab[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
1275 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1276 aBuf.append( pHexTab[(m_pData->m_aDecryptionKey[i] >> 4) & 0x0f] );
1277 aBuf.append( pHexTab[(m_pData->m_aDecryptionKey[i] & 0x0f)] );
1281 return aBuf.makeStringAndClear();
1284 PDFFileImplData* PDFFile::impl_getData() const
1286 if( m_pData )
1287 return m_pData;
1288 m_pData = new PDFFileImplData();
1289 // check for encryption dict in a trailer
1290 unsigned int nElements = m_aSubElements.size();
1291 while( nElements-- > 0 )
1293 PDFTrailer* pTrailer = dynamic_cast<PDFTrailer*>(m_aSubElements[nElements]);
1294 if( pTrailer && pTrailer->m_pDict )
1296 // search doc id
1297 PDFDict::Map::iterator doc_id = pTrailer->m_pDict->m_aMap.find( "ID" );
1298 if( doc_id != pTrailer->m_pDict->m_aMap.end() )
1300 PDFArray* pArr = dynamic_cast<PDFArray*>(doc_id->second);
1301 if( pArr && pArr->m_aSubElements.size() > 0 )
1303 PDFString* pStr = dynamic_cast<PDFString*>(pArr->m_aSubElements[0]);
1304 if( pStr )
1305 m_pData->m_aDocID = pStr->getFilteredString();
1306 #if OSL_DEBUG_LEVEL > 1
1307 OUString aTmp;
1308 for( int i = 0; i < m_pData->m_aDocID.getLength(); i++ )
1309 aTmp += OUString::number((unsigned int)sal_uInt8(m_pData->m_aDocID[i]), 16);
1310 SAL_INFO("sdext.pdfimport.pdfparse", "DocId is <" << OUStringToOString(aTmp, RTL_TEXTENCODING_UTF8).getStr() << ">");
1311 #endif
1314 // search Encrypt entry
1315 PDFDict::Map::iterator enc =
1316 pTrailer->m_pDict->m_aMap.find( "Encrypt" );
1317 if( enc != pTrailer->m_pDict->m_aMap.end() )
1319 PDFDict* pDict = dynamic_cast<PDFDict*>(enc->second);
1320 if( ! pDict )
1322 PDFObjectRef* pRef = dynamic_cast<PDFObjectRef*>(enc->second);
1323 if( pRef )
1325 PDFObject* pObj = findObject( pRef );
1326 if( pObj && pObj->m_pObject )
1327 pDict = dynamic_cast<PDFDict*>(pObj->m_pObject);
1330 if( pDict )
1332 PDFDict::Map::iterator filter = pDict->m_aMap.find( "Filter" );
1333 PDFDict::Map::iterator version = pDict->m_aMap.find( "V" );
1334 PDFDict::Map::iterator len = pDict->m_aMap.find( "Length" );
1335 PDFDict::Map::iterator o_ent = pDict->m_aMap.find( "O" );
1336 PDFDict::Map::iterator u_ent = pDict->m_aMap.find( "U" );
1337 PDFDict::Map::iterator r_ent = pDict->m_aMap.find( "R" );
1338 PDFDict::Map::iterator p_ent = pDict->m_aMap.find( "P" );
1339 if( filter != pDict->m_aMap.end() )
1341 m_pData->m_bIsEncrypted = true;
1342 m_pData->m_nKeyLength = 5;
1343 if( version != pDict->m_aMap.end() )
1345 PDFNumber* pNum = dynamic_cast<PDFNumber*>(version->second);
1346 if( pNum )
1347 m_pData->m_nAlgoVersion = static_cast<sal_uInt32>(pNum->m_fValue);
1349 if( m_pData->m_nAlgoVersion >= 3 )
1350 m_pData->m_nKeyLength = 16;
1351 if( len != pDict->m_aMap.end() )
1353 PDFNumber* pNum = dynamic_cast<PDFNumber*>(len->second);
1354 if( pNum )
1355 m_pData->m_nKeyLength = static_cast<sal_uInt32>(pNum->m_fValue) / 8;
1357 PDFName* pFilter = dynamic_cast<PDFName*>(filter->second);
1358 if( pFilter && pFilter->getFilteredName() == "Standard" )
1359 m_pData->m_bStandardHandler = true;
1360 if( o_ent != pDict->m_aMap.end() )
1362 PDFString* pString = dynamic_cast<PDFString*>(o_ent->second);
1363 if( pString )
1365 OString aEnt = pString->getFilteredString();
1366 if( aEnt.getLength() == 32 )
1367 memcpy( m_pData->m_aOEntry, aEnt.getStr(), 32 );
1368 #if OSL_DEBUG_LEVEL > 1
1369 else
1371 OUString aTmp;
1372 for( int i = 0; i < aEnt.getLength(); i++ )
1373 aTmp += " " + OUString::number((unsigned int)sal_uInt8(aEnt[i]), 16);
1374 SAL_WARN("sdext.pdfimport.pdfparse",
1375 "O entry has length " << (int)aEnt.getLength() << ", should be 32 <" << OUStringToOString(aTmp, RTL_TEXTENCODING_UTF8).getStr() << ">" );
1377 #endif
1380 if( u_ent != pDict->m_aMap.end() )
1382 PDFString* pString = dynamic_cast<PDFString*>(u_ent->second);
1383 if( pString )
1385 OString aEnt = pString->getFilteredString();
1386 if( aEnt.getLength() == 32 )
1387 memcpy( m_pData->m_aUEntry, aEnt.getStr(), 32 );
1388 #if OSL_DEBUG_LEVEL > 1
1389 else
1391 OUString aTmp;
1392 for( int i = 0; i < aEnt.getLength(); i++ )
1393 aTmp += " " + OUString::number((unsigned int)sal_uInt8(aEnt[i]), 16);
1394 SAL_WARN("sdext.pdfimport.pdfparse",
1395 "U entry has length " << (int)aEnt.getLength() << ", should be 32 <" << OUStringToOString(aTmp, RTL_TEXTENCODING_UTF8).getStr() << ">" );
1397 #endif
1400 if( r_ent != pDict->m_aMap.end() )
1402 PDFNumber* pNum = dynamic_cast<PDFNumber*>(r_ent->second);
1403 if( pNum )
1404 m_pData->m_nStandardRevision = static_cast<sal_uInt32>(pNum->m_fValue);
1406 if( p_ent != pDict->m_aMap.end() )
1408 PDFNumber* pNum = dynamic_cast<PDFNumber*>(p_ent->second);
1409 if( pNum )
1410 m_pData->m_nPEntry = static_cast<sal_uInt32>(static_cast<sal_Int32>(pNum->m_fValue));
1411 SAL_INFO("sdext.pdfimport.pdfparse", "p entry is " << m_pData->m_nPEntry );
1414 SAL_INFO("sdext.pdfimport.pdfparse", "Encryption dict: sec handler: " << (pFilter ? OUStringToOString( pFilter->getFilteredName(), RTL_TEXTENCODING_UTF8 ).getStr() : "<unknown>") << ", version = " << (int)m_pData->m_nAlgoVersion << ", revision = " << (int)m_pData->m_nStandardRevision << ", key length = " << m_pData->m_nKeyLength );
1415 break;
1422 return m_pData;
1425 bool PDFFile::emit( EmitContext& rWriteContext ) const
1427 setEmitData( rWriteContext, new EmitImplData( this ) );
1429 OStringBuffer aBuf( 32 );
1430 aBuf.append( "%PDF-" );
1431 aBuf.append( sal_Int32( m_nMajor ) );
1432 aBuf.append( '.' );
1433 aBuf.append( sal_Int32( m_nMinor ) );
1434 aBuf.append( "\n" );
1435 if( ! rWriteContext.write( aBuf.getStr(), aBuf.getLength() ) )
1436 return false;
1437 return emitSubElements( rWriteContext );
1440 PDFEntry* PDFFile::clone() const
1442 PDFFile* pNewFl = new PDFFile();
1443 pNewFl->m_nMajor = m_nMajor;
1444 pNewFl->m_nMinor = m_nMinor;
1445 cloneSubElements( pNewFl->m_aSubElements );
1446 return pNewFl;
1449 PDFPart::~PDFPart()
1453 bool PDFPart::emit( EmitContext& rWriteContext ) const
1455 return emitSubElements( rWriteContext );
1458 PDFEntry* PDFPart::clone() const
1460 PDFPart* pNewPt = new PDFPart();
1461 cloneSubElements( pNewPt->m_aSubElements );
1462 return pNewPt;
1465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */