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