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
45 namespace {
46
PDF_CreatorAppendObject(const CPDF_Object * pObj,CFX_FileBufferArchive * pFile,FX_FILESIZE & offset)47 int32_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
PDF_CreatorWriteTrailer(CPDF_Document * pDocument,CFX_FileBufferArchive * pFile,CPDF_Array * pIDArray)204 int32_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
PDF_CreatorWriteEncrypt(const CPDF_Dictionary * pEncryptDict,uint32_t dwObjNum,CFX_FileBufferArchive * pFile)292 int32_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
PDF_GenerateFileID(uint32_t dwSeed1,uint32_t dwSeed2)318 std::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
AppendIndex0(CFX_ByteTextBuf & buffer,bool bFirstObject)332 void 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
AppendIndex1(CFX_ByteTextBuf & buffer,FX_FILESIZE offset)343 void 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
AppendIndex2(CFX_ByteTextBuf & buffer,uint32_t objnum,int32_t index)353 void 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
IsXRefNeedEnd(CPDF_XRefStream * pXRef,uint32_t flag)363 bool 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
OutputIndex(CFX_FileBufferArchive * pFile,FX_FILESIZE offset)374 int32_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
400 class 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
CloneDict()417 void CPDF_FlateEncoder::CloneDict() {
418 if (m_pDict.IsOwned())
419 return;
420 m_pDict = ToDictionary(m_pDict->Clone());
421 ASSERT(m_pDict.IsOwned());
422 }
423
CPDF_FlateEncoder(CPDF_Stream * pStream,bool bFlateEncode)424 CPDF_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
CPDF_FlateEncoder(const uint8_t * pBuffer,uint32_t size,bool bFlateEncode,bool bXRefStream)453 CPDF_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
~CPDF_FlateEncoder()472 CPDF_FlateEncoder::~CPDF_FlateEncoder() {}
473
474 class 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
CPDF_Encryptor(CPDF_CryptoHandler * pHandler,int objnum,uint8_t * src_data,uint32_t src_size)487 CPDF_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
~CPDF_Encryptor()506 CPDF_Encryptor::~CPDF_Encryptor() {
507 if (m_bNewBuf)
508 FX_Free(m_pData);
509 }
510
511 } // namespace
512
CPDF_ObjectStream()513 CPDF_ObjectStream::CPDF_ObjectStream() : m_dwObjNum(0), m_index(0) {}
514
~CPDF_ObjectStream()515 CPDF_ObjectStream::~CPDF_ObjectStream() {}
516
Start()517 void CPDF_ObjectStream::Start() {
518 m_Items.clear();
519 m_Buffer.Clear();
520 m_dwObjNum = 0;
521 m_index = 0;
522 }
523
CompressIndirectObject(uint32_t dwObjNum,const CPDF_Object * pObj)524 void 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
CompressIndirectObject(uint32_t dwObjNum,const uint8_t * pBuffer,uint32_t dwSize)530 void 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
End(CPDF_Creator * pCreator)537 FX_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
CPDF_XRefStream()604 CPDF_XRefStream::CPDF_XRefStream()
605 : m_PrevOffset(0), m_dwTempObjNum(0), m_iSeg(0) {}
606
~CPDF_XRefStream()607 CPDF_XRefStream::~CPDF_XRefStream() {}
608
Start()609 bool CPDF_XRefStream::Start() {
610 m_IndexArray.clear();
611 m_Buffer.Clear();
612 m_iSeg = 0;
613 return true;
614 }
CompressIndirectObject(uint32_t dwObjNum,const CPDF_Object * pObj,CPDF_Creator * pCreator)615 int32_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 }
CompressIndirectObject(uint32_t dwObjNum,const uint8_t * pBuffer,uint32_t dwSize,CPDF_Creator * pCreator)629 int32_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
EndObjectStream(CPDF_Creator * pCreator,bool bEOF)645 int32_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 }
GenerateXRefStream(CPDF_Creator * pCreator,bool bEOF)711 bool 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
End(CPDF_Creator * pCreator,bool bEOF)842 bool CPDF_XRefStream::End(CPDF_Creator* pCreator, bool bEOF) {
843 if (EndObjectStream(pCreator, bEOF) < 0) {
844 return false;
845 }
846 return GenerateXRefStream(pCreator, bEOF);
847 }
EndXRefStream(CPDF_Creator * pCreator)848 bool 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 }
AddObjectNumberToIndexArray(uint32_t objnum)867 void 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
CPDF_Creator(CPDF_Document * pDoc)879 CPDF_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
~CPDF_Creator()899 CPDF_Creator::~CPDF_Creator() {
900 ResetStandardSecurity();
901 if (m_bEncryptCloned) {
902 delete m_pEncryptDict;
903 m_pEncryptDict = nullptr;
904 }
905 Clear();
906 }
907
WriteIndirectObjectToStream(const CPDF_Object * pObj)908 int32_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 }
WriteIndirectObjectToStream(uint32_t objnum,const uint8_t * pBuffer,uint32_t dwSize)946 int32_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 }
AppendObjectNumberToXRef(uint32_t objnum)969 int32_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 }
WriteStream(const CPDF_Object * pStream,uint32_t objnum,CPDF_CryptoHandler * pCrypto)985 int32_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 }
WriteIndirectObj(uint32_t objnum,const CPDF_Object * pObj)1016 int32_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 }
WriteIndirectObj(const CPDF_Object * pObj)1044 int32_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 }
WriteDirectObj(uint32_t objnum,const CPDF_Object * pObj,bool bEncrypt)1051 int32_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 }
WriteOldIndirectObject(uint32_t objnum)1230 int32_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 }
WriteOldObjs(IFX_Pause * pPause)1295 int32_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
WriteNewObjs(bool bIncremental,IFX_Pause * pPause)1317 int32_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
InitOldObjNumOffsets()1340 void 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
InitNewObjNumOffsets()1363 void 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
AppendNewObjNum(uint32_t objnum)1417 void 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
WriteDoc_Stage1(IFX_Pause * pPause)1423 int32_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 }
WriteDoc_Stage2(IFX_Pause * pPause)1520 int32_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 }
WriteDoc_Stage3(IFX_Pause * pPause)1566 int32_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
WriteDoc_Stage4(IFX_Pause * pPause)1677 int32_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
Clear()1876 void CPDF_Creator::Clear() {
1877 m_pXRefStream.reset();
1878 m_File.Clear();
1879 m_NewObjNumArray.clear();
1880 m_pIDArray.reset();
1881 }
1882
Create(const CFX_RetainPtr<IFX_WriteStream> & pFile,uint32_t flags)1883 bool CPDF_Creator::Create(const CFX_RetainPtr<IFX_WriteStream>& pFile,
1884 uint32_t flags) {
1885 m_File.AttachFile(pFile);
1886 return Create(flags);
1887 }
1888
Create(uint32_t flags)1889 bool 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
InitID(bool bDefault)1902 void 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 }
Continue(IFX_Pause * pPause)1949 int32_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 }
SetFileVersion(int32_t fileVersion)1975 bool CPDF_Creator::SetFileVersion(int32_t fileVersion) {
1976 if (fileVersion < 10 || fileVersion > 17) {
1977 return false;
1978 }
1979 m_FileVersion = fileVersion;
1980 return true;
1981 }
RemoveSecurity()1982 void CPDF_Creator::RemoveSecurity() {
1983 ResetStandardSecurity();
1984 m_bSecurityChanged = true;
1985 m_pEncryptDict = nullptr;
1986 m_pCryptoHandler = nullptr;
1987 }
ResetStandardSecurity()1988 void CPDF_Creator::ResetStandardSecurity() {
1989 if (!m_bLocalCryptoHandler)
1990 return;
1991
1992 delete m_pCryptoHandler;
1993 m_pCryptoHandler = nullptr;
1994 m_bLocalCryptoHandler = false;
1995 }
1996