blob: d37c8d54570c3976d66b8cc32b1eac84ff33037e [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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 Zhang95e854f2015-06-13 00:58:06 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
dsinclair488b7ad2016-10-04 11:55:50 -07007#include "core/fpdfapi/parser/cfdf_document.h"
Wei Liaa0f69a2016-01-07 10:49:33 -08008
tsepez0e606b52016-11-18 16:22:41 -08009#include <memory>
Henrique Nakashima5c09f4c2017-08-04 12:28:52 -040010#include <sstream>
tsepez0e606b52016-11-18 16:22:41 -080011#include <utility>
12
dsinclair24154352016-10-04 11:01:48 -070013#include "core/fpdfapi/edit/cpdf_creator.h"
dsinclair488b7ad2016-10-04 11:55:50 -070014#include "core/fpdfapi/parser/cpdf_dictionary.h"
15#include "core/fpdfapi/parser/cpdf_syntax_parser.h"
Tom Sepeza1193402017-04-13 10:42:41 -070016#include "core/fpdfapi/parser/fpdf_parser_utility.h"
Lei Zhang30029412018-08-13 19:56:29 +000017#include "core/fxcrt/cfx_readonlymemorystream.h"
tsepez36eb4bd2016-10-03 15:24:27 -070018#include "third_party/base/ptr_util.h"
Lei Zhangf0260b22018-08-13 22:50:02 +000019#include "third_party/base/span.h"
Lei Zhanga9fa50f2015-11-10 09:45:32 -080020
Lei Zhang30029412018-08-13 19:56:29 +000021CFDF_Document::CFDF_Document() = default;
dsinclaira61c01e2016-08-24 10:31:23 -070022
Lei Zhang30029412018-08-13 19:56:29 +000023CFDF_Document::~CFDF_Document() = default;
dsinclaira61c01e2016-08-24 10:31:23 -070024
tsepez05e01692016-11-28 17:30:09 -080025std::unique_ptr<CFDF_Document> CFDF_Document::CreateNewDoc() {
26 auto pDoc = pdfium::MakeUnique<CFDF_Document>();
tsepez5913a6c2016-11-16 17:31:18 -080027 pDoc->m_pRootDict = pDoc->NewIndirect<CPDF_Dictionary>();
tsepez0e606b52016-11-18 16:22:41 -080028 pDoc->m_pRootDict->SetNewFor<CPDF_Dictionary>("FDF");
Nico Weber9d8ec5a2015-08-04 13:00:21 -070029 return pDoc;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070030}
thestig2f1e05a2016-05-26 16:24:15 -070031
Lei Zhangf0260b22018-08-13 22:50:02 +000032std::unique_ptr<CFDF_Document> CFDF_Document::ParseMemory(
33 pdfium::span<const uint8_t> span) {
Lei Zhang58c2c142017-12-19 19:00:43 +000034 auto pDoc = pdfium::MakeUnique<CFDF_Document>();
Lei Zhangf0260b22018-08-13 22:50:02 +000035 pDoc->ParseStream(
36 pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(span.data(), span.size()));
Lei Zhang58c2c142017-12-19 19:00:43 +000037 return pDoc->m_pRootDict ? std::move(pDoc) : nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070038}
thestig2f1e05a2016-05-26 16:24:15 -070039
tsepez833619b2016-12-07 09:21:17 -080040void CFDF_Document::ParseStream(
Dan Sinclair0b950422017-09-21 15:49:49 -040041 const RetainPtr<IFX_SeekableReadStream>& pFile) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070042 m_pFile = pFile;
Lei Zhang5b322332018-07-25 17:35:18 +000043 CPDF_SyntaxParser parser(m_pFile);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070044 while (1) {
Lei Zhangec321272016-01-06 01:52:42 -080045 bool bNumber;
Ryan Harrison275e2602017-09-18 14:23:18 -040046 ByteString word = parser.GetNextWord(&bNumber);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070047 if (bNumber) {
tsepezb4c9f3f2016-04-13 15:41:21 -070048 uint32_t objnum = FXSYS_atoui(word.c_str());
tsepez761eed22016-11-04 11:02:59 -070049 if (!objnum)
50 break;
51
Lei Zhangec321272016-01-06 01:52:42 -080052 word = parser.GetNextWord(&bNumber);
thestig2f1e05a2016-05-26 16:24:15 -070053 if (!bNumber)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070054 break;
thestig2f1e05a2016-05-26 16:24:15 -070055
Lei Zhangec321272016-01-06 01:52:42 -080056 word = parser.GetNextWord(nullptr);
thestig2f1e05a2016-05-26 16:24:15 -070057 if (word != "obj")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058 break;
thestig2f1e05a2016-05-26 16:24:15 -070059
Artem Strygind8169d72017-10-02 19:19:28 +030060 std::unique_ptr<CPDF_Object> pObj = parser.GetObjectBody(this);
thestig2f1e05a2016-05-26 16:24:15 -070061 if (!pObj)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070062 break;
thestig2f1e05a2016-05-26 16:24:15 -070063
tsepez931d0872016-11-04 16:00:03 -070064 ReplaceIndirectObjectIfHigherGeneration(objnum, std::move(pObj));
Lei Zhangec321272016-01-06 01:52:42 -080065 word = parser.GetNextWord(nullptr);
thestig2f1e05a2016-05-26 16:24:15 -070066 if (word != "endobj")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070068 } else {
thestig2f1e05a2016-05-26 16:24:15 -070069 if (word != "trailer")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070070 break;
thestig2f1e05a2016-05-26 16:24:15 -070071
tsepez5ab31ef2016-11-07 13:49:17 -080072 std::unique_ptr<CPDF_Dictionary> pMainDict =
Artem Strygind8169d72017-10-02 19:19:28 +030073 ToDictionary(parser.GetObjectBody(this));
tsepez5ab31ef2016-11-07 13:49:17 -080074 if (pMainDict)
dsinclair38fd8442016-09-15 10:15:32 -070075 m_pRootDict = pMainDict->GetDictFor("Root");
tsepez5ab31ef2016-11-07 13:49:17 -080076
Nico Weber9d8ec5a2015-08-04 13:00:21 -070077 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070078 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070079 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070080}
thestig2f1e05a2016-05-26 16:24:15 -070081
Ryan Harrison275e2602017-09-18 14:23:18 -040082ByteString CFDF_Document::WriteToString() const {
dsinclaire07edce2016-08-23 20:14:27 -070083 if (!m_pRootDict)
Ryan Harrison275e2602017-09-18 14:23:18 -040084 return ByteString();
dsinclaire07edce2016-08-23 20:14:27 -070085
Henrique Nakashima5c09f4c2017-08-04 12:28:52 -040086 std::ostringstream buf;
Lei Zhangd983b092015-12-14 16:58:33 -080087 buf << "%FDF-1.2\r\n";
dsinclaire07edce2016-08-23 20:14:27 -070088 for (const auto& pair : *this)
tsepez5b7c9bb2016-09-20 12:02:32 -070089 buf << pair.first << " 0 obj\r\n"
90 << pair.second.get() << "\r\nendobj\r\n\r\n";
dsinclaire07edce2016-08-23 20:14:27 -070091
Lei Zhangd983b092015-12-14 16:58:33 -080092 buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum()
93 << " 0 R>>\r\n%%EOF\r\n";
Henrique Nakashima5c09f4c2017-08-04 12:28:52 -040094
Ryan Harrison275e2602017-09-18 14:23:18 -040095 return ByteString(buf);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070096}