• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
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/parser/cfdf_document.h"
8 
9 #include <memory>
10 #include <sstream>
11 #include <utility>
12 
13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
14 #include "core/fpdfapi/parser/cpdf_syntax_parser.h"
15 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
16 #include "core/fxcrt/cfx_read_only_span_stream.h"
17 #include "core/fxcrt/fx_string_wrappers.h"
18 #include "core/fxcrt/span.h"
19 
20 CFDF_Document::CFDF_Document() = default;
21 
22 CFDF_Document::~CFDF_Document() = default;
23 
CreateNewDoc()24 std::unique_ptr<CFDF_Document> CFDF_Document::CreateNewDoc() {
25   auto pDoc = std::make_unique<CFDF_Document>();
26   pDoc->m_pRootDict = pDoc->NewIndirect<CPDF_Dictionary>();
27   pDoc->m_pRootDict->SetNewFor<CPDF_Dictionary>("FDF");
28   return pDoc;
29 }
30 
ParseMemory(pdfium::span<const uint8_t> span)31 std::unique_ptr<CFDF_Document> CFDF_Document::ParseMemory(
32     pdfium::span<const uint8_t> span) {
33   auto pDoc = std::make_unique<CFDF_Document>();
34   pDoc->ParseStream(pdfium::MakeRetain<CFX_ReadOnlySpanStream>(span));
35   if (!pDoc->m_pRootDict) {
36     return nullptr;
37   }
38   return pDoc;
39 }
40 
ParseStream(RetainPtr<IFX_SeekableReadStream> pFile)41 void CFDF_Document::ParseStream(RetainPtr<IFX_SeekableReadStream> pFile) {
42   m_pFile = std::move(pFile);
43   CPDF_SyntaxParser parser(m_pFile);
44   while (true) {
45     CPDF_SyntaxParser::WordResult word_result = parser.GetNextWord();
46     if (word_result.is_number) {
47       uint32_t objnum = FXSYS_atoui(word_result.word.c_str());
48       if (!objnum)
49         break;
50 
51       word_result = parser.GetNextWord();
52       if (!word_result.is_number)
53         break;
54 
55       word_result = parser.GetNextWord();
56       if (word_result.word != "obj")
57         break;
58 
59       RetainPtr<CPDF_Object> pObj = parser.GetObjectBody(this);
60       if (!pObj)
61         break;
62 
63       ReplaceIndirectObjectIfHigherGeneration(objnum, std::move(pObj));
64       word_result = parser.GetNextWord();
65       if (word_result.word != "endobj")
66         break;
67     } else {
68       if (word_result.word != "trailer")
69         break;
70 
71       RetainPtr<CPDF_Dictionary> pMainDict =
72           ToDictionary(parser.GetObjectBody(this));
73       if (pMainDict)
74         m_pRootDict = pMainDict->GetMutableDictFor("Root");
75 
76       break;
77     }
78   }
79 }
80 
WriteToString() const81 ByteString CFDF_Document::WriteToString() const {
82   if (!m_pRootDict)
83     return ByteString();
84 
85   fxcrt::ostringstream buf;
86   buf << "%FDF-1.2\r\n";
87   for (const auto& pair : *this)
88     buf << pair.first << " 0 obj\r\n"
89         << pair.second.Get() << "\r\nendobj\r\n\r\n";
90 
91   buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum()
92       << " 0 R>>\r\n%%EOF\r\n";
93 
94   return ByteString(buf);
95 }
96