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