Initial commit.
[pdfium.git] / core / src / fpdfapi / fpdf_edit / fpdf_edit_create.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../include/fpdfapi/fpdf_serial.h"\r
8 #include "editint.h"\r
9 #define PDF_OBJECTSTREAM_MAXLENGTH      (256 * 1024)\r
10 #define PDF_XREFSTREAM_MAXSIZE          10000\r
11 extern void FlateEncode(const FX_BYTE* src_buf, FX_DWORD src_data, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);\r
12 extern void FlateEncode(FX_LPCBYTE src_buf, FX_DWORD src_size, int predictor, int Colors, int BitsPerComponent, int Columns,\r
13                         FX_LPBYTE& dest_buf, FX_DWORD& dest_size);\r
14 extern FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict);\r
15 FX_INT32 PDF_CreatorAppendObject(const CPDF_Object* pObj, CFX_FileBufferArchive *pFile, FX_FILESIZE& offset)\r
16 {\r
17     FX_INT32 len = 0;\r
18     if (pObj == NULL) {\r
19         if (pFile->AppendString(FX_BSTRC(" null")) < 0) {\r
20             return -1;\r
21         }\r
22         offset += 5;\r
23         return 1;\r
24     }\r
25     switch (pObj->GetType()) {\r
26         case PDFOBJ_NULL:\r
27             if (pFile->AppendString(FX_BSTRC(" null")) < 0) {\r
28                 return -1;\r
29             }\r
30             offset += 5;\r
31             break;\r
32         case PDFOBJ_BOOLEAN:\r
33         case PDFOBJ_NUMBER:\r
34             if (pFile->AppendString(FX_BSTRC(" ")) < 0) {\r
35                 return -1;\r
36             }\r
37             if ((len = pFile->AppendString(pObj->GetString())) < 0) {\r
38                 return -1;\r
39             }\r
40             offset += len + 1;\r
41             break;\r
42         case PDFOBJ_STRING: {\r
43                 CFX_ByteString str = pObj->GetString();\r
44                 FX_BOOL bHex = ((CPDF_String*)pObj)->IsHex();\r
45                 if ((len = pFile->AppendString(PDF_EncodeString(str, bHex))) < 0) {\r
46                     return -1;\r
47                 }\r
48                 offset += len;\r
49                 break;\r
50             }\r
51         case PDFOBJ_NAME: {\r
52                 if (pFile->AppendString(FX_BSTRC("/")) < 0) {\r
53                     return -1;\r
54                 }\r
55                 CFX_ByteString str = pObj->GetString();\r
56                 if ((len = pFile->AppendString(PDF_NameEncode(str))) < 0) {\r
57                     return -1;\r
58                 }\r
59                 offset += len + 1;\r
60                 break;\r
61             }\r
62         case PDFOBJ_REFERENCE: {\r
63                 if (pFile->AppendString(FX_BSTRC(" ")) < 0) {\r
64                     return -1;\r
65                 }\r
66                 CPDF_Reference* p = (CPDF_Reference*)pObj;\r
67                 if ((len = pFile->AppendDWord(p->GetRefObjNum())) < 0) {\r
68                     return -1;\r
69                 }\r
70                 if (pFile->AppendString(FX_BSTRC(" 0 R ")) < 0) {\r
71                     return -1;\r
72                 }\r
73                 offset += len + 6;\r
74                 break;\r
75             }\r
76         case PDFOBJ_ARRAY: {\r
77                 if (pFile->AppendString(FX_BSTRC("[")) < 0) {\r
78                     return -1;\r
79                 }\r
80                 offset += 1;\r
81                 CPDF_Array* p = (CPDF_Array*)pObj;\r
82                 for (FX_DWORD i = 0; i < p->GetCount(); i ++) {\r
83                     CPDF_Object* pElement = p->GetElement(i);\r
84                     if (pElement->GetObjNum()) {\r
85                         if (pFile->AppendString(FX_BSTRC(" ")) < 0) {\r
86                             return -1;\r
87                         }\r
88                         if ((len = pFile->AppendDWord(pElement->GetObjNum())) < 0) {\r
89                             return -1;\r
90                         }\r
91                         if (pFile->AppendString(FX_BSTRC(" 0 R")) < 0) {\r
92                             return -1;\r
93                         }\r
94                         offset += len + 5;\r
95                     } else {\r
96                         if (PDF_CreatorAppendObject(pElement, pFile, offset) < 0) {\r
97                             return -1;\r
98                         }\r
99                     }\r
100                 }\r
101                 if (pFile->AppendString(FX_BSTRC("]")) < 0) {\r
102                     return -1;\r
103                 }\r
104                 offset += 1;\r
105                 break;\r
106             }\r
107         case PDFOBJ_DICTIONARY: {\r
108                 if (pFile->AppendString(FX_BSTRC("<<")) < 0) {\r
109                     return -1;\r
110                 }\r
111                 offset += 2;\r
112                 CPDF_Dictionary* p = (CPDF_Dictionary*)pObj;\r
113                 FX_POSITION pos = p->GetStartPos();\r
114                 while (pos) {\r
115                     CFX_ByteString key;\r
116                     CPDF_Object* pValue = p->GetNextElement(pos, key);\r
117                     if (pFile->AppendString(FX_BSTRC("/")) < 0) {\r
118                         return -1;\r
119                     }\r
120                     if ((len = pFile->AppendString(PDF_NameEncode(key))) < 0) {\r
121                         return -1;\r
122                     }\r
123                     offset += len + 1;\r
124                     if (pValue->GetObjNum()) {\r
125                         if (pFile->AppendString(FX_BSTRC(" ")) < 0) {\r
126                             return -1;\r
127                         }\r
128                         if ((len = pFile->AppendDWord(pValue->GetObjNum())) < 0) {\r
129                             return -1;\r
130                         }\r
131                         if (pFile->AppendString(FX_BSTRC(" 0 R")) < 0) {\r
132                             return -1;\r
133                         }\r
134                         offset += len + 5;\r
135                     } else {\r
136                         if (PDF_CreatorAppendObject(pValue, pFile, offset) < 0) {\r
137                             return -1;\r
138                         }\r
139                     }\r
140                 }\r
141                 if (pFile->AppendString(FX_BSTRC(">>")) < 0) {\r
142                     return -1;\r
143                 }\r
144                 offset += 2;\r
145                 break;\r
146             }\r
147         case PDFOBJ_STREAM: {\r
148                 CPDF_Stream* p = (CPDF_Stream*)pObj;\r
149                 if (PDF_CreatorAppendObject(p->GetDict(), pFile, offset) < 0) {\r
150                     return -1;\r
151                 }\r
152                 if (pFile->AppendString(FX_BSTRC("stream\r\n")) < 0) {\r
153                     return -1;\r
154                 }\r
155                 offset += 8;\r
156                 CPDF_StreamAcc acc;\r
157                 acc.LoadAllData(p, TRUE);\r
158                 if (pFile->AppendBlock(acc.GetData(), acc.GetSize()) < 0) {\r
159                     return -1;\r
160                 }\r
161                 offset += acc.GetSize();\r
162                 if ((len = pFile->AppendString(FX_BSTRC("\r\nendstream"))) < 0) {\r
163                     return -1;\r
164                 }\r
165                 offset += len;\r
166                 break;\r
167             }\r
168         default:\r
169             ASSERT(FALSE);\r
170             break;\r
171     }\r
172     return 1;\r
173 }\r
174 FX_INT32 PDF_CreatorWriteTrailer(CPDF_Document* pDocument, CFX_FileBufferArchive* pFile, CPDF_Array* pIDArray, FX_BOOL bCompress)\r
175 {\r
176     FX_FILESIZE offset = 0;\r
177     FX_INT32 len = 0;\r
178     FXSYS_assert(pDocument && pFile);\r
179     CPDF_Parser *pParser = (CPDF_Parser*)pDocument->GetParser();\r
180     if (pParser) {\r
181         CPDF_Dictionary* p = pParser->GetTrailer();\r
182         FX_POSITION pos = p->GetStartPos();\r
183         while (pos) {\r
184             CFX_ByteString key;\r
185             CPDF_Object* pValue = p->GetNextElement(pos, key);\r
186             if (key == FX_BSTRC("Encrypt") || key == FX_BSTRC("Size") || key == FX_BSTRC("Filter") ||\r
187                     key == FX_BSTRC("Index") || key == FX_BSTRC("Length") || key == FX_BSTRC("Prev") ||\r
188                     key == FX_BSTRC("W") || key == FX_BSTRC("XRefStm") || key == FX_BSTRC("Type") || key == FX_BSTRC("ID")) {\r
189                 continue;\r
190             }\r
191             if (bCompress && key == FX_BSTRC("DecodeParms")) {\r
192                 continue;\r
193             }\r
194             if (pFile->AppendString((FX_BSTRC("/"))) < 0) {\r
195                 return -1;\r
196             }\r
197             if ((len = pFile->AppendString(PDF_NameEncode(key))) < 0) {\r
198                 return -1;\r
199             }\r
200             offset += len + 1;\r
201             if (pValue->GetObjNum()) {\r
202                 if (pFile->AppendString(FX_BSTRC(" ")) < 0) {\r
203                     return -1;\r
204                 }\r
205                 if ((len = pFile->AppendDWord(pValue->GetObjNum())) < 0) {\r
206                     return -1;\r
207                 }\r
208                 if (pFile->AppendString(FX_BSTRC(" 0 R ")) < 0) {\r
209                     return -1;\r
210                 }\r
211                 offset += len + 6;\r
212             } else {\r
213                 if (PDF_CreatorAppendObject(pValue, pFile, offset) < 0) {\r
214                     return -1;\r
215                 }\r
216             }\r
217         }\r
218         if (pIDArray) {\r
219             if (pFile->AppendString((FX_BSTRC("/ID"))) < 0) {\r
220                 return -1;\r
221             }\r
222             offset += 3;\r
223             if (PDF_CreatorAppendObject(pIDArray, pFile, offset) < 0) {\r
224                 return -1;\r
225             }\r
226         }\r
227         return offset;\r
228     }\r
229     if (pFile->AppendString(FX_BSTRC("\r\n/Root ")) < 0) {\r
230         return -1;\r
231     }\r
232     if ((len = pFile->AppendDWord(pDocument->GetRoot()->GetObjNum())) < 0) {\r
233         return -1;\r
234     }\r
235     if (pFile->AppendString(FX_BSTRC(" 0 R\r\n")) < 0) {\r
236         return -1;\r
237     }\r
238     offset += len + 14;\r
239     if (pDocument->GetInfo()) {\r
240         if (pFile->AppendString(FX_BSTRC("/Info ")) < 0) {\r
241             return -1;\r
242         }\r
243         if ((len = pFile->AppendDWord(pDocument->GetInfo()->GetObjNum())) < 0) {\r
244             return -1;\r
245         }\r
246         if (pFile->AppendString(FX_BSTRC(" 0 R\r\n")) < 0) {\r
247             return -1;\r
248         }\r
249         offset += len + 12;\r
250     }\r
251     if (pIDArray) {\r
252         if (pFile->AppendString((FX_BSTRC("/ID"))) < 0) {\r
253             return -1;\r
254         }\r
255         offset += 3;\r
256         if (PDF_CreatorAppendObject(pIDArray, pFile, offset) < 0) {\r
257             return -1;\r
258         }\r
259     }\r
260     return offset;\r
261 }\r
262 FX_INT32 PDF_CreatorWriteEncrypt(const CPDF_Dictionary* pEncryptDict, FX_DWORD dwObjNum, CFX_FileBufferArchive *pFile)\r
263 {\r
264     if (!pEncryptDict) {\r
265         return 0;\r
266     }\r
267     FXSYS_assert(pFile);\r
268     FX_FILESIZE offset = 0;\r
269     FX_INT32 len = 0;\r
270     if (pFile->AppendString(FX_BSTRC("/Encrypt")) < 0) {\r
271         return -1;\r
272     }\r
273     offset += 8;\r
274     if (pFile->AppendString(FX_BSTRC(" ")) < 0) {\r
275         return -1;\r
276     }\r
277     if ((len = pFile->AppendDWord(dwObjNum)) < 0) {\r
278         return -1;\r
279     }\r
280     if (pFile->AppendString(FX_BSTRC(" 0 R ")) < 0) {\r
281         return -1;\r
282     }\r
283     offset += len + 6;\r
284     return offset;\r
285 }\r
286 FX_BOOL PDF_GenerateFileID(FX_DWORD dwSeed1, FX_DWORD dwSeed2, FX_LPDWORD pBuffer)\r
287 {\r
288     if (!pBuffer) {\r
289         return FALSE;\r
290     }\r
291     FX_LPVOID pContext = FX_Random_MT_Start(dwSeed1);\r
292     FX_INT32 i = 0;\r
293     for (i = 0; i < 2; i++) {\r
294         *pBuffer++ = FX_Random_MT_Generate(pContext);\r
295     }\r
296     FX_Random_MT_Close(pContext);\r
297     pContext = FX_Random_MT_Start(dwSeed2);\r
298     for (i = 0; i < 2; i++) {\r
299         *pBuffer++ = FX_Random_MT_Generate(pContext);\r
300     }\r
301     FX_Random_MT_Close(pContext);\r
302     return TRUE;\r
303 }\r
304 class CPDF_FlateEncoder\r
305 {\r
306 public:\r
307     CPDF_FlateEncoder();\r
308     ~CPDF_FlateEncoder();\r
309     FX_BOOL             Initialize(CPDF_Stream* pStream, FX_BOOL bFlateEncode);\r
310     FX_BOOL             Initialize(FX_LPCBYTE pBuffer, FX_DWORD size, FX_BOOL bFlateEncode, FX_BOOL bXRefStream = FALSE);\r
311     void                CloneDict();\r
312     FX_LPBYTE                   m_pData;\r
313     FX_DWORD                    m_dwSize;\r
314     CPDF_Dictionary*    m_pDict;\r
315     FX_BOOL                             m_bCloned;\r
316     FX_BOOL                             m_bNewData;\r
317     CPDF_StreamAcc              m_Acc;\r
318 };\r
319 CPDF_FlateEncoder::CPDF_FlateEncoder()\r
320 {\r
321     m_pData = NULL;\r
322     m_dwSize = 0;\r
323     m_pDict = NULL;\r
324     m_bCloned = FALSE;\r
325     m_bNewData = FALSE;\r
326 }\r
327 void CPDF_FlateEncoder::CloneDict()\r
328 {\r
329     if (!m_bCloned) {\r
330         m_pDict = (CPDF_Dictionary*)m_pDict->Clone();\r
331         m_bCloned = TRUE;\r
332     }\r
333 }\r
334 FX_BOOL CPDF_FlateEncoder::Initialize(CPDF_Stream* pStream, FX_BOOL bFlateEncode)\r
335 {\r
336     m_Acc.LoadAllData(pStream, TRUE);\r
337     if (pStream->GetDict()->KeyExist("Filter") || !bFlateEncode) {\r
338         if (pStream->GetDict()->KeyExist("Filter") && !bFlateEncode) {\r
339             CPDF_StreamAcc destAcc;\r
340             destAcc.LoadAllData(pStream);\r
341             m_dwSize = destAcc.GetSize();\r
342             m_pData = (FX_LPBYTE)destAcc.DetachData();\r
343             m_pDict = (CPDF_Dictionary*)pStream->GetDict()->Clone();\r
344             m_pDict->RemoveAt(FX_BSTRC("Filter"));\r
345             m_bNewData = TRUE;\r
346             m_bCloned = TRUE;\r
347         } else {\r
348             m_pData = (FX_LPBYTE)m_Acc.GetData();\r
349             m_dwSize = m_Acc.GetSize();\r
350             m_pDict = pStream->GetDict();\r
351         }\r
352         return TRUE;\r
353     }\r
354     m_pData = NULL;\r
355     m_dwSize = 0;\r
356     m_bNewData = TRUE;\r
357     m_bCloned = TRUE;\r
358     ::FlateEncode(m_Acc.GetData(), m_Acc.GetSize(), m_pData, m_dwSize);\r
359     m_pDict = (CPDF_Dictionary*)pStream->GetDict()->Clone();\r
360     m_pDict->SetAtInteger("Length", m_dwSize);\r
361     m_pDict->SetAtName("Filter", "FlateDecode");\r
362     m_pDict->RemoveAt("DecodeParms");\r
363     return TRUE;\r
364 }\r
365 FX_BOOL CPDF_FlateEncoder::Initialize(FX_LPCBYTE pBuffer, FX_DWORD size, FX_BOOL bFlateEncode, FX_BOOL bXRefStream)\r
366 {\r
367     if (!bFlateEncode) {\r
368         m_pData = (FX_LPBYTE)pBuffer;\r
369         m_dwSize = size;\r
370         return TRUE;\r
371     }\r
372     m_bNewData = TRUE;\r
373     if (bXRefStream) {\r
374         ::FlateEncode(pBuffer, size, 12, 1, 8, 7, m_pData, m_dwSize);\r
375     } else {\r
376         ::FlateEncode(pBuffer, size, m_pData, m_dwSize);\r
377     }\r
378     return TRUE;\r
379 }\r
380 CPDF_FlateEncoder::~CPDF_FlateEncoder()\r
381 {\r
382     if (m_bCloned && m_pDict) {\r
383         m_pDict->Release();\r
384     }\r
385     if (m_bNewData && m_pData) {\r
386         FX_Free(m_pData);\r
387     }\r
388 }\r
389 class CPDF_Encryptor\r
390 {\r
391 public:\r
392     CPDF_Encryptor();\r
393     ~CPDF_Encryptor();\r
394     FX_BOOL             Initialize(CPDF_CryptoHandler* pHandler, int objnum, FX_LPBYTE src_data, FX_DWORD src_size);\r
395     FX_LPBYTE                   m_pData;\r
396     FX_DWORD                    m_dwSize;\r
397     FX_BOOL                             m_bNewBuf;\r
398 };\r
399 CPDF_Encryptor::CPDF_Encryptor()\r
400 {\r
401     m_pData = NULL;\r
402     m_dwSize = 0;\r
403     m_bNewBuf = FALSE;\r
404 }\r
405 FX_BOOL CPDF_Encryptor::Initialize(CPDF_CryptoHandler* pHandler, int objnum, FX_LPBYTE src_data, FX_DWORD src_size)\r
406 {\r
407     if (src_size == 0) {\r
408         return TRUE;\r
409     }\r
410     if (pHandler == NULL) {\r
411         m_pData = (FX_LPBYTE)src_data;\r
412         m_dwSize = src_size;\r
413         m_bNewBuf = FALSE;\r
414         return TRUE;\r
415     }\r
416     m_dwSize = pHandler->EncryptGetSize(objnum, 0, src_data, src_size);\r
417     m_pData = FX_Alloc(FX_BYTE, m_dwSize);\r
418     if(!m_pData) {\r
419         return FALSE;\r
420     }\r
421     pHandler->EncryptContent(objnum, 0, src_data, src_size, m_pData, m_dwSize);\r
422     m_bNewBuf = TRUE;\r
423     return TRUE;\r
424 }\r
425 CPDF_Encryptor::~CPDF_Encryptor()\r
426 {\r
427     if (m_bNewBuf) {\r
428         FX_Free(m_pData);\r
429     }\r
430 }\r
431 CPDF_ObjectStream::CPDF_ObjectStream()\r
432     : m_dwObjNum(0)\r
433     , m_index(0)\r
434 {\r
435 }\r
436 FX_BOOL CPDF_ObjectStream::Start()\r
437 {\r
438     m_ObjNumArray.RemoveAll();\r
439     m_OffsetArray.RemoveAll();\r
440     m_Buffer.Clear();\r
441     m_dwObjNum = 0;\r
442     m_index = 0;\r
443     return TRUE;\r
444 }\r
445 FX_INT32 CPDF_ObjectStream::CompressIndirectObject(FX_DWORD dwObjNum, const CPDF_Object *pObj)\r
446 {\r
447     m_ObjNumArray.Add(dwObjNum);\r
448     m_OffsetArray.Add(m_Buffer.GetLength());\r
449     m_Buffer << pObj;\r
450     return 1;\r
451 }\r
452 FX_INT32 CPDF_ObjectStream::CompressIndirectObject(FX_DWORD dwObjNum, FX_LPCBYTE pBuffer, FX_DWORD dwSize)\r
453 {\r
454     m_ObjNumArray.Add(dwObjNum);\r
455     m_OffsetArray.Add(m_Buffer.GetLength());\r
456     m_Buffer.AppendBlock(pBuffer, dwSize);\r
457     return 1;\r
458 }\r
459 FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator)\r
460 {\r
461     FXSYS_assert(pCreator);\r
462     if (m_ObjNumArray.GetSize() == 0) {\r
463         return 0;\r
464     }\r
465     CFX_FileBufferArchive *pFile = &pCreator->m_File;\r
466     CPDF_CryptoHandler *pHandler = pCreator->m_pCryptoHandler;\r
467     FX_FILESIZE ObjOffset = pCreator->m_Offset;\r
468     if (!m_dwObjNum) {\r
469         m_dwObjNum = ++pCreator->m_dwLastObjNum;\r
470     }\r
471     CFX_ByteTextBuf tempBuffer;\r
472     FX_INT32 iCount = m_ObjNumArray.GetSize();\r
473     for (FX_INT32 i = 0; i < iCount; i++) {\r
474         tempBuffer << m_ObjNumArray.ElementAt(i) << FX_BSTRC(" ") << m_OffsetArray.ElementAt(i) << FX_BSTRC(" ");\r
475     }\r
476     FX_FILESIZE &offset = pCreator->m_Offset;\r
477     FX_INT32 len = pFile->AppendDWord(m_dwObjNum);\r
478     if (len < 0) {\r
479         return -1;\r
480     }\r
481     offset += len;\r
482     if ((len = pFile->AppendString(FX_BSTRC(" 0 obj\r\n<</Type /ObjStm /N "))) < 0) {\r
483         return -1;\r
484     }\r
485     offset += len;\r
486     if ((len = pFile->AppendDWord((FX_DWORD)iCount)) < 0) {\r
487         return -1;\r
488     }\r
489     offset += len;\r
490     if (pFile->AppendString(FX_BSTRC("/First ")) < 0) {\r
491         return -1;\r
492     }\r
493     if ((len = pFile->AppendDWord((FX_DWORD)tempBuffer.GetLength())) < 0) {\r
494         return -1;\r
495     }\r
496     if (pFile->AppendString(FX_BSTRC("/Length ")) < 0) {\r
497         return -1;\r
498     }\r
499     offset += len + 15;\r
500     if (!pCreator->m_bCompress && !pHandler) {\r
501         if ((len = pFile->AppendDWord((FX_DWORD)(tempBuffer.GetLength() + m_Buffer.GetLength()))) < 0) {\r
502             return -1;\r
503         }\r
504         offset += len;\r
505         if ((len = pFile->AppendString(FX_BSTRC(">>stream\r\n"))) < 0) {\r
506             return -1;\r
507         }\r
508         if (pFile->AppendBlock(tempBuffer.GetBuffer(), tempBuffer.GetLength()) < 0) {\r
509             return -1;\r
510         }\r
511         if (pFile->AppendBlock(m_Buffer.GetBuffer(), m_Buffer.GetLength()) < 0) {\r
512             return -1;\r
513         }\r
514         offset += len + tempBuffer.GetLength() + m_Buffer.GetLength();\r
515     } else {\r
516         tempBuffer << m_Buffer;\r
517         CPDF_FlateEncoder encoder;\r
518         encoder.Initialize(tempBuffer.GetBuffer(), tempBuffer.GetLength(), pCreator->m_bCompress);\r
519         CPDF_Encryptor encryptor;\r
520         encryptor.Initialize(pHandler, m_dwObjNum, encoder.m_pData, encoder.m_dwSize);\r
521         if ((len = pFile->AppendDWord(encryptor.m_dwSize)) < 0) {\r
522             return -1;\r
523         }\r
524         offset += len;\r
525         if (pCreator->m_bCompress) {\r
526             if (pFile->AppendString(FX_BSTRC("/Filter /FlateDecode")) < 0) {\r
527                 return -1;\r
528             }\r
529             offset += 20;\r
530         }\r
531         if ((len = pFile->AppendString(FX_BSTRC(">>stream\r\n"))) < 0) {\r
532             return -1;\r
533         }\r
534         if (pFile->AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) {\r
535             return -1;\r
536         }\r
537         offset += len + encryptor.m_dwSize;\r
538     }\r
539     if ((len = pFile->AppendString(FX_BSTRC("\r\nendstream\r\nendobj\r\n"))) < 0) {\r
540         return -1;\r
541     }\r
542     offset += len;\r
543     return ObjOffset;\r
544 }\r
545 CPDF_XRefStream::CPDF_XRefStream()\r
546     : m_PrevOffset(0)\r
547     , m_iSeg(0)\r
548     , m_dwTempObjNum(0)\r
549 {\r
550 }\r
551 FX_BOOL CPDF_XRefStream::Start()\r
552 {\r
553     m_IndexArray.RemoveAll();\r
554     m_Buffer.Clear();\r
555     m_iSeg = 0;\r
556     return TRUE;\r
557 }\r
558 FX_INT32 CPDF_XRefStream::CompressIndirectObject(FX_DWORD dwObjNum, const CPDF_Object *pObj, CPDF_Creator *pCreator)\r
559 {\r
560     if (!pCreator) {\r
561         return 0;\r
562     }\r
563     m_ObjStream.CompressIndirectObject(dwObjNum, pObj);\r
564     if (m_ObjStream.m_ObjNumArray.GetSize() < pCreator->m_ObjectStreamSize &&\r
565             m_ObjStream.m_Buffer.GetLength() < PDF_OBJECTSTREAM_MAXLENGTH) {\r
566         return 1;\r
567     }\r
568     return EndObjectStream(pCreator);\r
569 }\r
570 FX_INT32 CPDF_XRefStream::CompressIndirectObject(FX_DWORD dwObjNum, FX_LPCBYTE pBuffer, FX_DWORD dwSize, CPDF_Creator *pCreator)\r
571 {\r
572     if (!pCreator) {\r
573         return 0;\r
574     }\r
575     m_ObjStream.CompressIndirectObject(dwObjNum, pBuffer, dwSize);\r
576     if (m_ObjStream.m_ObjNumArray.GetSize() < pCreator->m_ObjectStreamSize &&\r
577             m_ObjStream.m_Buffer.GetLength() < PDF_OBJECTSTREAM_MAXLENGTH) {\r
578         return 1;\r
579     }\r
580     return EndObjectStream(pCreator);\r
581 }\r
582 static void _AppendIndex0(CFX_ByteTextBuf& buffer, FX_BOOL bFirstObject =  TRUE)\r
583 {\r
584     buffer.AppendByte(0);\r
585     buffer.AppendByte(0);\r
586     buffer.AppendByte(0);\r
587     buffer.AppendByte(0);\r
588     buffer.AppendByte(0);\r
589     if (bFirstObject) {\r
590         buffer.AppendByte(0xFF);\r
591         buffer.AppendByte(0xFF);\r
592     } else {\r
593         buffer.AppendByte(0);\r
594         buffer.AppendByte(0);\r
595     }\r
596 }\r
597 static void _AppendIndex1(CFX_ByteTextBuf& buffer, FX_FILESIZE offset)\r
598 {\r
599     buffer.AppendByte(1);\r
600     buffer.AppendByte(FX_GETBYTEOFFSET24(offset));\r
601     buffer.AppendByte(FX_GETBYTEOFFSET16(offset));\r
602     buffer.AppendByte(FX_GETBYTEOFFSET8(offset));\r
603     buffer.AppendByte(FX_GETBYTEOFFSET0(offset));\r
604     buffer.AppendByte(0);\r
605     buffer.AppendByte(0);\r
606 }\r
607 static void _AppendIndex2(CFX_ByteTextBuf& buffer, FX_DWORD objnum, FX_INT32 index)\r
608 {\r
609     buffer.AppendByte(2);\r
610     buffer.AppendByte(FX_GETBYTEOFFSET24(objnum));\r
611     buffer.AppendByte(FX_GETBYTEOFFSET16(objnum));\r
612     buffer.AppendByte(FX_GETBYTEOFFSET8(objnum));\r
613     buffer.AppendByte(FX_GETBYTEOFFSET0(objnum));\r
614     buffer.AppendByte(FX_GETBYTEOFFSET8(index));\r
615     buffer.AppendByte(FX_GETBYTEOFFSET0(index));\r
616 }\r
617 FX_INT32 CPDF_XRefStream::EndObjectStream(CPDF_Creator *pCreator, FX_BOOL bEOF)\r
618 {\r
619     FX_FILESIZE objOffset = 0;\r
620     if (bEOF) {\r
621         objOffset = m_ObjStream.End(pCreator);\r
622         if (objOffset < 0) {\r
623             return -1;\r
624         }\r
625     }\r
626     FX_DWORD &dwObjStmNum = m_ObjStream.m_dwObjNum;\r
627     if (!dwObjStmNum) {\r
628         dwObjStmNum = ++pCreator->m_dwLastObjNum;\r
629     }\r
630     FX_INT32 iSize = m_ObjStream.m_ObjNumArray.GetSize();\r
631     FX_INT32 iSeg = m_IndexArray.GetSize() / 2;\r
632     if (!(pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL)) {\r
633         if (m_dwTempObjNum == 0) {\r
634             _AppendIndex0(m_Buffer);\r
635             m_dwTempObjNum++;\r
636         }\r
637         FX_DWORD end_num = m_IndexArray.GetAt((iSeg - 1) * 2) + m_IndexArray.GetAt((iSeg - 1) * 2 + 1);\r
638         int index = 0;\r
639         for (; m_dwTempObjNum < end_num; m_dwTempObjNum++) {\r
640             FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(m_dwTempObjNum);\r
641             if (offset) {\r
642                 if (index >= iSize || m_dwTempObjNum != m_ObjStream.m_ObjNumArray[index]) {\r
643                     _AppendIndex1(m_Buffer, *offset);\r
644                 } else {\r
645                     _AppendIndex2(m_Buffer, dwObjStmNum, index++);\r
646                 }\r
647             } else {\r
648                 _AppendIndex0(m_Buffer, FALSE);\r
649             }\r
650         }\r
651         if (iSize > 0 && bEOF) {\r
652             pCreator->m_ObjectOffset.Add(dwObjStmNum, 1);\r
653             pCreator->m_ObjectSize.Add(dwObjStmNum, 1);\r
654             pCreator->m_ObjectOffset[dwObjStmNum] = objOffset;\r
655         }\r
656         m_iSeg = iSeg;\r
657         if (bEOF) {\r
658             m_ObjStream.Start();\r
659         }\r
660         return 1;\r
661     }\r
662     FX_INT32 &j = m_ObjStream.m_index;\r
663     for (int i = m_iSeg; i < iSeg; i++) {\r
664         FX_DWORD start = m_IndexArray.ElementAt(i * 2);\r
665         FX_DWORD end = m_IndexArray.ElementAt(i * 2 + 1) + start;\r
666         for (FX_DWORD m = start; m < end; m++) {\r
667             if (j >= iSize || m != m_ObjStream.m_ObjNumArray.ElementAt(j)) {\r
668                 _AppendIndex1(m_Buffer, pCreator->m_ObjectOffset[m]);\r
669             } else {\r
670                 _AppendIndex2(m_Buffer, dwObjStmNum, j++);\r
671             }\r
672         }\r
673     }\r
674     if (iSize > 0 && bEOF) {\r
675         _AppendIndex1(m_Buffer, objOffset);\r
676         m_IndexArray.Add(dwObjStmNum);\r
677         m_IndexArray.Add(1);\r
678         iSeg += 1;\r
679     }\r
680     m_iSeg = iSeg;\r
681     if (bEOF) {\r
682         m_ObjStream.Start();\r
683     }\r
684     return 1;\r
685 }\r
686 FX_BOOL CPDF_XRefStream::GenerateXRefStream(CPDF_Creator* pCreator, FX_BOOL bEOF)\r
687 {\r
688     FX_FILESIZE offset_tmp = pCreator->m_Offset;\r
689     FX_DWORD objnum = ++pCreator->m_dwLastObjNum;\r
690     CFX_FileBufferArchive *pFile = &pCreator->m_File;\r
691     FX_BOOL bIncremental = (pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL) != 0;\r
692     if (bIncremental) {\r
693         AddObjectNumberToIndexArray(objnum);\r
694     } else {\r
695         for (; m_dwTempObjNum < pCreator->m_dwLastObjNum; m_dwTempObjNum++) {\r
696             FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(m_dwTempObjNum);\r
697             if (offset) {\r
698                 _AppendIndex1(m_Buffer, *offset);\r
699             } else {\r
700                 _AppendIndex0(m_Buffer, FALSE);\r
701             }\r
702         }\r
703     }\r
704     _AppendIndex1(m_Buffer, offset_tmp);\r
705     FX_FILESIZE &offset = pCreator->m_Offset;\r
706     FX_INT32 len = pFile->AppendDWord(objnum);\r
707     if (len < 0) {\r
708         return FALSE;\r
709     }\r
710     offset += len;\r
711     if ((len = pFile->AppendString(FX_BSTRC(" 0 obj\r\n<</Type /XRef/W[1 4 2]/Index["))) < 0) {\r
712         return FALSE;\r
713     }\r
714     offset += len;\r
715     if (!bIncremental) {\r
716         if ((len = pFile->AppendDWord(0)) < 0) {\r
717             return FALSE;\r
718         }\r
719         if ((len = pFile->AppendString(FX_BSTRC(" "))) < 0) {\r
720             return FALSE;\r
721         }\r
722         offset += len + 1;\r
723         if ((len = pFile->AppendDWord(objnum + 1)) < 0) {\r
724             return FALSE;\r
725         }\r
726         offset += len;\r
727     } else {\r
728         FX_INT32 iSeg = m_IndexArray.GetSize() / 2;\r
729         for (FX_INT32 i = 0; i < iSeg; i++) {\r
730             if ((len = pFile->AppendDWord(m_IndexArray.ElementAt(i * 2))) < 0) {\r
731                 return FALSE;\r
732             }\r
733             if (pFile->AppendString(FX_BSTRC(" ")) < 0) {\r
734                 return FALSE;\r
735             }\r
736             offset += len + 1;\r
737             if ((len = pFile->AppendDWord(m_IndexArray.ElementAt(i * 2 + 1))) < 0) {\r
738                 return FALSE;\r
739             }\r
740             if (pFile->AppendString(FX_BSTRC(" ")) < 0) {\r
741                 return FALSE;\r
742             }\r
743             offset += len + 1;\r
744         }\r
745     }\r
746     if (pFile->AppendString(FX_BSTRC("]/Size ")) < 0) {\r
747         return FALSE;\r
748     }\r
749     if ((len = pFile->AppendDWord(objnum + 1)) < 0) {\r
750         return FALSE;\r
751     }\r
752     offset += len + 7;\r
753     if (m_PrevOffset > 0) {\r
754         if (pFile->AppendString(FX_BSTRC("/Prev ")) < 0) {\r
755             return -1;\r
756         }\r
757         FX_CHAR offset_buf[20];\r
758         FXSYS_memset32(offset_buf, 0, sizeof(offset_buf));\r
759         FXSYS_i64toa(m_PrevOffset, offset_buf, 10);\r
760         FX_INT32 len = (FX_INT32)FXSYS_strlen(offset_buf);\r
761         if (pFile->AppendBlock(offset_buf, len) < 0) {\r
762             return -1;\r
763         }\r
764         offset += len + 6;\r
765     }\r
766     FX_BOOL bPredictor = TRUE;\r
767     CPDF_FlateEncoder encoder;\r
768     encoder.Initialize(m_Buffer.GetBuffer(), m_Buffer.GetLength(), pCreator->m_bCompress, bPredictor);\r
769     if (pCreator->m_bCompress) {\r
770         if (pFile->AppendString(FX_BSTRC("/Filter /FlateDecode")) < 0) {\r
771             return FALSE;\r
772         }\r
773         offset += 20;\r
774         if (bPredictor) {\r
775             if ((len = pFile->AppendString(FX_BSTRC("/DecodeParms<</Columns 7/Predictor 12>>"))) < 0) {\r
776                 return FALSE;\r
777             }\r
778             offset += len;\r
779         }\r
780     }\r
781     if (pFile->AppendString(FX_BSTRC("/Length ")) < 0) {\r
782         return FALSE;\r
783     }\r
784     if ((len = pFile->AppendDWord(encoder.m_dwSize)) < 0) {\r
785         return FALSE;\r
786     }\r
787     offset += len + 8;\r
788     if (bEOF) {\r
789         if ((len = PDF_CreatorWriteTrailer(pCreator->m_pDocument, pFile, pCreator->m_pIDArray, pCreator->m_bCompress)) < 0) {\r
790             return -1;\r
791         }\r
792         offset += len;\r
793         if (pCreator->m_pEncryptDict) {\r
794             FX_DWORD dwEncryptObjNum = pCreator->m_pEncryptDict->GetObjNum();\r
795             if (dwEncryptObjNum == 0) {\r
796                 dwEncryptObjNum = pCreator->m_dwEnryptObjNum;\r
797             }\r
798             if ((len = PDF_CreatorWriteEncrypt(pCreator->m_pEncryptDict, dwEncryptObjNum, pFile)) < 0) {\r
799                 return -1;\r
800             }\r
801             offset += len;\r
802         }\r
803     }\r
804     if ((len = pFile->AppendString(FX_BSTRC(">>stream\r\n"))) < 0) {\r
805         return FALSE;\r
806     }\r
807     offset += len;\r
808     if (pFile->AppendBlock(encoder.m_pData, encoder.m_dwSize) < 0) {\r
809         return FALSE;\r
810     }\r
811     if ((len = pFile->AppendString(FX_BSTRC("\r\nendstream\r\nendobj\r\n"))) < 0) {\r
812         return FALSE;\r
813     }\r
814     offset += encoder.m_dwSize + len;\r
815     m_PrevOffset = offset_tmp;\r
816     return TRUE;\r
817 }\r
818 FX_BOOL CPDF_XRefStream::End(CPDF_Creator *pCreator, FX_BOOL bEOF )\r
819 {\r
820     if (EndObjectStream(pCreator, bEOF) < 0) {\r
821         return FALSE;\r
822     }\r
823     return GenerateXRefStream(pCreator, bEOF);\r
824 }\r
825 FX_BOOL CPDF_XRefStream::EndXRefStream(CPDF_Creator* pCreator)\r
826 {\r
827     if (!(pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL)) {\r
828         _AppendIndex0(m_Buffer);\r
829         for (FX_DWORD i = 1; i < pCreator->m_dwLastObjNum + 1; i++) {\r
830             FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(i);\r
831             if (offset) {\r
832                 _AppendIndex1(m_Buffer, *offset);\r
833             } else {\r
834                 _AppendIndex0(m_Buffer, FALSE);\r
835             }\r
836         }\r
837     } else {\r
838         FX_INT32 iSeg = m_IndexArray.GetSize() / 2;\r
839         for (int i = 0; i < iSeg; i++) {\r
840             FX_DWORD start = m_IndexArray.ElementAt(i * 2);\r
841             FX_DWORD end = m_IndexArray.ElementAt(i * 2 + 1) + start;\r
842             for (FX_DWORD j = start; j < end; j++) {\r
843                 _AppendIndex1(m_Buffer, pCreator->m_ObjectOffset[j]);\r
844             }\r
845         }\r
846     }\r
847     return GenerateXRefStream(pCreator, FALSE);\r
848 }\r
849 FX_BOOL CPDF_XRefStream::AddObjectNumberToIndexArray(FX_DWORD objnum)\r
850 {\r
851     FX_INT32 iSize = m_IndexArray.GetSize();\r
852     if (iSize == 0) {\r
853         m_IndexArray.Add(objnum);\r
854         m_IndexArray.Add(1);\r
855     } else {\r
856         FXSYS_assert(iSize > 1);\r
857         FX_DWORD startobjnum = m_IndexArray.ElementAt(iSize - 2);\r
858         FX_INT32 iCount = m_IndexArray.ElementAt(iSize - 1);\r
859         if (objnum == startobjnum + iCount) {\r
860             m_IndexArray[iSize - 1] = iCount + 1;\r
861         } else {\r
862             m_IndexArray.Add(objnum);\r
863             m_IndexArray.Add(1);\r
864         }\r
865     }\r
866     return TRUE;\r
867 }\r
868 CPDF_Creator::CPDF_Creator(CPDF_Document* pDoc)\r
869 {\r
870     m_pDocument = pDoc;\r
871     m_pParser = (CPDF_Parser*)pDoc->m_pParser;\r
872     m_bCompress = TRUE;\r
873     if (m_pParser) {\r
874         m_pEncryptDict = m_pParser->GetEncryptDict();\r
875         m_pCryptoHandler = m_pParser->GetCryptoHandler();\r
876     } else {\r
877         m_pEncryptDict = NULL;\r
878         m_pCryptoHandler = NULL;\r
879     }\r
880     m_bSecurityChanged = FALSE;\r
881     m_bStandardSecurity = FALSE;\r
882     m_pMetadata = NULL;\r
883     m_bEncryptCloned = FALSE;\r
884     m_bEncryptMetadata = FALSE;\r
885     m_Offset = 0;\r
886     m_iStage = -1;\r
887     m_dwFlags = 0;\r
888     m_Pos = NULL;\r
889     m_XrefStart = 0;\r
890     m_pXRefStream = NULL;\r
891     m_ObjectStreamSize = 200;\r
892     m_dwLastObjNum = m_pDocument->GetLastObjNum();\r
893     m_pIDArray = NULL;\r
894     m_FileVersion = 0;\r
895     m_dwEnryptObjNum = 0;\r
896     m_bNewCrypto = FALSE;\r
897 }\r
898 CPDF_Creator::~CPDF_Creator()\r
899 {\r
900     ResetStandardSecurity();\r
901     if (m_bEncryptCloned && m_pEncryptDict) {\r
902         m_pEncryptDict->Release();\r
903         m_pEncryptDict = NULL;\r
904     }\r
905     Clear();\r
906 }\r
907 static FX_BOOL _IsXRefNeedEnd(CPDF_XRefStream* pXRef, FX_DWORD flag)\r
908 {\r
909     if (!(flag & FPDFCREATE_INCREMENTAL)) {\r
910         return FALSE;\r
911     }\r
912     FX_INT32 iSize = pXRef->m_IndexArray.GetSize() / 2;\r
913     FX_INT32 iCount = 0;\r
914     for (FX_INT32 i = 0; i < iSize; i++) {\r
915         iCount += pXRef->m_IndexArray.ElementAt(i * 2 + 1);\r
916     }\r
917     return (iCount >= PDF_XREFSTREAM_MAXSIZE);\r
918 }\r
919 FX_INT32 CPDF_Creator::WriteIndirectObjectToStream(const CPDF_Object* pObj)\r
920 {\r
921     if (!m_pXRefStream) {\r
922         return 1;\r
923     }\r
924     FX_DWORD objnum = pObj->GetObjNum();\r
925     if (m_pParser && m_pParser->m_ObjVersion.GetSize() > (FX_INT32)objnum && m_pParser->m_ObjVersion[objnum] > 0) {\r
926         return 1;\r
927     }\r
928     if (pObj->GetType() == PDFOBJ_NUMBER) {\r
929         return 1;\r
930     }\r
931     CPDF_Dictionary *pDict = pObj->GetDict();\r
932     if (pObj->GetType() == PDFOBJ_STREAM) {\r
933         if (pDict && pDict->GetString(FX_BSTRC("Type")) == FX_BSTRC("XRef")) {\r
934             return 0;\r
935         }\r
936         return 1;\r
937     }\r
938     if (pDict) {\r
939         if (pDict == m_pDocument->m_pRootDict || pDict == m_pEncryptDict) {\r
940             return 1;\r
941         }\r
942         if (IsSignatureDict(pDict)) {\r
943             return 1;\r
944         }\r
945         if (pDict->GetString(FX_BSTRC("Type")) == FX_BSTRC("Page")) {\r
946             return 1;\r
947         }\r
948     }\r
949     m_pXRefStream->AddObjectNumberToIndexArray(objnum);\r
950     if (m_pXRefStream->CompressIndirectObject(objnum, pObj, this) < 0) {\r
951         return -1;\r
952     }\r
953     if (!_IsXRefNeedEnd(m_pXRefStream, m_dwFlags)) {\r
954         return 0;\r
955     }\r
956     if (!m_pXRefStream->End(this)) {\r
957         return -1;\r
958     }\r
959     if (!m_pXRefStream->Start()) {\r
960         return -1;\r
961     }\r
962     return 0;\r
963 }\r
964 FX_INT32 CPDF_Creator::WriteIndirectObjectToStream(FX_DWORD objnum, FX_LPCBYTE pBuffer, FX_DWORD dwSize)\r
965 {\r
966     if (!m_pXRefStream) {\r
967         return 1;\r
968     }\r
969     m_pXRefStream->AddObjectNumberToIndexArray(objnum);\r
970     FX_INT32 iRet = m_pXRefStream->CompressIndirectObject(objnum, pBuffer, dwSize, this);\r
971     if (iRet < 1) {\r
972         return iRet;\r
973     }\r
974     if (!_IsXRefNeedEnd(m_pXRefStream, m_dwFlags)) {\r
975         return 0;\r
976     }\r
977     if (!m_pXRefStream->End(this)) {\r
978         return -1;\r
979     }\r
980     if (!m_pXRefStream->Start()) {\r
981         return -1;\r
982     }\r
983     return 0;\r
984 }\r
985 FX_INT32 CPDF_Creator::AppendObjectNumberToXRef(FX_DWORD objnum)\r
986 {\r
987     if (!m_pXRefStream) {\r
988         return 1;\r
989     }\r
990     m_pXRefStream->AddObjectNumberToIndexArray(objnum);\r
991     if (!_IsXRefNeedEnd(m_pXRefStream, m_dwFlags)) {\r
992         return 0;\r
993     }\r
994     if (!m_pXRefStream->End(this)) {\r
995         return -1;\r
996     }\r
997     if (!m_pXRefStream->Start()) {\r
998         return -1;\r
999     }\r
1000     return 0;\r
1001 }\r
1002 FX_INT32 CPDF_Creator::WriteStream(const CPDF_Object* pStream, FX_DWORD objnum, CPDF_CryptoHandler* pCrypto)\r
1003 {\r
1004     CPDF_FlateEncoder encoder;\r
1005     encoder.Initialize((CPDF_Stream*)pStream, pStream == m_pMetadata ? FALSE : m_bCompress);\r
1006     CPDF_Encryptor encryptor;\r
1007     if(!encryptor.Initialize(pCrypto, objnum, encoder.m_pData, encoder.m_dwSize)) {\r
1008         return -1;\r
1009     }\r
1010     if ((FX_DWORD)encoder.m_pDict->GetInteger(FX_BSTRC("Length")) != encryptor.m_dwSize) {\r
1011         encoder.CloneDict();\r
1012         encoder.m_pDict->SetAtInteger(FX_BSTRC("Length"), encryptor.m_dwSize);\r
1013     }\r
1014     if (WriteDirectObj(objnum, encoder.m_pDict) < 0) {\r
1015         return -1;\r
1016     }\r
1017     int len = m_File.AppendString(FX_BSTRC("stream\r\n"));\r
1018     if (len < 0) {\r
1019         return -1;\r
1020     }\r
1021     m_Offset += len;\r
1022     if (m_File.AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) {\r
1023         return -1;\r
1024     }\r
1025     m_Offset += encryptor.m_dwSize;\r
1026     if ((len = m_File.AppendString(FX_BSTRC("\r\nendstream"))) < 0) {\r
1027         return -1;\r
1028     }\r
1029     m_Offset += len;\r
1030     return 1;\r
1031 }\r
1032 FX_INT32 CPDF_Creator::WriteIndirectObj(FX_DWORD objnum, const CPDF_Object* pObj)\r
1033 {\r
1034     FX_INT32 len = m_File.AppendDWord(objnum);\r
1035     if (len < 0) {\r
1036         return -1;\r
1037     }\r
1038     m_Offset += len;\r
1039     if ((len = m_File.AppendString(FX_BSTRC(" 0 obj\r\n"))) < 0) {\r
1040         return -1;\r
1041     }\r
1042     m_Offset += len;\r
1043     if (pObj->GetType() == PDFOBJ_STREAM) {\r
1044         CPDF_CryptoHandler *pHandler = NULL;\r
1045         pHandler = (pObj == m_pMetadata && !m_bEncryptMetadata) ? NULL : m_pCryptoHandler;\r
1046         if (WriteStream(pObj, objnum, pHandler) < 0) {\r
1047             return -1;\r
1048         }\r
1049     } else {\r
1050         if (WriteDirectObj(objnum, pObj) < 0) {\r
1051             return -1;\r
1052         }\r
1053     }\r
1054     if ((len = m_File.AppendString(FX_BSTRC("\r\nendobj\r\n"))) < 0) {\r
1055         return -1;\r
1056     }\r
1057     m_Offset += len;\r
1058     if (AppendObjectNumberToXRef(objnum) < 0) {\r
1059         return -1;\r
1060     }\r
1061     return 0;\r
1062 }\r
1063 FX_INT32 CPDF_Creator::WriteIndirectObj(const CPDF_Object* pObj)\r
1064 {\r
1065     FX_INT32 iRet = WriteIndirectObjectToStream(pObj);\r
1066     if (iRet < 1) {\r
1067         return iRet;\r
1068     }\r
1069     return WriteIndirectObj(pObj->GetObjNum(), pObj);\r
1070 }\r
1071 FX_INT32 CPDF_Creator::WriteDirectObj(FX_DWORD objnum, const CPDF_Object* pObj, FX_BOOL bEncrypt)\r
1072 {\r
1073     FX_INT32 len = 0;\r
1074     if (pObj == NULL) {\r
1075         if (m_File.AppendString(FX_BSTRC(" null")) < 0) {\r
1076             return -1;\r
1077         }\r
1078         m_Offset += 5;\r
1079         return 1;\r
1080     }\r
1081     switch (pObj->GetType()) {\r
1082         case PDFOBJ_NULL:\r
1083             if (m_File.AppendString(FX_BSTRC(" null")) < 0) {\r
1084                 return -1;\r
1085             }\r
1086             m_Offset += 5;\r
1087             break;\r
1088         case PDFOBJ_BOOLEAN:\r
1089         case PDFOBJ_NUMBER:\r
1090             if (m_File.AppendString(FX_BSTRC(" ")) < 0) {\r
1091                 return -1;\r
1092             }\r
1093             if ((len = m_File.AppendString(pObj->GetString())) < 0) {\r
1094                 return -1;\r
1095             }\r
1096             m_Offset += len + 1;\r
1097             break;\r
1098         case PDFOBJ_STRING: {\r
1099                 CFX_ByteString str = pObj->GetString();\r
1100                 FX_BOOL bHex = ((CPDF_String*)pObj)->IsHex();\r
1101                 if (m_pCryptoHandler == NULL || !bEncrypt) {\r
1102                     CFX_ByteString content = PDF_EncodeString(str, bHex);\r
1103                     if ((len = m_File.AppendString(content)) < 0) {\r
1104                         return -1;\r
1105                     }\r
1106                     m_Offset += len;\r
1107                     break;\r
1108                 }\r
1109                 CPDF_Encryptor encryptor;\r
1110                 encryptor.Initialize(m_pCryptoHandler, objnum, (FX_LPBYTE)(FX_LPCSTR)str, str.GetLength());\r
1111                 CFX_ByteString content = PDF_EncodeString(CFX_ByteString((FX_LPCSTR)encryptor.m_pData, encryptor.m_dwSize), bHex);\r
1112                 if ((len = m_File.AppendString(content)) < 0) {\r
1113                     return -1;\r
1114                 }\r
1115                 m_Offset += len;\r
1116                 break;\r
1117             }\r
1118         case PDFOBJ_STREAM: {\r
1119                 CPDF_FlateEncoder encoder;\r
1120                 encoder.Initialize((CPDF_Stream*)pObj, m_bCompress);\r
1121                 CPDF_Encryptor encryptor;\r
1122                 CPDF_CryptoHandler* pHandler = m_pCryptoHandler;\r
1123                 encryptor.Initialize(pHandler, objnum, encoder.m_pData, encoder.m_dwSize);\r
1124                 if ((FX_DWORD)encoder.m_pDict->GetInteger(FX_BSTRC("Length")) != encryptor.m_dwSize) {\r
1125                     encoder.CloneDict();\r
1126                     encoder.m_pDict->SetAtInteger(FX_BSTRC("Length"), encryptor.m_dwSize);\r
1127                 }\r
1128                 if (WriteDirectObj(objnum, encoder.m_pDict) < 0) {\r
1129                     return -1;\r
1130                 }\r
1131                 if ((len = m_File.AppendString(FX_BSTRC("stream\r\n"))) < 0) {\r
1132                     return -1;\r
1133                 }\r
1134                 m_Offset += len;\r
1135                 if (m_File.AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) {\r
1136                     return -1;\r
1137                 }\r
1138                 m_Offset += encryptor.m_dwSize;\r
1139                 if ((len = m_File.AppendString(FX_BSTRC("\r\nendstream"))) < 0) {\r
1140                     return -1;\r
1141                 }\r
1142                 m_Offset += len;\r
1143                 break;\r
1144             }\r
1145         case PDFOBJ_NAME: {\r
1146                 if (m_File.AppendString(FX_BSTRC("/")) < 0) {\r
1147                     return -1;\r
1148                 }\r
1149                 CFX_ByteString str = pObj->GetString();\r
1150                 if ((len = m_File.AppendString(PDF_NameEncode(str))) < 0) {\r
1151                     return -1;\r
1152                 }\r
1153                 m_Offset += len + 1;\r
1154                 break;\r
1155             }\r
1156         case PDFOBJ_REFERENCE: {\r
1157                 if (m_File.AppendString(FX_BSTRC(" ")) < 0) {\r
1158                     return -1;\r
1159                 }\r
1160                 CPDF_Reference* p = (CPDF_Reference*)pObj;\r
1161                 if ((len = m_File.AppendDWord(p->GetRefObjNum())) < 0) {\r
1162                     return -1;\r
1163                 }\r
1164                 if (m_File.AppendString(FX_BSTRC(" 0 R")) < 0) {\r
1165                     return -1;\r
1166                 }\r
1167                 m_Offset += len + 5;\r
1168                 break;\r
1169             }\r
1170         case PDFOBJ_ARRAY: {\r
1171                 if (m_File.AppendString(FX_BSTRC("[")) < 0) {\r
1172                     return -1;\r
1173                 }\r
1174                 m_Offset += 1;\r
1175                 CPDF_Array* p = (CPDF_Array*)pObj;\r
1176                 for (FX_DWORD i = 0; i < p->GetCount(); i ++) {\r
1177                     CPDF_Object* pElement = p->GetElement(i);\r
1178                     if (pElement->GetObjNum()) {\r
1179                         if (m_File.AppendString(FX_BSTRC(" ")) < 0) {\r
1180                             return -1;\r
1181                         }\r
1182                         if ((len = m_File.AppendDWord(pElement->GetObjNum())) < 0) {\r
1183                             return -1;\r
1184                         }\r
1185                         if (m_File.AppendString(FX_BSTRC(" 0 R")) < 0) {\r
1186                             return -1;\r
1187                         }\r
1188                         m_Offset += len + 5;\r
1189                     } else {\r
1190                         if (WriteDirectObj(objnum, pElement) < 0) {\r
1191                             return -1;\r
1192                         }\r
1193                     }\r
1194                 }\r
1195                 if (m_File.AppendString(FX_BSTRC("]")) < 0) {\r
1196                     return -1;\r
1197                 }\r
1198                 m_Offset += 1;\r
1199                 break;\r
1200             }\r
1201         case PDFOBJ_DICTIONARY: {\r
1202                 if (m_pCryptoHandler == NULL || pObj == m_pEncryptDict) {\r
1203                     return PDF_CreatorAppendObject(pObj, &m_File, m_Offset);\r
1204                 }\r
1205                 if (m_File.AppendString(FX_BSTRC("<<")) < 0) {\r
1206                     return -1;\r
1207                 }\r
1208                 m_Offset += 2;\r
1209                 CPDF_Dictionary* p = (CPDF_Dictionary*)pObj;\r
1210                 FX_BOOL bSignDict = IsSignatureDict(p);\r
1211                 FX_POSITION pos = p->GetStartPos();\r
1212                 while (pos) {\r
1213                     FX_BOOL bSignValue = FALSE;\r
1214                     CFX_ByteString key;\r
1215                     CPDF_Object* pValue = p->GetNextElement(pos, key);\r
1216                     if (m_File.AppendString(FX_BSTRC("/")) < 0) {\r
1217                         return -1;\r
1218                     }\r
1219                     if ((len = m_File.AppendString(PDF_NameEncode(key))) < 0) {\r
1220                         return -1;\r
1221                     }\r
1222                     m_Offset += len + 1;\r
1223                     if (bSignDict && key == FX_BSTRC("Contents")) {\r
1224                         bSignValue = TRUE;\r
1225                     }\r
1226                     if (pValue->GetObjNum()) {\r
1227                         if (m_File.AppendString(FX_BSTRC(" ")) < 0) {\r
1228                             return -1;\r
1229                         }\r
1230                         if ((len = m_File.AppendDWord(pValue->GetObjNum())) < 0) {\r
1231                             return -1;\r
1232                         }\r
1233                         if (m_File.AppendString(FX_BSTRC(" 0 R ")) < 0) {\r
1234                             return -1;\r
1235                         }\r
1236                         m_Offset += len + 6;\r
1237                     } else {\r
1238                         if (WriteDirectObj(objnum, pValue, !bSignValue) < 0) {\r
1239                             return -1;\r
1240                         }\r
1241                     }\r
1242                 }\r
1243                 if (m_File.AppendString(FX_BSTRC(">>")) < 0) {\r
1244                     return -1;\r
1245                 }\r
1246                 m_Offset += 2;\r
1247                 break;\r
1248             }\r
1249     }\r
1250     return 1;\r
1251 }\r
1252 FX_INT32 CPDF_Creator::WriteOldIndirectObject(FX_DWORD objnum)\r
1253 {\r
1254     if(m_pParser->m_V5Type[objnum] == 0 || m_pParser->m_V5Type[objnum] == 255) {\r
1255         return 0;\r
1256     }\r
1257     m_ObjectOffset[objnum] = m_Offset;\r
1258     FX_LPVOID valuetemp = NULL;\r
1259     FX_BOOL bExistInMap = m_pDocument->m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, valuetemp);\r
1260     FX_BOOL bObjStm = (m_pParser->m_V5Type[objnum] == 2) && m_pEncryptDict && !m_pXRefStream;\r
1261     if(m_pParser->m_bVersionUpdated || m_bSecurityChanged || bExistInMap || bObjStm) {\r
1262         CPDF_Object* pObj = m_pDocument->GetIndirectObject(objnum);\r
1263         if (pObj == NULL) {\r
1264             m_ObjectOffset[objnum] = 0;\r
1265             m_ObjectSize[objnum] = 0;\r
1266             return 0;\r
1267         }\r
1268         if (WriteIndirectObj(pObj)) {\r
1269             return -1;\r
1270         }\r
1271         if (!bExistInMap) {\r
1272             m_pDocument->ReleaseIndirectObject(objnum);\r
1273         }\r
1274     } else {\r
1275         FX_BYTE* pBuffer;\r
1276         FX_DWORD size;\r
1277         m_pParser->GetIndirectBinary(objnum, pBuffer, size);\r
1278         if (pBuffer == NULL) {\r
1279             return 0;\r
1280         }\r
1281         if (m_pParser->m_V5Type[objnum] == 2) {\r
1282             if (m_pXRefStream) {\r
1283                 if (WriteIndirectObjectToStream(objnum, pBuffer, size) < 0) {\r
1284                     FX_Free(pBuffer);\r
1285                     return -1;\r
1286                 }\r
1287             } else {\r
1288                 FX_INT32 len = m_File.AppendDWord(objnum);\r
1289                 if (len < 0) {\r
1290                     return -1;\r
1291                 }\r
1292                 if (m_File.AppendString(FX_BSTRC(" 0 obj ")) < 0) {\r
1293                     return -1;\r
1294                 }\r
1295                 m_Offset += len + 7;\r
1296                 if (m_File.AppendBlock(pBuffer, size) < 0) {\r
1297                     return -1;\r
1298                 }\r
1299                 m_Offset += size;\r
1300                 if (m_File.AppendString(FX_BSTRC("\r\nendobj\r\n")) < 0) {\r
1301                     return -1;\r
1302                 }\r
1303                 m_Offset += 10;\r
1304             }\r
1305         } else {\r
1306             if (m_File.AppendBlock(pBuffer, size) < 0) {\r
1307                 return -1;\r
1308             }\r
1309             m_Offset += size;\r
1310             if(AppendObjectNumberToXRef(objnum) < 0) {\r
1311                 return -1;\r
1312             }\r
1313         }\r
1314         FX_Free(pBuffer);\r
1315     }\r
1316     return 1;\r
1317 }\r
1318 FX_INT32 CPDF_Creator::WriteOldObjs(IFX_Pause *pPause)\r
1319 {\r
1320     FX_DWORD nOldSize = m_pParser->m_CrossRef.GetSize();\r
1321     FX_DWORD objnum = (FX_DWORD)(FX_UINTPTR)m_Pos;\r
1322     for(; objnum < nOldSize; objnum ++) {\r
1323         FX_INT32 iRet = WriteOldIndirectObject(objnum);\r
1324         if (!iRet) {\r
1325             continue;\r
1326         }\r
1327         if (iRet < 0) {\r
1328             return iRet;\r
1329         }\r
1330         m_ObjectSize[objnum] = (FX_DWORD)(m_Offset - m_ObjectOffset[objnum]);\r
1331         if (pPause && pPause->NeedToPauseNow()) {\r
1332             m_Pos = (FX_LPVOID)(FX_UINTPTR)(objnum + 1);\r
1333             return 1;\r
1334         }\r
1335     }\r
1336     return 0;\r
1337 }\r
1338 FX_INT32 CPDF_Creator::WriteNewObjs(FX_BOOL bIncremental, IFX_Pause *pPause)\r
1339 {\r
1340     FX_INT32 iCount = m_NewObjNumArray.GetSize();\r
1341     FX_INT32 index = (FX_INT32)(FX_UINTPTR)m_Pos;\r
1342     while (index < iCount) {\r
1343         FX_DWORD objnum = m_NewObjNumArray.ElementAt(index);\r
1344         CPDF_Object *pObj = NULL;\r
1345         m_pDocument->m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pObj);\r
1346         if (NULL == pObj) {\r
1347             ++index;\r
1348             continue;\r
1349         }\r
1350         m_ObjectOffset[objnum] = m_Offset;\r
1351         if (WriteIndirectObj(pObj)) {\r
1352             return -1;\r
1353         }\r
1354         m_ObjectSize[objnum] = (FX_DWORD)(m_Offset - m_ObjectOffset[objnum]);\r
1355         index++;\r
1356         if (pPause && pPause->NeedToPauseNow()) {\r
1357             m_Pos = (FX_POSITION)(FX_UINTPTR)index;\r
1358             return 1;\r
1359         }\r
1360     }\r
1361     return 0;\r
1362 }\r
1363 void CPDF_Creator::InitOldObjNumOffsets()\r
1364 {\r
1365     if (!m_pParser) {\r
1366         return;\r
1367     }\r
1368     FX_DWORD j = 0;\r
1369     FX_DWORD dwStart = 0;\r
1370     FX_DWORD dwEnd = m_pParser->GetLastObjNum();\r
1371     while (dwStart <= dwEnd) {\r
1372         while (dwStart <= dwEnd && (m_pParser->m_V5Type[dwStart] == 0 || m_pParser->m_V5Type[dwStart] == 255)) {\r
1373             dwStart++;\r
1374         }\r
1375         if (dwStart > dwEnd) {\r
1376             break;\r
1377         }\r
1378         j = dwStart;\r
1379         while (j <= dwEnd && m_pParser->m_V5Type[j] != 0 && m_pParser->m_V5Type[j] != 255) {\r
1380             j++;\r
1381         }\r
1382         m_ObjectOffset.Add(dwStart, j - dwStart);\r
1383         m_ObjectSize.Add(dwStart, j - dwStart);\r
1384         dwStart = j;\r
1385     }\r
1386 }\r
1387 void CPDF_Creator::InitNewObjNumOffsets()\r
1388 {\r
1389     FX_BOOL bIncremental = (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0;\r
1390     FX_BOOL bNoOriginal = (m_dwFlags & FPDFCREATE_NO_ORIGINAL) != 0;\r
1391     FX_DWORD nOldSize = m_pParser ? m_pParser->m_CrossRef.GetSize() : 0;\r
1392     FX_POSITION pos = m_pDocument->m_IndirectObjs.GetStartPosition();\r
1393     while (pos) {\r
1394         size_t key = 0;\r
1395         CPDF_Object* pObj;\r
1396         m_pDocument->m_IndirectObjs.GetNextAssoc(pos, (FX_LPVOID&)key, (FX_LPVOID&)pObj);\r
1397         FX_DWORD objnum = (FX_DWORD)key;\r
1398         if (pObj->GetObjNum() == -1) {\r
1399             continue;\r
1400         }\r
1401         if (bIncremental) {\r
1402             if (!pObj->IsModified()) {\r
1403                 continue;\r
1404             }\r
1405         } else {\r
1406             if (objnum < nOldSize && m_pParser->m_V5Type[objnum] != 0) {\r
1407                 continue;\r
1408             }\r
1409         }\r
1410         AppendNewObjNum(objnum);\r
1411     }\r
1412     FX_INT32 iCount = m_NewObjNumArray.GetSize();\r
1413     if (iCount == 0) {\r
1414         return;\r
1415     }\r
1416     FX_INT32 i = 0;\r
1417     FX_DWORD dwStartObjNum = 0;\r
1418     FX_BOOL bCrossRefValid = m_pParser && m_pParser->GetLastXRefOffset() > 0;\r
1419     while (i < iCount) {\r
1420         dwStartObjNum = m_NewObjNumArray.ElementAt(i);\r
1421         if ((bIncremental && (bNoOriginal || bCrossRefValid)) || !m_ObjectOffset.GetPtrAt(dwStartObjNum)) {\r
1422             break;\r
1423         }\r
1424         i++;\r
1425     }\r
1426     if (i >= iCount) {\r
1427         return;\r
1428     }\r
1429     FX_DWORD dwLastObjNum = dwStartObjNum;\r
1430     i++;\r
1431     FX_BOOL bNewStart = FALSE;\r
1432     for (; i < iCount; i++) {\r
1433         FX_DWORD dwCurObjNum = m_NewObjNumArray.ElementAt(i);\r
1434         FX_BOOL bExist = (dwCurObjNum < nOldSize && m_ObjectOffset.GetPtrAt(dwCurObjNum) != NULL);\r
1435         if (bExist || dwCurObjNum - dwLastObjNum > 1) {\r
1436             if (!bNewStart) {\r
1437                 m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);\r
1438                 m_ObjectSize.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);\r
1439             }\r
1440             dwStartObjNum = dwCurObjNum;\r
1441         }\r
1442         if (bNewStart) {\r
1443             dwStartObjNum = dwCurObjNum;\r
1444         }\r
1445         bNewStart = bExist;\r
1446         dwLastObjNum = dwCurObjNum;\r
1447     }\r
1448     m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);\r
1449     m_ObjectSize.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);\r
1450 }\r
1451 void CPDF_Creator::AppendNewObjNum(FX_DWORD objbum)\r
1452 {\r
1453     FX_INT32 iStart = 0, iFind = 0;\r
1454     FX_INT32 iEnd = m_NewObjNumArray.GetUpperBound();\r
1455     while (iStart <= iEnd) {\r
1456         FX_INT32 iMid = (iStart + iEnd) / 2;\r
1457         FX_DWORD dwMid = m_NewObjNumArray.ElementAt(iMid);\r
1458         if (objbum < dwMid) {\r
1459             iEnd = iMid - 1;\r
1460         } else {\r
1461             if (iMid == iEnd) {\r
1462                 iFind = iMid + 1;\r
1463                 break;\r
1464             }\r
1465             FX_DWORD dwNext = m_NewObjNumArray.ElementAt(iMid + 1);\r
1466             if (objbum < dwNext) {\r
1467                 iFind = iMid + 1;\r
1468                 break;\r
1469             }\r
1470             iStart = iMid + 1;\r
1471         }\r
1472     }\r
1473     m_NewObjNumArray.InsertAt(iFind, objbum);\r
1474 }\r
1475 FX_INT32 CPDF_Creator::WriteDoc_Stage1(IFX_Pause *pPause)\r
1476 {\r
1477     FXSYS_assert(m_iStage > -1 || m_iStage < 20);\r
1478     if (m_iStage == 0) {\r
1479         if (m_pParser == NULL) {\r
1480             m_dwFlags &= ~FPDFCREATE_INCREMENTAL;\r
1481         }\r
1482         if (m_bSecurityChanged && (m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0) {\r
1483             m_dwFlags &= ~FPDFCREATE_INCREMENTAL;\r
1484         }\r
1485         m_pMetadata = m_pDocument->GetRoot()->GetElementValue(FX_BSTRC("Metadata"));\r
1486         if (m_dwFlags & FPDFCREATE_OBJECTSTREAM) {\r
1487             m_pXRefStream = FX_NEW CPDF_XRefStream;\r
1488             m_pXRefStream->Start();\r
1489             if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser) {\r
1490                 FX_FILESIZE prev = m_pParser->GetLastXRefOffset();\r
1491                 m_pXRefStream->m_PrevOffset = prev;\r
1492             }\r
1493         }\r
1494         m_iStage = 10;\r
1495     }\r
1496     if (m_iStage == 10) {\r
1497         if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0) {\r
1498             if (m_File.AppendString(FX_BSTRC("%PDF-1.")) < 0) {\r
1499                 return -1;\r
1500             }\r
1501             m_Offset += 7;\r
1502             FX_INT32 version = 7;\r
1503             if (m_FileVersion) {\r
1504                 version = m_FileVersion;\r
1505             } else if (m_pParser) {\r
1506                 version = m_pParser->GetFileVersion();\r
1507             }\r
1508             FX_INT32 len = m_File.AppendDWord(version % 10);\r
1509             if (len < 0) {\r
1510                 return -1;\r
1511             }\r
1512             m_Offset += len;\r
1513             if ((len = m_File.AppendString(FX_BSTRC("\r\n%\xA1\xB3\xC5\xD7\r\n"))) < 0) {\r
1514                 return -1;\r
1515             }\r
1516             m_Offset += len;\r
1517             InitOldObjNumOffsets();\r
1518             m_iStage = 20;\r
1519         } else {\r
1520             IFX_FileRead* pSrcFile = m_pParser->GetFileAccess();\r
1521             m_Offset = pSrcFile->GetSize();\r
1522             m_Pos = (FX_LPVOID)(FX_UINTPTR)m_Offset;\r
1523             m_iStage = 15;\r
1524         }\r
1525     }\r
1526     if (m_iStage == 15) {\r
1527         if ((m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0 && m_Pos) {\r
1528             IFX_FileRead* pSrcFile = m_pParser->GetFileAccess();\r
1529             FX_BYTE buffer[4096];\r
1530             FX_DWORD src_size = (FX_DWORD)(FX_UINTPTR)m_Pos;\r
1531             while (src_size) {\r
1532                 FX_DWORD block_size = src_size > 4096 ? 4096 : src_size;\r
1533                 if (!pSrcFile->ReadBlock(buffer, m_Offset - src_size, block_size)) {\r
1534                     return -1;\r
1535                 }\r
1536                 if (m_File.AppendBlock(buffer, block_size) < 0) {\r
1537                     return -1;\r
1538                 }\r
1539                 src_size -= block_size;\r
1540                 if (pPause && pPause->NeedToPauseNow()) {\r
1541                     m_Pos = (FX_LPVOID)(FX_UINTPTR)src_size;\r
1542                     return 1;\r
1543                 }\r
1544             }\r
1545         }\r
1546         if ((m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0 && m_pParser->GetLastXRefOffset() == 0) {\r
1547             InitOldObjNumOffsets();\r
1548             FX_DWORD dwEnd = m_pParser->GetLastObjNum();\r
1549             FX_BOOL bObjStm = (m_dwFlags & FPDFCREATE_OBJECTSTREAM) != 0;\r
1550             for (FX_DWORD objnum = 0; objnum <= dwEnd; objnum++) {\r
1551                 if (m_pParser->m_V5Type[objnum] == 0 || m_pParser->m_V5Type[objnum] == 255) {\r
1552                     continue;\r
1553                 }\r
1554                 m_ObjectOffset[objnum] = m_pParser->m_CrossRef[objnum];\r
1555                 if (bObjStm) {\r
1556                     m_pXRefStream->AddObjectNumberToIndexArray(objnum);\r
1557                 }\r
1558             }\r
1559             if (bObjStm) {\r
1560                 m_pXRefStream->EndXRefStream(this);\r
1561                 m_pXRefStream->Start();\r
1562             }\r
1563         }\r
1564         m_iStage = 20;\r
1565     }\r
1566     InitNewObjNumOffsets();\r
1567     return m_iStage;\r
1568 }\r
1569 FX_INT32 CPDF_Creator::WriteDoc_Stage2(IFX_Pause *pPause)\r
1570 {\r
1571     FXSYS_assert(m_iStage >= 20 || m_iStage < 30);\r
1572     if (m_iStage == 20) {\r
1573         if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 && m_pParser) {\r
1574             m_Pos = (FX_LPVOID)(FX_UINTPTR)0;\r
1575             m_iStage = 21;\r
1576         } else {\r
1577             m_iStage = 25;\r
1578         }\r
1579     }\r
1580     if (m_iStage == 21) {\r
1581         FX_INT32 iRet = WriteOldObjs(pPause);\r
1582         if (iRet) {\r
1583             return iRet;\r
1584         }\r
1585         m_iStage = 25;\r
1586     }\r
1587     if (m_iStage == 25) {\r
1588         m_Pos = (FX_LPVOID)(FX_UINTPTR)0;\r
1589         m_iStage = 26;\r
1590     }\r
1591     if (m_iStage == 26) {\r
1592         FX_INT32 iRet = WriteNewObjs((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0, pPause);\r
1593         if (iRet) {\r
1594             return iRet;\r
1595         }\r
1596         m_iStage = 27;\r
1597     }\r
1598     if (m_iStage == 27) {\r
1599         if (NULL != m_pEncryptDict && 0 == m_pEncryptDict->GetObjNum()) {\r
1600             m_dwLastObjNum += 1;\r
1601             FX_FILESIZE saveOffset = m_Offset;\r
1602             if (WriteIndirectObj(m_dwLastObjNum, m_pEncryptDict) < 0) {\r
1603                 return -1;\r
1604             }\r
1605             m_ObjectOffset.Add(m_dwLastObjNum, 1);\r
1606             m_ObjectOffset[m_dwLastObjNum] = saveOffset;\r
1607             m_ObjectSize.Add(m_dwLastObjNum, 1);\r
1608             m_ObjectSize[m_dwLastObjNum] = m_Offset - saveOffset;\r
1609             m_dwEnryptObjNum = m_dwLastObjNum;\r
1610             if (m_dwFlags & FPDFCREATE_INCREMENTAL) {\r
1611                 m_NewObjNumArray.Add(m_dwLastObjNum);\r
1612             }\r
1613         }\r
1614         m_iStage = 80;\r
1615     }\r
1616     return m_iStage;\r
1617 }\r
1618 FX_INT32 CPDF_Creator::WriteDoc_Stage3(IFX_Pause *pPause)\r
1619 {\r
1620     FXSYS_assert(m_iStage >= 80 || m_iStage < 90);\r
1621     FX_DWORD dwLastObjNum = m_dwLastObjNum;\r
1622     if (m_iStage == 80) {\r
1623         m_XrefStart = m_Offset;\r
1624         if (m_dwFlags & FPDFCREATE_OBJECTSTREAM) {\r
1625             m_pXRefStream->End(this, TRUE);\r
1626             m_XrefStart = m_pXRefStream->m_PrevOffset;\r
1627             m_iStage = 90;\r
1628         } else if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 || !m_pParser->IsXRefStream()) {\r
1629             if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 || m_pParser->GetLastXRefOffset() == 0) {\r
1630                 CFX_ByteString str;\r
1631                 str = m_ObjectOffset.GetPtrAt(1) ? FX_BSTRC("xref\r\n") : FX_BSTRC("xref\r\n0 1\r\n0000000000 65536 f\r\n");\r
1632                 if (m_File.AppendString(str) < 0) {\r
1633                     return -1;\r
1634                 }\r
1635                 m_Pos = (FX_LPVOID)(FX_UINTPTR)1;\r
1636                 m_iStage = 81;\r
1637             } else {\r
1638                 if (m_File.AppendString(FX_BSTRC("xref\r\n")) < 0) {\r
1639                     return -1;\r
1640                 }\r
1641                 m_Pos = (FX_LPVOID)(FX_UINTPTR)0;\r
1642                 m_iStage = 82;\r
1643             }\r
1644         } else {\r
1645             m_iStage = 90;\r
1646         }\r
1647     }\r
1648     if (m_iStage == 81) {\r
1649         CFX_ByteString str;\r
1650         FX_DWORD i = (FX_DWORD)(FX_UINTPTR)m_Pos, j;\r
1651         while (i <= dwLastObjNum) {\r
1652             while (i <= dwLastObjNum && !m_ObjectOffset.GetPtrAt(i)) {\r
1653                 i++;\r
1654             }\r
1655             if (i > dwLastObjNum) {\r
1656                 break;\r
1657             }\r
1658             j = i;\r
1659             while (j <= dwLastObjNum && m_ObjectOffset.GetPtrAt(j)) {\r
1660                 j++;\r
1661             }\r
1662             if (i == 1) {\r
1663                 str.Format("0 %d\r\n0000000000 65536 f\r\n", j);\r
1664             } else {\r
1665                 str.Format("%d %d\r\n", i, j - i);\r
1666             }\r
1667             if (m_File.AppendBlock((FX_LPCSTR)str, str.GetLength()) < 0) {\r
1668                 return -1;\r
1669             }\r
1670             while (i < j) {\r
1671                 str.Format("%010d 00000 n\r\n", m_ObjectOffset[i ++]);\r
1672                 if (m_File.AppendBlock((FX_LPCSTR)str, str.GetLength()) < 0) {\r
1673                     return -1;\r
1674                 }\r
1675             }\r
1676             if (i > dwLastObjNum) {\r
1677                 break;\r
1678             }\r
1679             if (pPause && pPause->NeedToPauseNow()) {\r
1680                 m_Pos = (FX_LPVOID)(FX_UINTPTR)i;\r
1681                 return 1;\r
1682             }\r
1683         }\r
1684         m_iStage = 90;\r
1685     }\r
1686     if (m_iStage == 82) {\r
1687         CFX_ByteString str;\r
1688         FX_INT32 iCount = m_NewObjNumArray.GetSize();\r
1689         FX_INT32 i = (FX_INT32)(FX_UINTPTR)m_Pos;\r
1690         while (i < iCount) {\r
1691             FX_INT32 j = i;\r
1692             FX_DWORD objnum = m_NewObjNumArray.ElementAt(i);\r
1693             while (j < iCount) {\r
1694                 if (++j == iCount) {\r
1695                     break;\r
1696                 }\r
1697                 FX_DWORD dwCurrent = m_NewObjNumArray.ElementAt(j);\r
1698                 if (dwCurrent - objnum > 1) {\r
1699                     break;\r
1700                 }\r
1701                 objnum = dwCurrent;\r
1702             }\r
1703             objnum = m_NewObjNumArray.ElementAt(i);\r
1704             if (objnum == 1) {\r
1705                 str.Format("0 %d\r\n0000000000 65536 f\r\n", j - i + 1);\r
1706             } else {\r
1707                 str.Format("%d %d\r\n", objnum, j - i);\r
1708             }\r
1709             if (m_File.AppendBlock((FX_LPCSTR)str, str.GetLength()) < 0) {\r
1710                 return -1;\r
1711             }\r
1712             while (i < j) {\r
1713                 objnum = m_NewObjNumArray.ElementAt(i++);\r
1714                 str.Format("%010d 00000 n\r\n", m_ObjectOffset[objnum]);\r
1715                 if (m_File.AppendBlock((FX_LPCSTR)str, str.GetLength()) < 0) {\r
1716                     return -1;\r
1717                 }\r
1718             }\r
1719             if (pPause && (i % 100) == 0 && pPause->NeedToPauseNow()) {\r
1720                 m_Pos = (FX_LPVOID)(FX_UINTPTR)i;\r
1721                 return 1;\r
1722             }\r
1723         }\r
1724         m_iStage = 90;\r
1725     }\r
1726     return m_iStage;\r
1727 }\r
1728 static FX_INT32 _OutPutIndex(CFX_FileBufferArchive* pFile, FX_FILESIZE offset)\r
1729 {\r
1730     FXSYS_assert(pFile);\r
1731     if (sizeof(offset) > 4) {\r
1732         if (FX_GETBYTEOFFSET32(offset)) {\r
1733             if (pFile->AppendByte(FX_GETBYTEOFFSET56(offset)) < 0) {\r
1734                 return -1;\r
1735             }\r
1736             if (pFile->AppendByte(FX_GETBYTEOFFSET48(offset)) < 0) {\r
1737                 return -1;\r
1738             }\r
1739             if (pFile->AppendByte(FX_GETBYTEOFFSET40(offset)) < 0) {\r
1740                 return -1;\r
1741             }\r
1742             if (pFile->AppendByte(FX_GETBYTEOFFSET32(offset)) < 0) {\r
1743                 return -1;\r
1744             }\r
1745         }\r
1746     }\r
1747     if (pFile->AppendByte(FX_GETBYTEOFFSET24(offset)) < 0) {\r
1748         return -1;\r
1749     }\r
1750     if (pFile->AppendByte(FX_GETBYTEOFFSET16(offset)) < 0) {\r
1751         return -1;\r
1752     }\r
1753     if (pFile->AppendByte(FX_GETBYTEOFFSET8(offset)) < 0) {\r
1754         return -1;\r
1755     }\r
1756     if (pFile->AppendByte(FX_GETBYTEOFFSET0(offset)) < 0) {\r
1757         return -1;\r
1758     }\r
1759     if (pFile->AppendByte(0) < 0) {\r
1760         return -1;\r
1761     }\r
1762     return 0;\r
1763 }\r
1764 FX_INT32 CPDF_Creator::WriteDoc_Stage4(IFX_Pause *pPause)\r
1765 {\r
1766     FXSYS_assert(m_iStage >= 90);\r
1767     if ((m_dwFlags & FPDFCREATE_OBJECTSTREAM) == 0) {\r
1768         FX_BOOL bXRefStream = (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser->IsXRefStream();\r
1769         if (!bXRefStream) {\r
1770             if (m_File.AppendString(FX_BSTRC("trailer\r\n<<")) < 0) {\r
1771                 return -1;\r
1772             }\r
1773         } else {\r
1774             if (m_File.AppendDWord(m_pDocument->m_LastObjNum + 1) < 0) {\r
1775                 return -1;\r
1776             }\r
1777             if (m_File.AppendString(FX_BSTRC(" 0 obj <<")) < 0) {\r
1778                 return -1;\r
1779             }\r
1780         }\r
1781         if (m_pParser) {\r
1782             CPDF_Dictionary* p = m_pParser->m_pTrailer;\r
1783             FX_POSITION pos = p->GetStartPos();\r
1784             while (pos) {\r
1785                 CFX_ByteString key;\r
1786                 CPDF_Object* pValue = p->GetNextElement(pos, key);\r
1787                 if (key == FX_BSTRC("Encrypt") || key == FX_BSTRC("Size") || key == FX_BSTRC("Filter") ||\r
1788                         key == FX_BSTRC("Index") || key == FX_BSTRC("Length") || key == FX_BSTRC("Prev") ||\r
1789                         key == FX_BSTRC("W") || key == FX_BSTRC("XRefStm") || key == FX_BSTRC("ID")) {\r
1790                     continue;\r
1791                 }\r
1792                 if (m_File.AppendString((FX_BSTRC("/"))) < 0) {\r
1793                     return -1;\r
1794                 }\r
1795                 if (m_File.AppendString(PDF_NameEncode(key)) < 0) {\r
1796                     return -1;\r
1797                 }\r
1798                 if (pValue->GetObjNum()) {\r
1799                     if (m_File.AppendString(FX_BSTRC(" ")) < 0) {\r
1800                         return -1;\r
1801                     }\r
1802                     if (m_File.AppendDWord(pValue->GetObjNum()) < 0) {\r
1803                         return -1;\r
1804                     }\r
1805                     if (m_File.AppendString(FX_BSTRC(" 0 R ")) < 0) {\r
1806                         return -1;\r
1807                     }\r
1808                 } else {\r
1809                     FX_FILESIZE offset = 0;\r
1810                     if (PDF_CreatorAppendObject(pValue, &m_File, offset) < 0) {\r
1811                         return -1;\r
1812                     }\r
1813                 }\r
1814             }\r
1815         } else {\r
1816             if (m_File.AppendString(FX_BSTRC("\r\n/Root ")) < 0) {\r
1817                 return -1;\r
1818             }\r
1819             if (m_File.AppendDWord(m_pDocument->m_pRootDict->GetObjNum()) < 0) {\r
1820                 return -1;\r
1821             }\r
1822             if (m_File.AppendString(FX_BSTRC(" 0 R\r\n")) < 0) {\r
1823                 return -1;\r
1824             }\r
1825             if (m_pDocument->m_pInfoDict) {\r
1826                 if (m_File.AppendString(FX_BSTRC("/Info ")) < 0) {\r
1827                     return -1;\r
1828                 }\r
1829                 if (m_File.AppendDWord(m_pDocument->m_pInfoDict->GetObjNum()) < 0) {\r
1830                     return -1;\r
1831                 }\r
1832                 if (m_File.AppendString(FX_BSTRC(" 0 R\r\n")) < 0) {\r
1833                     return -1;\r
1834                 }\r
1835             }\r
1836         }\r
1837         if (m_pEncryptDict) {\r
1838             if (m_File.AppendString(FX_BSTRC("/Encrypt")) < 0) {\r
1839                 return -1;\r
1840             }\r
1841             FX_DWORD dwObjNum = m_pEncryptDict->GetObjNum();\r
1842             if (dwObjNum == 0) {\r
1843                 dwObjNum = m_pDocument->GetLastObjNum() + 1;\r
1844             }\r
1845             if (m_File.AppendString(FX_BSTRC(" ")) < 0) {\r
1846                 return -1;\r
1847             }\r
1848             if (m_File.AppendDWord(dwObjNum) < 0) {\r
1849                 return -1;\r
1850             }\r
1851             if (m_File.AppendString(FX_BSTRC(" 0 R ")) < 0) {\r
1852                 return -1;\r
1853             }\r
1854         }\r
1855         if (m_File.AppendString(FX_BSTRC("/Size ")) < 0) {\r
1856             return -1;\r
1857         }\r
1858         if (m_File.AppendDWord(m_dwLastObjNum + (bXRefStream ? 2 : 1)) < 0) {\r
1859             return -1;\r
1860         }\r
1861         if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0) {\r
1862             FX_FILESIZE prev = m_pParser->GetLastXRefOffset();\r
1863             if (prev) {\r
1864                 if (m_File.AppendString(FX_BSTRC("/Prev ")) < 0) {\r
1865                     return -1;\r
1866                 }\r
1867                 FX_CHAR offset_buf[20];\r
1868                 FXSYS_memset32(offset_buf, 0, sizeof(offset_buf));\r
1869                 FXSYS_i64toa(prev, offset_buf, 10);\r
1870                 if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) {\r
1871                     return -1;\r
1872                 }\r
1873             }\r
1874         }\r
1875         if (m_pIDArray) {\r
1876             if (m_File.AppendString((FX_BSTRC("/ID"))) < 0) {\r
1877                 return -1;\r
1878             }\r
1879             FX_FILESIZE offset = 0;\r
1880             if (PDF_CreatorAppendObject(m_pIDArray, &m_File, offset) < 0) {\r
1881                 return -1;\r
1882             }\r
1883         }\r
1884         if (!bXRefStream) {\r
1885             if (m_File.AppendString(FX_BSTRC(">>")) < 0) {\r
1886                 return -1;\r
1887             }\r
1888         } else {\r
1889             if (m_File.AppendString(FX_BSTRC("/W[0 4 1]/Index[")) < 0) {\r
1890                 return -1;\r
1891             }\r
1892             if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser && m_pParser->GetLastXRefOffset() == 0) {\r
1893                 FX_DWORD i = 0;\r
1894                 for (i = 0; i < m_dwLastObjNum; i++) {\r
1895                     if (!m_ObjectOffset.GetPtrAt(i)) {\r
1896                         continue;\r
1897                     }\r
1898                     if (m_File.AppendDWord(i) < 0) {\r
1899                         return -1;\r
1900                     }\r
1901                     if (m_File.AppendString(FX_BSTRC(" 1 ")) < 0) {\r
1902                         return -1;\r
1903                     }\r
1904                 }\r
1905                 if (m_File.AppendString(FX_BSTRC("]/Length ")) < 0) {\r
1906                     return -1;\r
1907                 }\r
1908                 if (m_File.AppendDWord(m_dwLastObjNum * 5) < 0) {\r
1909                     return -1;\r
1910                 }\r
1911                 if (m_File.AppendString(FX_BSTRC(">>stream\r\n")) < 0) {\r
1912                     return -1;\r
1913                 }\r
1914                 for (i = 0; i < m_dwLastObjNum; i++) {\r
1915                     FX_FILESIZE* offset = m_ObjectOffset.GetPtrAt(i);\r
1916                     if (!offset) {\r
1917                         continue;\r
1918                     }\r
1919                     _OutPutIndex(&m_File, *offset);\r
1920                 }\r
1921             } else {\r
1922                 int count = m_NewObjNumArray.GetSize();\r
1923                 FX_INT32 i = 0;\r
1924                 for (i = 0; i < count; i++) {\r
1925                     FX_DWORD objnum = m_NewObjNumArray.ElementAt(i);\r
1926                     if (m_File.AppendDWord(objnum) < 0) {\r
1927                         return -1;\r
1928                     }\r
1929                     if (m_File.AppendString(FX_BSTRC(" 1 ")) < 0) {\r
1930                         return -1;\r
1931                     }\r
1932                 }\r
1933                 if (m_File.AppendString(FX_BSTRC("]/Length ")) < 0) {\r
1934                     return -1;\r
1935                 }\r
1936                 if (m_File.AppendDWord(count * 5) < 0) {\r
1937                     return -1;\r
1938                 }\r
1939                 if (m_File.AppendString(FX_BSTRC(">>stream\r\n")) < 0) {\r
1940                     return -1;\r
1941                 }\r
1942                 for (i = 0; i < count; i++) {\r
1943                     FX_DWORD objnum = m_NewObjNumArray.ElementAt(i);\r
1944                     FX_FILESIZE offset = m_ObjectOffset[objnum];\r
1945                     _OutPutIndex(&m_File, offset);\r
1946                 }\r
1947             }\r
1948             if (m_File.AppendString(FX_BSTRC("\r\nendstream")) < 0) {\r
1949                 return -1;\r
1950             }\r
1951         }\r
1952     }\r
1953     if (m_File.AppendString(FX_BSTRC("\r\nstartxref\r\n")) < 0) {\r
1954         return -1;\r
1955     }\r
1956     FX_CHAR offset_buf[20];\r
1957     FXSYS_memset32(offset_buf, 0, sizeof(offset_buf));\r
1958     FXSYS_i64toa(m_XrefStart, offset_buf, 10);\r
1959     if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) {\r
1960         return -1;\r
1961     }\r
1962     if (m_File.AppendString(FX_BSTRC("\r\n%%EOF\r\n")) < 0) {\r
1963         return -1;\r
1964     }\r
1965     m_File.Flush();\r
1966     return m_iStage = 100;\r
1967 }\r
1968 void CPDF_Creator::Clear()\r
1969 {\r
1970     if (m_pXRefStream) {\r
1971         delete m_pXRefStream;\r
1972         m_pXRefStream = NULL;\r
1973     }\r
1974     m_File.Clear();\r
1975     m_NewObjNumArray.RemoveAll();\r
1976     if (m_pIDArray) {\r
1977         m_pIDArray->Release();\r
1978         m_pIDArray = NULL;\r
1979     }\r
1980 }\r
1981 FX_BOOL CPDF_Creator::Create(FX_LPCSTR filename, FX_DWORD flags)\r
1982 {\r
1983     if (!m_File.AttachFile(filename)) {\r
1984         return FALSE;\r
1985     }\r
1986     FX_BOOL bRet = Create(flags);\r
1987     if (!bRet || !(flags & FPDFCREATE_PROGRESSIVE)) {\r
1988         Clear();\r
1989     }\r
1990     return bRet;\r
1991 }\r
1992 FX_BOOL CPDF_Creator::Create(FX_LPCWSTR filename, FX_DWORD flags)\r
1993 {\r
1994     if (!m_File.AttachFile(filename)) {\r
1995         return FALSE;\r
1996     }\r
1997     FX_BOOL bRet = Create(flags);\r
1998     if (!bRet || !(flags & FPDFCREATE_PROGRESSIVE)) {\r
1999         Clear();\r
2000     }\r
2001     return bRet;\r
2002 }\r
2003 FX_BOOL CPDF_Creator::Create(IFX_StreamWrite* pFile, FX_DWORD flags)\r
2004 {\r
2005     if (!pFile) {\r
2006         return FALSE;\r
2007     }\r
2008     if (!m_File.AttachFile(pFile, FALSE)) {\r
2009         return FALSE;\r
2010     }\r
2011     return Create(flags);\r
2012 }\r
2013 FX_BOOL CPDF_Creator::Create(FX_DWORD flags)\r
2014 {\r
2015     m_dwFlags = flags;\r
2016     m_iStage = 0;\r
2017     m_Offset = 0;\r
2018     m_dwLastObjNum = m_pDocument->GetLastObjNum();\r
2019     m_ObjectOffset.Clear();\r
2020     m_ObjectSize.Clear();\r
2021     m_NewObjNumArray.RemoveAll();\r
2022     InitID();\r
2023     if (flags & FPDFCREATE_PROGRESSIVE) {\r
2024         return TRUE;\r
2025     }\r
2026     return Continue(NULL) > -1;\r
2027 }\r
2028 void CPDF_Creator::InitID(FX_BOOL bDefault )\r
2029 {\r
2030     CPDF_Array* pOldIDArray = m_pParser ? m_pParser->GetIDArray() : NULL;\r
2031     FX_BOOL bNewId = !m_pIDArray;\r
2032     if (!m_pIDArray) {\r
2033         FX_LPDWORD pBuffer = NULL;\r
2034         m_pIDArray = CPDF_Array::Create();\r
2035         CPDF_Object* pID1 = pOldIDArray->GetElement(0);\r
2036         if (pID1) {\r
2037             m_pIDArray->Add(pID1->Clone());\r
2038         } else {\r
2039             pBuffer = FX_Alloc(FX_DWORD, 4);\r
2040             PDF_GenerateFileID((FX_DWORD)(FX_UINTPTR)this, m_dwLastObjNum, pBuffer);\r
2041             CFX_ByteStringC bsBuffer((FX_LPCBYTE)pBuffer, 4 * sizeof(FX_DWORD));\r
2042             m_pIDArray->Add(CPDF_String::Create(bsBuffer, TRUE), m_pDocument);\r
2043         }\r
2044         if (pBuffer) {\r
2045             FX_Free(pBuffer);\r
2046         }\r
2047     }\r
2048     if (!bDefault) {\r
2049         return;\r
2050     }\r
2051     if (pOldIDArray) {\r
2052         CPDF_Object* pID2 = pOldIDArray->GetElement(1);\r
2053         if ((m_dwFlags & FPDFCREATE_INCREMENTAL) && m_pEncryptDict && pID2) {\r
2054             m_pIDArray->Add(pID2->Clone());\r
2055             return;\r
2056         }\r
2057         FX_LPDWORD pBuffer = FX_Alloc(FX_DWORD, 4);\r
2058         PDF_GenerateFileID((FX_DWORD)(FX_UINTPTR)this, m_dwLastObjNum, pBuffer);\r
2059         CFX_ByteStringC bsBuffer((FX_LPCBYTE)pBuffer, 4 * sizeof(FX_DWORD));\r
2060         m_pIDArray->Add(CPDF_String::Create(bsBuffer, TRUE), m_pDocument);\r
2061         FX_Free(pBuffer);\r
2062         return;\r
2063     }\r
2064     m_pIDArray->Add(m_pIDArray->GetElement(0)->Clone());\r
2065     if (m_pEncryptDict && !pOldIDArray && m_pParser && bNewId) {\r
2066         if (m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) {\r
2067             CPDF_StandardSecurityHandler handler;\r
2068             CFX_ByteString user_pass = m_pParser->GetPassword();\r
2069             FX_DWORD flag = PDF_ENCRYPT_CONTENT;\r
2070             handler.OnCreate(m_pEncryptDict, m_pIDArray, (FX_LPCBYTE)user_pass, user_pass.GetLength(), flag);\r
2071             if (m_pCryptoHandler && m_bNewCrypto) {\r
2072                 delete m_pCryptoHandler;\r
2073             }\r
2074             m_pCryptoHandler = FX_NEW CPDF_StandardCryptoHandler;\r
2075             m_pCryptoHandler->Init(m_pEncryptDict, &handler);\r
2076             m_bNewCrypto = TRUE;\r
2077             m_bSecurityChanged = TRUE;\r
2078         }\r
2079     }\r
2080 }\r
2081 FX_INT32 CPDF_Creator::Continue(IFX_Pause *pPause)\r
2082 {\r
2083     if (m_iStage < 0) {\r
2084         return m_iStage;\r
2085     }\r
2086     FX_INT32 iRet;\r
2087     while (m_iStage < 100) {\r
2088         if (m_iStage < 20) {\r
2089             iRet = WriteDoc_Stage1(pPause);\r
2090         } else if (m_iStage < 30) {\r
2091             iRet = WriteDoc_Stage2(pPause);\r
2092         } else if (m_iStage < 90) {\r
2093             iRet = WriteDoc_Stage3(pPause);\r
2094         } else {\r
2095             iRet = WriteDoc_Stage4(pPause);\r
2096         }\r
2097         if (iRet < m_iStage) {\r
2098             break;\r
2099         }\r
2100     }\r
2101     if (iRet < 1 || m_iStage == 100) {\r
2102         m_iStage = -1;\r
2103         Clear();\r
2104         return iRet > 99 ? 0 : (iRet < 1 ? -1 : iRet);\r
2105     }\r
2106     return m_iStage;\r
2107 }\r
2108 FX_BOOL CPDF_Creator::SetFileVersion(FX_INT32 fileVersion )\r
2109 {\r
2110     if (fileVersion < 10 || fileVersion > 17) {\r
2111         return FALSE;\r
2112     }\r
2113     m_FileVersion = fileVersion;\r
2114     return TRUE;\r
2115 }\r
2116 void CPDF_Creator::ResetStandardSecurity()\r
2117 {\r
2118     if ((m_bStandardSecurity || m_bNewCrypto) && m_pCryptoHandler) {\r
2119         delete m_pCryptoHandler;\r
2120         m_pCryptoHandler = NULL;\r
2121     }\r
2122     m_bNewCrypto = FALSE;\r
2123     if (!m_bStandardSecurity) {\r
2124         return;\r
2125     }\r
2126     if (m_pEncryptDict) {\r
2127         m_pEncryptDict->Release();\r
2128         m_pEncryptDict = NULL;\r
2129     }\r
2130     m_bStandardSecurity = FALSE;\r
2131 }\r