Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: core/fpdfapi/fpdf_edit/fpdf_edit_create.cpp

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

Powered by Google App Engine
This is Rietveld 408576698