1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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() )
59 m_aXRefTable
[ nObject
] = std::pair
<unsigned int, unsigned int>(nGeneration
,nOffset
);
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
);
71 EmitImplData( const PDFContainer
* pTopContainer
) :
72 m_pObjectContainer( pTopContainer
),
73 m_nDecryptObject( 0 ),
74 m_nDecryptGeneration( 0 )
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
) :
101 m_pImplData
= new EmitImplData( pTop
);
104 EmitContext::~EmitContext()
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
);
147 bool PDFName::emit( EmitContext
& rWriteContext
) const
149 if( ! rWriteContext
.write( " /", 2 ) )
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;
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;
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
);
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 ) )
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 ) )
218 for( sal_Int32 i
= 0; i
< aFiltered
.getLength(); i
++ )
220 if( ! rWriteContext
.write( pHexTab
+ ((sal_uInt32(pStr
[i
]) >> 4) & 0x0f), 1 ) )
222 if( ! rWriteContext
.write( pHexTab
+ (sal_uInt32(pStr
[i
]) & 0x0f), 1 ) )
225 if( ! rWriteContext
.write( ">", 1 ) )
230 if( ! rWriteContext
.write( "(", 1 ) )
232 if( ! rWriteContext
.write( aFiltered
.getStr(), aFiltered
.getLength() ) )
234 if( ! rWriteContext
.write( ")", 1 ) )
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();
255 const sal_Char
* pRun
= pStr
+1;
256 while( pRun
- pStr
< nLen
-1 )
261 if( pRun
- pStr
< nLen
)
266 else if( *pRun
== 'r' )
268 else if( *pRun
== 't' )
270 else if( *pRun
== 'b' )
272 else if( *pRun
== 'f' )
274 else if( *pRun
== '(' )
276 else if( *pRun
== ')' )
278 else if( *pRun
== '\\' )
280 else if( *pRun
== '\n' )
285 else if( *pRun
== '\r' )
295 while( i
++ < 3 && *pRun
>= '0' && *pRun
<= '7' )
296 aEsc
= 8*aEsc
+ (*pRun
++ - '0');
297 // move pointer back to last character of octal sequence
304 aBuf
.append( *pRun
);
305 // move pointer to next character
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;
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 );
332 aBuf
.append( rResult
);
336 return aBuf
.makeStringAndClear();
339 PDFNumber::~PDFNumber()
343 bool PDFNumber::emit( EmitContext
& rWriteContext
) const
345 OStringBuffer
aBuf( 32 );
348 double fValue
= m_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
)
368 fValue
*= pow( 10.0, (double)nPrecision
);
369 nFrac
= (sal_Int64
)fValue
;
371 if( bNeg
&& ( nInt
|| nFrac
) )
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
);
388 return rWriteContext
.write( aBuf
.getStr(), aBuf
.getLength() );
391 PDFEntry
* PDFNumber::clone() const
393 return new PDFNumber( m_fValue
);
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
);
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 );
434 aBuf
.append( sal_Int32( m_nNumber
) );
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")
467 if( ! m_aSubElements
[i
]->emit( rWriteContext
) )
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
]);
487 pObject
->m_nNumber
== nNumber
&&
488 pObject
->m_nGeneration
== nGeneration
)
496 PDFArray::~PDFArray()
500 bool PDFArray::emit( EmitContext
& rWriteContext
) const
502 if( ! rWriteContext
.write( "[", 1 ) )
504 if( ! emitSubElements( rWriteContext
) )
506 return rWriteContext
.write( "]", 1 );
509 PDFEntry
* PDFArray::clone() const
511 PDFArray
* pNewAr
= new PDFArray();
512 cloneSubElements( pNewAr
->m_aSubElements
);
520 bool PDFDict::emit( EmitContext
& rWriteContext
) const
522 if( ! rWriteContext
.write( "<<\n", 3 ) )
524 if( ! emitSubElements( rWriteContext
) )
526 return rWriteContext
.write( "\n>>\n", 4 );
529 void PDFDict::insertValue( const OString
& rName
, PDFEntry
* pValue
)
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
);
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
;
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
);
578 PDFEntry
* PDFDict::buildMap()
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
)
591 m_aMap
[ pName
->m_aName
] = m_aSubElements
[i
];
594 else if( (pName
= dynamic_cast<PDFName
*>(m_aSubElements
[i
])) == NULL
)
595 return m_aSubElements
[i
];
601 PDFEntry
* PDFDict::clone() const
603 PDFDict
* pNewDict
= new PDFDict();
604 cloneSubElements( pNewDict
->m_aSubElements
);
605 pNewDict
->buildMap();
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
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() )
632 PDFNumber
* pNum
= dynamic_cast<PDFNumber
*>(it
->second
);
633 if( ! pNum
&& pContainer
)
635 PDFObjectRef
* pRef
= dynamic_cast<PDFObjectRef
*>(it
->second
);
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
]);
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
);
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
);
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
);
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")
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' )
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
),
714 reinterpret_cast<sal_uInt8
*>(*ppStream
),
717 ); // decrypt inplace
721 *ppStream
= NULL
, *pBytes
= 0;
725 static void unzipToBuffer( char* pBegin
, unsigned int nLen
,
726 sal_uInt8
** pOutBuf
, sal_uInt32
* pOutLen
)
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
;
766 rtl_freeMemory( *pOutBuf
);
772 bool PDFObject::writeStream( EmitContext
& rWriteContext
, const PDFFile
* pParsedFile
) const
774 bool bSuccess
= false;
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
);
794 bool PDFObject::emit( EmitContext
& rWriteContext
) const
796 if( ! rWriteContext
.write( "\n", 1 ) )
799 EmitImplData
* pEData
= getEmitData( rWriteContext
);
801 pEData
->insertXref( m_nNumber
, m_nGeneration
, rWriteContext
.getCurPos() );
803 OStringBuffer
aBuf( 32 );
804 aBuf
.append( sal_Int32( m_nNumber
) );
806 aBuf
.append( sal_Int32( m_nGeneration
) );
807 aBuf
.append( " obj\n" );
808 if( ! rWriteContext
.write( aBuf
.getStr(), aBuf
.getLength() ) )
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
)
821 sal_uInt8
* pOutBytes
= NULL
;
822 sal_uInt32 nOutBytes
= 0;
823 if( bDeflate
&& rWriteContext
.m_bDeflate
)
824 unzipToBuffer( pStream
, nBytes
, &pOutBytes
, &nOutBytes
);
827 // nothing to deflate, but decryption has happened
828 pOutBytes
= reinterpret_cast<sal_uInt8
*>(pStream
);
829 nOutBytes
= (sal_uInt32
)nBytes
;
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" );
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")
859 pArray
->m_aSubElements
.erase( pArray
->m_aSubElements
.begin() );
866 // write sub elements except stream
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
);
877 rWriteContext
.write( "stream\n", 7 );
879 bRet
= rWriteContext
.write( pOutBytes
, nOutBytes
);
881 bRet
= rWriteContext
.write( "\nendstream\nendobj\n", 18 );
882 if( pOutBytes
!= reinterpret_cast<sal_uInt8
*>(pStream
) )
883 rtl_freeMemory( pOutBytes
);
884 rtl_freeMemory( pStream
);
886 pEData
->setDecryptObject( 0, 0 );
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 );
898 pEData
->setDecryptObject( 0, 0 );
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
;
922 PDFTrailer::~PDFTrailer()
926 bool PDFTrailer::emit( EmitContext
& rWriteContext
) const
929 unsigned int nXRefPos
= rWriteContext
.getCurPos();
930 // begin xref section, object 0 is always free
931 if( ! rWriteContext
.write( "xref\r\n"
933 "0000000000 65535 f\r\n", 31 ) )
935 // check if we are emitting a complete PDF file
936 EmitImplData
* pEData
= getEmitData( rWriteContext
);
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
) );
955 aBuf
.append( sal_Int32(nLast
- section_begin
->first
+ 1) );
956 aBuf
.append( "\r\n" );
957 if( ! rWriteContext
.write( aBuf
.getStr(), aBuf
.getLength() ) )
959 while( section_begin
!= section_end
)
961 // write 20 char entry of form
962 // 0000offset 00gen n\r\n
964 OString
aOffset( OString::number( section_begin
->second
.second
) );
965 int nPad
= 10 - aOffset
.getLength();
966 for( int i
= 0; i
< nPad
; i
++ )
968 aBuf
.append( aOffset
);
970 OString
aGeneration( OString::number( section_begin
->second
.first
) );
971 nPad
= 5 - aGeneration
.getLength();
972 for( int i
= 0; i
< nPad
; i
++ )
974 aBuf
.append( aGeneration
);
975 aBuf
.append( " n\r\n" );
976 if( ! rWriteContext
.write( aBuf
.getStr(), 20 ) )
982 if( ! rWriteContext
.write( "trailer\n", 8 ) )
984 if( ! emitSubElements( rWriteContext
) )
986 if( ! rWriteContext
.write( "startxref\n", 10 ) )
988 OString
aOffset( OString::number( nXRefPos
) );
989 if( ! rWriteContext
.write( aOffset
.getStr(), aOffset
.getLength() ) )
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
]);
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
;
1025 rtlCipher m_aCipher
;
1026 rtlDigest m_aDigest
;
1028 sal_uInt8 m_aDecryptionKey
[ENCRYPTION_KEY_LEN
+5]; // maximum handled key length
1031 m_bIsEncrypted( false ),
1032 m_bStandardHandler( false ),
1033 m_nAlgoVersion( 0 ),
1034 m_nStandardRevision( 0 ),
1040 memset( m_aOEntry
, 0, sizeof( m_aOEntry
) );
1041 memset( m_aUEntry
, 0, sizeof( m_aUEntry
) );
1042 memset( m_aDecryptionKey
, 0, sizeof( m_aDecryptionKey
) );
1048 rtl_cipher_destroyARCFOUR( m_aCipher
);
1050 rtl_digest_destroyMD5( m_aDigest
);
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() )
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
) );
1090 rtlCipherError aErr
= rtl_cipher_initARCFOUR( m_pData
->m_aCipher
,
1091 rtl_Cipher_DirectionDecode
,
1094 if( aErr
== rtl_Cipher_E_None
)
1095 aErr
= rtl_cipher_decodeARCFOUR( m_pData
->m_aCipher
,
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();
1112 const sal_Char
* pStr
= rStr
.getStr();
1113 memcpy( pBuffer
, pStr
, nLen
);
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
) );
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
);
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
,
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);
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() )
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
);
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,
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
,
1258 nPwd
, 32 ); // decrypt inplace
1261 bValid
= check_user_password( OString( reinterpret_cast<char*>(nPwd
), 32 ), m_pData
);
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
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
)
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]);
1305 m_pData
->m_aDocID
= pStr
->getFilteredString();
1306 #if OSL_DEBUG_LEVEL > 1
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() << ">");
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
);
1322 PDFObjectRef
* pRef
= dynamic_cast<PDFObjectRef
*>(enc
->second
);
1325 PDFObject
* pObj
= findObject( pRef
);
1326 if( pObj
&& pObj
->m_pObject
)
1327 pDict
= dynamic_cast<PDFDict
*>(pObj
->m_pObject
);
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
);
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
);
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
);
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
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() << ">" );
1380 if( u_ent
!= pDict
->m_aMap
.end() )
1382 PDFString
* pString
= dynamic_cast<PDFString
*>(u_ent
->second
);
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
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() << ">" );
1400 if( r_ent
!= pDict
->m_aMap
.end() )
1402 PDFNumber
* pNum
= dynamic_cast<PDFNumber
*>(r_ent
->second
);
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
);
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
);
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
) );
1433 aBuf
.append( sal_Int32( m_nMinor
) );
1434 aBuf
.append( "\n" );
1435 if( ! rWriteContext
.write( aBuf
.getStr(), aBuf
.getLength() ) )
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
);
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
);
1465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */