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