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