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