blob: 55493b257dbfad437c489e583af2bdd3d8745b6a [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"
Dan Sinclair283a0432017-04-20 14:11:21 -040017#include "core/fxcrt/cfx_memorystream.h"
tsepez36eb4bd2016-10-03 15:24:27 -070018#include "third_party/base/ptr_util.h"
Lei Zhanga9fa50f2015-11-10 09:45:32 -080019
dsinclaira61c01e2016-08-24 10:31:23 -070020CFDF_Document::CFDF_Document()
tsepez833619b2016-12-07 09:21:17 -080021 : CPDF_IndirectObjectHolder(), m_pRootDict(nullptr) {}
dsinclaira61c01e2016-08-24 10:31:23 -070022
tsepez833619b2016-12-07 09:21:17 -080023CFDF_Document::~CFDF_Document() {}
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
tsepez05e01692016-11-28 17:30:09 -080032std::unique_ptr<CFDF_Document> CFDF_Document::ParseFile(
Dan Sinclair0b950422017-09-21 15:49:49 -040033 const RetainPtr<IFX_SeekableReadStream>& pFile) {
thestig2f1e05a2016-05-26 16:24:15 -070034 if (!pFile)
35 return nullptr;
36
tsepez05e01692016-11-28 17:30:09 -080037 auto pDoc = pdfium::MakeUnique<CFDF_Document>();
tsepez833619b2016-12-07 09:21:17 -080038 pDoc->ParseStream(pFile);
tsepez05e01692016-11-28 17:30:09 -080039 return pDoc->m_pRootDict ? std::move(pDoc) : nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070040}
thestig2f1e05a2016-05-26 16:24:15 -070041
tsepez833619b2016-12-07 09:21:17 -080042std::unique_ptr<CFDF_Document> CFDF_Document::ParseMemory(uint8_t* pData,
tsepez05e01692016-11-28 17:30:09 -080043 uint32_t size) {
Dan Sinclair283a0432017-04-20 14:11:21 -040044 return CFDF_Document::ParseFile(
45 pdfium::MakeRetain<CFX_MemoryStream>(pData, size, false));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070046}
thestig2f1e05a2016-05-26 16:24:15 -070047
tsepez833619b2016-12-07 09:21:17 -080048void CFDF_Document::ParseStream(
Dan Sinclair0b950422017-09-21 15:49:49 -040049 const RetainPtr<IFX_SeekableReadStream>& pFile) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070050 m_pFile = pFile;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070051 CPDF_SyntaxParser parser;
52 parser.InitParser(m_pFile, 0);
53 while (1) {
Lei Zhangec321272016-01-06 01:52:42 -080054 bool bNumber;
Ryan Harrison275e2602017-09-18 14:23:18 -040055 ByteString word = parser.GetNextWord(&bNumber);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070056 if (bNumber) {
tsepezb4c9f3f2016-04-13 15:41:21 -070057 uint32_t objnum = FXSYS_atoui(word.c_str());
tsepez761eed22016-11-04 11:02:59 -070058 if (!objnum)
59 break;
60
Lei Zhangec321272016-01-06 01:52:42 -080061 word = parser.GetNextWord(&bNumber);
thestig2f1e05a2016-05-26 16:24:15 -070062 if (!bNumber)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070063 break;
thestig2f1e05a2016-05-26 16:24:15 -070064
Lei Zhangec321272016-01-06 01:52:42 -080065 word = parser.GetNextWord(nullptr);
thestig2f1e05a2016-05-26 16:24:15 -070066 if (word != "obj")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067 break;
thestig2f1e05a2016-05-26 16:24:15 -070068
Artem Strygind8169d72017-10-02 19:19:28 +030069 std::unique_ptr<CPDF_Object> pObj = parser.GetObjectBody(this);
thestig2f1e05a2016-05-26 16:24:15 -070070 if (!pObj)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070071 break;
thestig2f1e05a2016-05-26 16:24:15 -070072
tsepez931d0872016-11-04 16:00:03 -070073 ReplaceIndirectObjectIfHigherGeneration(objnum, std::move(pObj));
Lei Zhangec321272016-01-06 01:52:42 -080074 word = parser.GetNextWord(nullptr);
thestig2f1e05a2016-05-26 16:24:15 -070075 if (word != "endobj")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070076 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070077 } else {
thestig2f1e05a2016-05-26 16:24:15 -070078 if (word != "trailer")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070079 break;
thestig2f1e05a2016-05-26 16:24:15 -070080
tsepez5ab31ef2016-11-07 13:49:17 -080081 std::unique_ptr<CPDF_Dictionary> pMainDict =
Artem Strygind8169d72017-10-02 19:19:28 +030082 ToDictionary(parser.GetObjectBody(this));
tsepez5ab31ef2016-11-07 13:49:17 -080083 if (pMainDict)
dsinclair38fd8442016-09-15 10:15:32 -070084 m_pRootDict = pMainDict->GetDictFor("Root");
tsepez5ab31ef2016-11-07 13:49:17 -080085
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070087 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070088 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070089}
thestig2f1e05a2016-05-26 16:24:15 -070090
Ryan Harrison275e2602017-09-18 14:23:18 -040091ByteString CFDF_Document::WriteToString() const {
dsinclaire07edce2016-08-23 20:14:27 -070092 if (!m_pRootDict)
Ryan Harrison275e2602017-09-18 14:23:18 -040093 return ByteString();
dsinclaire07edce2016-08-23 20:14:27 -070094
Henrique Nakashima5c09f4c2017-08-04 12:28:52 -040095 std::ostringstream buf;
Lei Zhangd983b092015-12-14 16:58:33 -080096 buf << "%FDF-1.2\r\n";
dsinclaire07edce2016-08-23 20:14:27 -070097 for (const auto& pair : *this)
tsepez5b7c9bb2016-09-20 12:02:32 -070098 buf << pair.first << " 0 obj\r\n"
99 << pair.second.get() << "\r\nendobj\r\n\r\n";
dsinclaire07edce2016-08-23 20:14:27 -0700100
Lei Zhangd983b092015-12-14 16:58:33 -0800101 buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum()
102 << " 0 R>>\r\n%%EOF\r\n";
Henrique Nakashima5c09f4c2017-08-04 12:28:52 -0400103
Ryan Harrison275e2602017-09-18 14:23:18 -0400104 return ByteString(buf);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700105}