Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_creator.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
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/cpdf_creator.h"
8
9#include <stdint.h>
10
11#include <algorithm>
12#include <set>
13#include <utility>
14
15#include "core/fpdfapi/parser/cpdf_array.h"
16#include "core/fpdfapi/parser/cpdf_crypto_handler.h"
17#include "core/fpdfapi/parser/cpdf_dictionary.h"
18#include "core/fpdfapi/parser/cpdf_document.h"
19#include "core/fpdfapi/parser/cpdf_encryptor.h"
20#include "core/fpdfapi/parser/cpdf_flateencoder.h"
21#include "core/fpdfapi/parser/cpdf_number.h"
22#include "core/fpdfapi/parser/cpdf_parser.h"
23#include "core/fpdfapi/parser/cpdf_security_handler.h"
24#include "core/fpdfapi/parser/cpdf_string.h"
25#include "core/fpdfapi/parser/fpdf_parser_utility.h"
26#include "core/fpdfapi/parser/object_tree_traversal_util.h"
27#include "core/fxcrt/data_vector.h"
28#include "core/fxcrt/fx_extension.h"
29#include "core/fxcrt/fx_random.h"
30#include "core/fxcrt/fx_safe_types.h"
31#include "core/fxcrt/span_util.h"
32#include "core/fxcrt/stl_util.h"
33#include "third_party/base/check.h"
34#include "third_party/base/containers/contains.h"
35
36namespace {
37
38const size_t kArchiveBufferSize = 32768;
39
40class CFX_FileBufferArchive final : public IFX_ArchiveStream {
41 public:
42 explicit CFX_FileBufferArchive(RetainPtr<IFX_RetainableWriteStream> file);
43 ~CFX_FileBufferArchive() override;
44
45 bool WriteBlock(pdfium::span<const uint8_t> buffer) override;
46 FX_FILESIZE CurrentOffset() const override { return offset_; }
47
48 private:
49 bool Flush();
50
51 FX_FILESIZE offset_ = 0;
52 DataVector<uint8_t> buffer_;
53 pdfium::span<uint8_t> available_;
54 RetainPtr<IFX_RetainableWriteStream> const backing_file_;
55};
56
57CFX_FileBufferArchive::CFX_FileBufferArchive(
59 : buffer_(kArchiveBufferSize),
60 available_(buffer_),
61 backing_file_(std::move(file)) {
62 DCHECK(backing_file_);
63}
64
65CFX_FileBufferArchive::~CFX_FileBufferArchive() {
66 Flush();
67}
68
69bool CFX_FileBufferArchive::Flush() {
70 size_t nUsed = buffer_.size() - available_.size();
71 available_ = pdfium::make_span(buffer_);
72 if (!nUsed)
73 return true;
74 return backing_file_->WriteBlock(available_.first(nUsed));
75}
76
77bool CFX_FileBufferArchive::WriteBlock(pdfium::span<const uint8_t> buffer) {
78 if (buffer.empty())
79 return true;
80
81 pdfium::span<const uint8_t> src_span = buffer;
82 while (!src_span.empty()) {
83 size_t copy_size = std::min(available_.size(), src_span.size());
84 fxcrt::spancpy(available_, src_span.first(copy_size));
85 src_span = src_span.subspan(copy_size);
86 available_ = available_.subspan(copy_size);
87 if (available_.empty() && !Flush())
88 return false;
89 }
90
91 FX_SAFE_FILESIZE safe_offset = offset_;
92 safe_offset += buffer.size();
93 if (!safe_offset.IsValid())
94 return false;
95
96 offset_ = safe_offset.ValueOrDie();
97 return true;
98}
99
100ByteString GenerateFileID(uint32_t dwSeed1, uint32_t dwSeed2) {
101 uint32_t buffer[4];
102 void* pContext1 = FX_Random_MT_Start(dwSeed1);
103 void* pContext2 = FX_Random_MT_Start(dwSeed2);
104 buffer[0] = FX_Random_MT_Generate(pContext1);
105 buffer[1] = FX_Random_MT_Generate(pContext1);
106 buffer[2] = FX_Random_MT_Generate(pContext2);
107 buffer[3] = FX_Random_MT_Generate(pContext2);
108 FX_Random_MT_Close(pContext1);
109 FX_Random_MT_Close(pContext2);
110 return ByteString(ByteStringView(pdfium::as_byte_span(buffer)));
111}
112
113bool OutputIndex(IFX_ArchiveStream* archive, FX_FILESIZE offset) {
114 return archive->WriteByte(static_cast<uint8_t>(offset >> 24)) &&
115 archive->WriteByte(static_cast<uint8_t>(offset >> 16)) &&
116 archive->WriteByte(static_cast<uint8_t>(offset >> 8)) &&
117 archive->WriteByte(static_cast<uint8_t>(offset)) &&
118 archive->WriteByte(0);
119}
120
121} // namespace
122
131
132CPDF_Creator::~CPDF_Creator() = default;
133
134bool CPDF_Creator::WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj) {
135 if (!m_Archive->WriteDWord(objnum) || !m_Archive->WriteString(" 0 obj\r\n"))
136 return false;
137
138 std::unique_ptr<CPDF_Encryptor> encryptor;
139 if (GetCryptoHandler() && pObj != m_pEncryptDict)
140 encryptor = std::make_unique<CPDF_Encryptor>(GetCryptoHandler(), objnum);
141
142 if (!pObj->WriteTo(m_Archive.get(), encryptor.get()))
143 return false;
144
145 return m_Archive->WriteString("\r\nendobj\r\n");
146}
147
148bool CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) {
149 if (m_pParser->IsObjectFreeOrNull(objnum))
150 return true;
151
152 m_ObjectOffsets[objnum] = m_Archive->CurrentOffset();
153
154 bool bExistInMap = !!m_pDocument->GetIndirectObject(objnum);
155 RetainPtr<CPDF_Object> pObj = m_pDocument->GetOrParseIndirectObject(objnum);
156 if (!pObj) {
157 m_ObjectOffsets.erase(objnum);
158 return true;
159 }
160 if (!WriteIndirectObj(pObj->GetObjNum(), pObj.Get()))
161 return false;
162 if (!bExistInMap)
163 m_pDocument->DeleteIndirectObject(objnum);
164 return true;
165}
166
167bool CPDF_Creator::WriteOldObjs() {
168 const uint32_t nLastObjNum = m_pParser->GetLastObjNum();
169 if (!m_pParser->IsValidObjectNumber(nLastObjNum)) {
170 return true;
171 }
172 if (m_CurObjNum > nLastObjNum) {
173 return true;
174 }
175
176 const std::set<uint32_t> objects_with_refs =
177 GetObjectsWithReferences(m_pDocument);
178 uint32_t last_object_number_written = 0;
179 for (uint32_t objnum = m_CurObjNum; objnum <= nLastObjNum; ++objnum) {
180 if (!pdfium::Contains(objects_with_refs, objnum)) {
181 continue;
182 }
183 if (!WriteOldIndirectObject(objnum)) {
184 return false;
185 }
186 last_object_number_written = objnum;
187 }
188 // If there are no new objects to write, then adjust `m_dwLastObjNum` if
189 // needed to reflect the actual last object number.
190 if (m_NewObjNumArray.empty()) {
191 m_dwLastObjNum = last_object_number_written;
192 }
193 return true;
194}
195
196bool CPDF_Creator::WriteNewObjs() {
197 for (size_t i = m_CurObjNum; i < m_NewObjNumArray.size(); ++i) {
198 uint32_t objnum = m_NewObjNumArray[i];
199 RetainPtr<const CPDF_Object> pObj = m_pDocument->GetIndirectObject(objnum);
200 if (!pObj)
201 continue;
202
203 m_ObjectOffsets[objnum] = m_Archive->CurrentOffset();
204 if (!WriteIndirectObj(pObj->GetObjNum(), pObj.Get()))
205 return false;
206 }
207 return true;
208}
209
210void CPDF_Creator::InitNewObjNumOffsets() {
211 for (const auto& pair : *m_pDocument) {
212 const uint32_t objnum = pair.first;
213 if (m_IsIncremental ||
214 pair.second->GetObjNum() == CPDF_Object::kInvalidObjNum) {
215 continue;
216 }
217 if (m_pParser && m_pParser->IsValidObjectNumber(objnum) &&
218 !m_pParser->IsObjectFree(objnum)) {
219 continue;
220 }
221 m_NewObjNumArray.insert(std::lower_bound(m_NewObjNumArray.begin(),
222 m_NewObjNumArray.end(), objnum),
223 objnum);
224 }
225}
226
227CPDF_Creator::Stage CPDF_Creator::WriteDoc_Stage1() {
228 DCHECK(m_iStage > Stage::kInvalid || m_iStage < Stage::kInitWriteObjs20);
229 if (m_iStage == Stage::kInit0) {
230 if (!m_pParser || (m_bSecurityChanged && m_IsOriginal))
231 m_IsIncremental = false;
232
233 m_iStage = Stage::kWriteHeader10;
234 }
235 if (m_iStage == Stage::kWriteHeader10) {
236 if (!m_IsIncremental) {
237 if (!m_Archive->WriteString("%PDF-1."))
238 return Stage::kInvalid;
239
240 int32_t version = 7;
241 if (m_FileVersion)
242 version = m_FileVersion;
243 else if (m_pParser)
244 version = m_pParser->GetFileVersion();
245
246 if (!m_Archive->WriteDWord(version % 10) ||
247 !m_Archive->WriteString("\r\n%\xA1\xB3\xC5\xD7\r\n")) {
248 return Stage::kInvalid;
249 }
250 m_iStage = Stage::kInitWriteObjs20;
251 } else {
252 m_SavedOffset = m_pParser->GetDocumentSize();
253 m_iStage = Stage::kWriteIncremental15;
254 }
255 }
256 if (m_iStage == Stage::kWriteIncremental15) {
257 if (m_IsOriginal && m_SavedOffset > 0) {
258 if (!m_pParser->WriteToArchive(m_Archive.get(), m_SavedOffset))
259 return Stage::kInvalid;
260 }
261 if (m_IsOriginal && m_pParser->GetLastXRefOffset() == 0) {
262 for (uint32_t num = 0; num <= m_pParser->GetLastObjNum(); ++num) {
263 if (m_pParser->IsObjectFreeOrNull(num))
264 continue;
265
266 m_ObjectOffsets[num] = m_pParser->GetObjectPositionOrZero(num);
267 }
268 }
269 m_iStage = Stage::kInitWriteObjs20;
270 }
271 InitNewObjNumOffsets();
272 return m_iStage;
273}
274
275CPDF_Creator::Stage CPDF_Creator::WriteDoc_Stage2() {
276 DCHECK(m_iStage >= Stage::kInitWriteObjs20 ||
277 m_iStage < Stage::kInitWriteXRefs80);
278 if (m_iStage == Stage::kInitWriteObjs20) {
279 if (!m_IsIncremental && m_pParser) {
280 m_CurObjNum = 0;
281 m_iStage = Stage::kWriteOldObjs21;
282 } else {
283 m_iStage = Stage::kInitWriteNewObjs25;
284 }
285 }
286 if (m_iStage == Stage::kWriteOldObjs21) {
287 if (!WriteOldObjs())
288 return Stage::kInvalid;
289
290 m_iStage = Stage::kInitWriteNewObjs25;
291 }
292 if (m_iStage == Stage::kInitWriteNewObjs25) {
293 m_CurObjNum = 0;
294 m_iStage = Stage::kWriteNewObjs26;
295 }
296 if (m_iStage == Stage::kWriteNewObjs26) {
297 if (!WriteNewObjs())
298 return Stage::kInvalid;
299
300 m_iStage = Stage::kWriteEncryptDict27;
301 }
302 if (m_iStage == Stage::kWriteEncryptDict27) {
303 if (m_pEncryptDict && m_pEncryptDict->IsInline()) {
304 m_dwLastObjNum += 1;
305 FX_FILESIZE saveOffset = m_Archive->CurrentOffset();
306 if (!WriteIndirectObj(m_dwLastObjNum, m_pEncryptDict.Get()))
307 return Stage::kInvalid;
308
309 m_ObjectOffsets[m_dwLastObjNum] = saveOffset;
310 if (m_IsIncremental)
311 m_NewObjNumArray.push_back(m_dwLastObjNum);
312 }
313 m_iStage = Stage::kInitWriteXRefs80;
314 }
315 return m_iStage;
316}
317
318CPDF_Creator::Stage CPDF_Creator::WriteDoc_Stage3() {
319 DCHECK(m_iStage >= Stage::kInitWriteXRefs80 ||
320 m_iStage < Stage::kWriteTrailerAndFinish90);
321
322 uint32_t dwLastObjNum = m_dwLastObjNum;
323 if (m_iStage == Stage::kInitWriteXRefs80) {
324 m_XrefStart = m_Archive->CurrentOffset();
325 if (!m_IsIncremental || !m_pParser->IsXRefStream()) {
326 if (!m_IsIncremental || m_pParser->GetLastXRefOffset() == 0) {
327 ByteString str;
328 str = pdfium::Contains(m_ObjectOffsets, 1)
329 ? "xref\r\n"
330 : "xref\r\n0 1\r\n0000000000 65535 f\r\n";
331 if (!m_Archive->WriteString(str.AsStringView()))
332 return Stage::kInvalid;
333
334 m_CurObjNum = 1;
335 m_iStage = Stage::kWriteXrefsNotIncremental81;
336 } else {
337 if (!m_Archive->WriteString("xref\r\n"))
338 return Stage::kInvalid;
339
340 m_CurObjNum = 0;
341 m_iStage = Stage::kWriteXrefsIncremental82;
342 }
343 } else {
344 m_iStage = Stage::kWriteTrailerAndFinish90;
345 }
346 }
347 if (m_iStage == Stage::kWriteXrefsNotIncremental81) {
348 ByteString str;
349 uint32_t i = m_CurObjNum;
350 uint32_t j;
351 while (i <= dwLastObjNum) {
352 while (i <= dwLastObjNum && !pdfium::Contains(m_ObjectOffsets, i))
353 i++;
354
355 if (i > dwLastObjNum)
356 break;
357
358 j = i;
359 while (j <= dwLastObjNum && pdfium::Contains(m_ObjectOffsets, j))
360 j++;
361
362 if (i == 1)
363 str = ByteString::Format("0 %d\r\n0000000000 65535 f\r\n", j);
364 else
365 str = ByteString::Format("%d %d\r\n", i, j - i);
366
367 if (!m_Archive->WriteString(str.AsStringView()))
368 return Stage::kInvalid;
369
370 while (i < j) {
371 str = ByteString::Format("%010d 00000 n\r\n", m_ObjectOffsets[i++]);
372 if (!m_Archive->WriteString(str.AsStringView()))
373 return Stage::kInvalid;
374 }
375 if (i > dwLastObjNum)
376 break;
377 }
378 m_iStage = Stage::kWriteTrailerAndFinish90;
379 }
380 if (m_iStage == Stage::kWriteXrefsIncremental82) {
381 ByteString str;
382 uint32_t iCount = fxcrt::CollectionSize<uint32_t>(m_NewObjNumArray);
383 uint32_t i = m_CurObjNum;
384 while (i < iCount) {
385 size_t j = i;
386 uint32_t objnum = m_NewObjNumArray[i];
387 while (j < iCount) {
388 if (++j == iCount)
389 break;
390 uint32_t dwCurrent = m_NewObjNumArray[j];
391 if (dwCurrent - objnum > 1)
392 break;
393 objnum = dwCurrent;
394 }
395 objnum = m_NewObjNumArray[i];
396 if (objnum == 1)
397 str = ByteString::Format("0 %d\r\n0000000000 65535 f\r\n", j - i + 1);
398 else
399 str = ByteString::Format("%d %d\r\n", objnum, j - i);
400
401 if (!m_Archive->WriteString(str.AsStringView()))
402 return Stage::kInvalid;
403
404 while (i < j) {
405 objnum = m_NewObjNumArray[i++];
406 str = ByteString::Format("%010d 00000 n\r\n", m_ObjectOffsets[objnum]);
407 if (!m_Archive->WriteString(str.AsStringView()))
408 return Stage::kInvalid;
409 }
410 }
411 m_iStage = Stage::kWriteTrailerAndFinish90;
412 }
413 return m_iStage;
414}
415
416CPDF_Creator::Stage CPDF_Creator::WriteDoc_Stage4() {
417 DCHECK(m_iStage >= Stage::kWriteTrailerAndFinish90);
418
419 bool bXRefStream = m_IsIncremental && m_pParser->IsXRefStream();
420 if (!bXRefStream) {
421 if (!m_Archive->WriteString("trailer\r\n<<"))
422 return Stage::kInvalid;
423 } else {
424 if (!m_Archive->WriteDWord(m_pDocument->GetLastObjNum() + 1) ||
425 !m_Archive->WriteString(" 0 obj <<")) {
426 return Stage::kInvalid;
427 }
428 }
429
430 if (m_pParser) {
431 CPDF_DictionaryLocker locker(m_pParser->GetCombinedTrailer());
432 for (const auto& it : locker) {
433 const ByteString& key = it.first;
434 const RetainPtr<CPDF_Object>& pValue = it.second;
435 if (key == "Encrypt" || key == "Size" || key == "Filter" ||
436 key == "Index" || key == "Length" || key == "Prev" || key == "W" ||
437 key == "XRefStm" || key == "ID" || key == "DecodeParms" ||
438 key == "Type") {
439 continue;
440 }
441 if (!m_Archive->WriteString(("/")) ||
442 !m_Archive->WriteString(PDF_NameEncode(key).AsStringView())) {
443 return Stage::kInvalid;
444 }
445 if (!pValue->WriteTo(m_Archive.get(), nullptr))
446 return Stage::kInvalid;
447 }
448 } else {
449 if (!m_Archive->WriteString("\r\n/Root ") ||
450 !m_Archive->WriteDWord(m_pDocument->GetRoot()->GetObjNum()) ||
451 !m_Archive->WriteString(" 0 R\r\n")) {
452 return Stage::kInvalid;
453 }
454 if (m_pDocument->GetInfo()) {
455 if (!m_Archive->WriteString("/Info ") ||
456 !m_Archive->WriteDWord(m_pDocument->GetInfo()->GetObjNum()) ||
457 !m_Archive->WriteString(" 0 R\r\n")) {
458 return Stage::kInvalid;
459 }
460 }
461 }
462 if (m_pEncryptDict) {
463 if (!m_Archive->WriteString("/Encrypt"))
464 return Stage::kInvalid;
465
466 uint32_t dwObjNum = m_pEncryptDict->GetObjNum();
467 if (dwObjNum == 0)
468 dwObjNum = m_pDocument->GetLastObjNum() + 1;
469 if (!m_Archive->WriteString(" ") || !m_Archive->WriteDWord(dwObjNum) ||
470 !m_Archive->WriteString(" 0 R ")) {
471 return Stage::kInvalid;
472 }
473 }
474
475 if (!m_Archive->WriteString("/Size ") ||
476 !m_Archive->WriteDWord(m_dwLastObjNum + (bXRefStream ? 2 : 1))) {
477 return Stage::kInvalid;
478 }
479 if (m_IsIncremental) {
480 FX_FILESIZE prev = m_pParser->GetLastXRefOffset();
481 if (prev) {
482 if (!m_Archive->WriteString("/Prev ") || !m_Archive->WriteFilesize(prev))
483 return Stage::kInvalid;
484 }
485 }
486 if (m_pIDArray) {
487 if (!m_Archive->WriteString(("/ID")) ||
488 !m_pIDArray->WriteTo(m_Archive.get(), nullptr)) {
489 return Stage::kInvalid;
490 }
491 }
492 if (!bXRefStream) {
493 if (!m_Archive->WriteString(">>"))
494 return Stage::kInvalid;
495 } else {
496 if (!m_Archive->WriteString("/W[0 4 1]/Index["))
497 return Stage::kInvalid;
498 if (m_IsIncremental && m_pParser && m_pParser->GetLastXRefOffset() == 0) {
499 uint32_t i = 0;
500 for (i = 0; i < m_dwLastObjNum; i++) {
501 if (!pdfium::Contains(m_ObjectOffsets, i))
502 continue;
503 if (!m_Archive->WriteDWord(i) || !m_Archive->WriteString(" 1 "))
504 return Stage::kInvalid;
505 }
506 if (!m_Archive->WriteString("]/Length ") ||
507 !m_Archive->WriteDWord(m_dwLastObjNum * 5) ||
508 !m_Archive->WriteString(">>stream\r\n")) {
509 return Stage::kInvalid;
510 }
511 for (i = 0; i < m_dwLastObjNum; i++) {
512 auto it = m_ObjectOffsets.find(i);
513 if (it == m_ObjectOffsets.end())
514 continue;
515 if (!OutputIndex(m_Archive.get(), it->second))
516 return Stage::kInvalid;
517 }
518 } else {
519 int count = fxcrt::CollectionSize<int>(m_NewObjNumArray);
520 int i = 0;
521 for (i = 0; i < count; i++) {
522 if (!m_Archive->WriteDWord(m_NewObjNumArray[i]) ||
523 !m_Archive->WriteString(" 1 ")) {
524 return Stage::kInvalid;
525 }
526 }
527 if (!m_Archive->WriteString("]/Length ") ||
528 !m_Archive->WriteDWord(count * 5) ||
529 !m_Archive->WriteString(">>stream\r\n")) {
530 return Stage::kInvalid;
531 }
532 for (i = 0; i < count; ++i) {
533 if (!OutputIndex(m_Archive.get(), m_ObjectOffsets[m_NewObjNumArray[i]]))
534 return Stage::kInvalid;
535 }
536 }
537 if (!m_Archive->WriteString("\r\nendstream"))
538 return Stage::kInvalid;
539 }
540
541 if (!m_Archive->WriteString("\r\nstartxref\r\n") ||
542 !m_Archive->WriteFilesize(m_XrefStart) ||
543 !m_Archive->WriteString("\r\n%%EOF\r\n")) {
544 return Stage::kInvalid;
545 }
546
547 m_iStage = Stage::kComplete100;
548 return m_iStage;
549}
550
551bool CPDF_Creator::Create(uint32_t flags) {
552 m_IsIncremental = !!(flags & FPDFCREATE_INCREMENTAL);
553 m_IsOriginal = !(flags & FPDFCREATE_NO_ORIGINAL);
554
555 m_iStage = Stage::kInit0;
556 m_dwLastObjNum = m_pDocument->GetLastObjNum();
557 m_ObjectOffsets.clear();
558 m_NewObjNumArray.clear();
559
560 InitID();
561 return Continue();
562}
563
564void CPDF_Creator::InitID() {
565 DCHECK(!m_pIDArray);
566
567 m_pIDArray = pdfium::MakeRetain<CPDF_Array>();
568 RetainPtr<const CPDF_Array> pOldIDArray =
569 m_pParser ? m_pParser->GetIDArray() : nullptr;
570 RetainPtr<const CPDF_Object> pID1 =
571 pOldIDArray ? pOldIDArray->GetObjectAt(0) : nullptr;
572 if (pID1) {
573 m_pIDArray->Append(pID1->Clone());
574 } else {
575 ByteString bsBuffer =
576 GenerateFileID((uint32_t)(uintptr_t)this, m_dwLastObjNum);
577 m_pIDArray->AppendNew<CPDF_String>(bsBuffer, true);
578 }
579
580 if (pOldIDArray) {
581 RetainPtr<const CPDF_Object> pID2 = pOldIDArray->GetObjectAt(1);
582 if (m_IsIncremental && m_pEncryptDict && pID2) {
583 m_pIDArray->Append(pID2->Clone());
584 return;
585 }
586 ByteString bsBuffer =
587 GenerateFileID((uint32_t)(uintptr_t)this, m_dwLastObjNum);
588 m_pIDArray->AppendNew<CPDF_String>(bsBuffer, true);
589 return;
590 }
591
592 m_pIDArray->Append(m_pIDArray->GetObjectAt(0)->Clone());
593 if (m_pEncryptDict) {
594 DCHECK(m_pParser);
595 int revision = m_pEncryptDict->GetIntegerFor("R");
596 if ((revision == 2 || revision == 3) &&
597 m_pEncryptDict->GetByteStringFor("Filter") == "Standard") {
598 m_pNewEncryptDict = ToDictionary(m_pEncryptDict->Clone());
599 m_pEncryptDict = m_pNewEncryptDict;
600 m_pSecurityHandler = pdfium::MakeRetain<CPDF_SecurityHandler>();
601 m_pSecurityHandler->OnCreate(m_pNewEncryptDict.Get(), m_pIDArray.Get(),
602 m_pParser->GetEncodedPassword());
603 m_bSecurityChanged = true;
604 }
605 }
606}
607
608bool CPDF_Creator::Continue() {
609 if (m_iStage < Stage::kInit0)
610 return false;
611
612 Stage iRet = Stage::kInit0;
613 while (m_iStage < Stage::kComplete100) {
614 if (m_iStage < Stage::kInitWriteObjs20)
615 iRet = WriteDoc_Stage1();
616 else if (m_iStage < Stage::kInitWriteXRefs80)
617 iRet = WriteDoc_Stage2();
618 else if (m_iStage < Stage::kWriteTrailerAndFinish90)
619 iRet = WriteDoc_Stage3();
620 else
621 iRet = WriteDoc_Stage4();
622
623 if (iRet < m_iStage)
624 break;
625 }
626
627 if (iRet <= Stage::kInit0 || m_iStage == Stage::kComplete100) {
628 m_iStage = Stage::kInvalid;
629 return iRet > Stage::kInit0;
630 }
631
632 return m_iStage > Stage::kInvalid;
633}
634
635bool CPDF_Creator::SetFileVersion(int32_t fileVersion) {
636 if (fileVersion < 10 || fileVersion > 17)
637 return false;
638 m_FileVersion = fileVersion;
639 return true;
640}
641
643 m_pSecurityHandler.Reset();
644 m_bSecurityChanged = true;
645 m_pEncryptDict = nullptr;
646 m_pNewEncryptDict.Reset();
647}
648
649CPDF_CryptoHandler* CPDF_Creator::GetCryptoHandler() {
650 return m_pSecurityHandler ? m_pSecurityHandler->GetCryptoHandler() : nullptr;
651}
CPDF_Creator(CPDF_Document *pDoc, RetainPtr< IFX_RetainableWriteStream > archive)
bool SetFileVersion(int32_t fileVersion)
void RemoveSecurity()
bool Create(uint32_t flags)
bool WriteByte(uint8_t byte)
Definition fx_stream.cpp:51
static ByteString Format(const char *pFormat,...)
ByteString & operator=(ByteString &&that) noexcept
#define FPDFCREATE_INCREMENTAL
#define FPDFCREATE_NO_ORIGINAL
void * FX_Random_MT_Start(uint32_t dwSeed)
Definition fx_random.cpp:85
uint32_t FX_Random_MT_Generate(void *pContext)
Definition fx_random.cpp:96
void FX_Random_MT_Close(void *pContext)
#define FX_FILESIZE
Definition fx_types.h:19