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