John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 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. | ||||
Lei Zhang | 95e854f | 2015-06-13 00:58:06 -0700 | [diff] [blame] | 4 | |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 5 | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | |||||
dsinclair | 488b7ad | 2016-10-04 11:55:50 -0700 | [diff] [blame] | 7 | #include "core/fpdfapi/parser/cfdf_document.h" |
Wei Li | aa0f69a | 2016-01-07 10:49:33 -0800 | [diff] [blame] | 8 | |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 9 | #include <memory> |
Henrique Nakashima | 5c09f4c | 2017-08-04 12:28:52 -0400 | [diff] [blame] | 10 | #include <sstream> |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 11 | #include <utility> |
12 | |||||
dsinclair | 2415435 | 2016-10-04 11:01:48 -0700 | [diff] [blame] | 13 | #include "core/fpdfapi/edit/cpdf_creator.h" |
dsinclair | 488b7ad | 2016-10-04 11:55:50 -0700 | [diff] [blame] | 14 | #include "core/fpdfapi/parser/cpdf_dictionary.h" |
15 | #include "core/fpdfapi/parser/cpdf_syntax_parser.h" | ||||
Tom Sepez | a119340 | 2017-04-13 10:42:41 -0700 | [diff] [blame] | 16 | #include "core/fpdfapi/parser/fpdf_parser_utility.h" |
Dan Sinclair | 283a043 | 2017-04-20 14:11:21 -0400 | [diff] [blame] | 17 | #include "core/fxcrt/cfx_memorystream.h" |
tsepez | 36eb4bd | 2016-10-03 15:24:27 -0700 | [diff] [blame] | 18 | #include "third_party/base/ptr_util.h" |
Lei Zhang | a9fa50f | 2015-11-10 09:45:32 -0800 | [diff] [blame] | 19 | |
dsinclair | a61c01e | 2016-08-24 10:31:23 -0700 | [diff] [blame] | 20 | CFDF_Document::CFDF_Document() |
tsepez | 833619b | 2016-12-07 09:21:17 -0800 | [diff] [blame] | 21 | : CPDF_IndirectObjectHolder(), m_pRootDict(nullptr) {} |
dsinclair | a61c01e | 2016-08-24 10:31:23 -0700 | [diff] [blame] | 22 | |
tsepez | 833619b | 2016-12-07 09:21:17 -0800 | [diff] [blame] | 23 | CFDF_Document::~CFDF_Document() {} |
dsinclair | a61c01e | 2016-08-24 10:31:23 -0700 | [diff] [blame] | 24 | |
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 25 | std::unique_ptr<CFDF_Document> CFDF_Document::CreateNewDoc() { |
26 | auto pDoc = pdfium::MakeUnique<CFDF_Document>(); | ||||
tsepez | 5913a6c | 2016-11-16 17:31:18 -0800 | [diff] [blame] | 27 | pDoc->m_pRootDict = pDoc->NewIndirect<CPDF_Dictionary>(); |
tsepez | 0e606b5 | 2016-11-18 16:22:41 -0800 | [diff] [blame] | 28 | pDoc->m_pRootDict->SetNewFor<CPDF_Dictionary>("FDF"); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 29 | return pDoc; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 30 | } |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 31 | |
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 32 | std::unique_ptr<CFDF_Document> CFDF_Document::ParseFile( |
Dan Sinclair | 0b95042 | 2017-09-21 15:49:49 -0400 | [diff] [blame] | 33 | const RetainPtr<IFX_SeekableReadStream>& pFile) { |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 34 | if (!pFile) |
35 | return nullptr; | ||||
36 | |||||
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 37 | auto pDoc = pdfium::MakeUnique<CFDF_Document>(); |
tsepez | 833619b | 2016-12-07 09:21:17 -0800 | [diff] [blame] | 38 | pDoc->ParseStream(pFile); |
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 39 | return pDoc->m_pRootDict ? std::move(pDoc) : nullptr; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 40 | } |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 41 | |
tsepez | 833619b | 2016-12-07 09:21:17 -0800 | [diff] [blame] | 42 | std::unique_ptr<CFDF_Document> CFDF_Document::ParseMemory(uint8_t* pData, |
tsepez | 05e0169 | 2016-11-28 17:30:09 -0800 | [diff] [blame] | 43 | uint32_t size) { |
Dan Sinclair | 283a043 | 2017-04-20 14:11:21 -0400 | [diff] [blame] | 44 | return CFDF_Document::ParseFile( |
45 | pdfium::MakeRetain<CFX_MemoryStream>(pData, size, false)); | ||||
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 46 | } |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 47 | |
tsepez | 833619b | 2016-12-07 09:21:17 -0800 | [diff] [blame] | 48 | void CFDF_Document::ParseStream( |
Dan Sinclair | 0b95042 | 2017-09-21 15:49:49 -0400 | [diff] [blame] | 49 | const RetainPtr<IFX_SeekableReadStream>& pFile) { |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 50 | m_pFile = pFile; |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 51 | CPDF_SyntaxParser parser; |
52 | parser.InitParser(m_pFile, 0); | ||||
53 | while (1) { | ||||
Lei Zhang | ec32127 | 2016-01-06 01:52:42 -0800 | [diff] [blame] | 54 | bool bNumber; |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 55 | ByteString word = parser.GetNextWord(&bNumber); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 56 | if (bNumber) { |
tsepez | b4c9f3f | 2016-04-13 15:41:21 -0700 | [diff] [blame] | 57 | uint32_t objnum = FXSYS_atoui(word.c_str()); |
tsepez | 761eed2 | 2016-11-04 11:02:59 -0700 | [diff] [blame] | 58 | if (!objnum) |
59 | break; | ||||
60 | |||||
Lei Zhang | ec32127 | 2016-01-06 01:52:42 -0800 | [diff] [blame] | 61 | word = parser.GetNextWord(&bNumber); |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 62 | if (!bNumber) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 63 | break; |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 64 | |
Lei Zhang | ec32127 | 2016-01-06 01:52:42 -0800 | [diff] [blame] | 65 | word = parser.GetNextWord(nullptr); |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 66 | if (word != "obj") |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 67 | break; |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 68 | |
Artem Strygin | d8169d7 | 2017-10-02 19:19:28 +0300 | [diff] [blame^] | 69 | std::unique_ptr<CPDF_Object> pObj = parser.GetObjectBody(this); |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 70 | if (!pObj) |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 71 | break; |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 72 | |
tsepez | 931d087 | 2016-11-04 16:00:03 -0700 | [diff] [blame] | 73 | ReplaceIndirectObjectIfHigherGeneration(objnum, std::move(pObj)); |
Lei Zhang | ec32127 | 2016-01-06 01:52:42 -0800 | [diff] [blame] | 74 | word = parser.GetNextWord(nullptr); |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 75 | if (word != "endobj") |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 76 | break; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 77 | } else { |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 78 | if (word != "trailer") |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 79 | break; |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 80 | |
tsepez | 5ab31ef | 2016-11-07 13:49:17 -0800 | [diff] [blame] | 81 | std::unique_ptr<CPDF_Dictionary> pMainDict = |
Artem Strygin | d8169d7 | 2017-10-02 19:19:28 +0300 | [diff] [blame^] | 82 | ToDictionary(parser.GetObjectBody(this)); |
tsepez | 5ab31ef | 2016-11-07 13:49:17 -0800 | [diff] [blame] | 83 | if (pMainDict) |
dsinclair | 38fd844 | 2016-09-15 10:15:32 -0700 | [diff] [blame] | 84 | m_pRootDict = pMainDict->GetDictFor("Root"); |
tsepez | 5ab31ef | 2016-11-07 13:49:17 -0800 | [diff] [blame] | 85 | |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 86 | break; |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 87 | } |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 88 | } |
John Abd-El-Malek | 3f3b45c | 2014-05-23 17:28:10 -0700 | [diff] [blame] | 89 | } |
thestig | 2f1e05a | 2016-05-26 16:24:15 -0700 | [diff] [blame] | 90 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 91 | ByteString CFDF_Document::WriteToString() const { |
dsinclair | e07edce | 2016-08-23 20:14:27 -0700 | [diff] [blame] | 92 | if (!m_pRootDict) |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 93 | return ByteString(); |
dsinclair | e07edce | 2016-08-23 20:14:27 -0700 | [diff] [blame] | 94 | |
Henrique Nakashima | 5c09f4c | 2017-08-04 12:28:52 -0400 | [diff] [blame] | 95 | std::ostringstream buf; |
Lei Zhang | d983b09 | 2015-12-14 16:58:33 -0800 | [diff] [blame] | 96 | buf << "%FDF-1.2\r\n"; |
dsinclair | e07edce | 2016-08-23 20:14:27 -0700 | [diff] [blame] | 97 | for (const auto& pair : *this) |
tsepez | 5b7c9bb | 2016-09-20 12:02:32 -0700 | [diff] [blame] | 98 | buf << pair.first << " 0 obj\r\n" |
99 | << pair.second.get() << "\r\nendobj\r\n\r\n"; | ||||
dsinclair | e07edce | 2016-08-23 20:14:27 -0700 | [diff] [blame] | 100 | |
Lei Zhang | d983b09 | 2015-12-14 16:58:33 -0800 | [diff] [blame] | 101 | buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum() |
102 | << " 0 R>>\r\n%%EOF\r\n"; | ||||
Henrique Nakashima | 5c09f4c | 2017-08-04 12:28:52 -0400 | [diff] [blame] | 103 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 104 | return ByteString(buf); |
Nico Weber | 9d8ec5a | 2015-08-04 13:00:21 -0700 | [diff] [blame] | 105 | } |