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