Home | History | Annotate | Download | only in parser
      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/parser/cfdf_document.h"
      8 
      9 #include <memory>
     10 #include <utility>
     11 
     12 #include "core/fpdfapi/edit/cpdf_creator.h"
     13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     14 #include "core/fpdfapi/parser/cpdf_syntax_parser.h"
     15 #include "third_party/base/ptr_util.h"
     16 
     17 CFDF_Document::CFDF_Document()
     18     : CPDF_IndirectObjectHolder(), m_pRootDict(nullptr) {}
     19 
     20 CFDF_Document::~CFDF_Document() {}
     21 
     22 std::unique_ptr<CFDF_Document> CFDF_Document::CreateNewDoc() {
     23   auto pDoc = pdfium::MakeUnique<CFDF_Document>();
     24   pDoc->m_pRootDict = pDoc->NewIndirect<CPDF_Dictionary>();
     25   pDoc->m_pRootDict->SetNewFor<CPDF_Dictionary>("FDF");
     26   return pDoc;
     27 }
     28 
     29 std::unique_ptr<CFDF_Document> CFDF_Document::ParseFile(
     30     const CFX_RetainPtr<IFX_SeekableReadStream>& pFile) {
     31   if (!pFile)
     32     return nullptr;
     33 
     34   auto pDoc = pdfium::MakeUnique<CFDF_Document>();
     35   pDoc->ParseStream(pFile);
     36   return pDoc->m_pRootDict ? std::move(pDoc) : nullptr;
     37 }
     38 
     39 std::unique_ptr<CFDF_Document> CFDF_Document::ParseMemory(uint8_t* pData,
     40                                                           uint32_t size) {
     41   return CFDF_Document::ParseFile(IFX_MemoryStream::Create(pData, size));
     42 }
     43 
     44 void CFDF_Document::ParseStream(
     45     const CFX_RetainPtr<IFX_SeekableReadStream>& pFile) {
     46   m_pFile = pFile;
     47   CPDF_SyntaxParser parser;
     48   parser.InitParser(m_pFile, 0);
     49   while (1) {
     50     bool bNumber;
     51     CFX_ByteString word = parser.GetNextWord(&bNumber);
     52     if (bNumber) {
     53       uint32_t objnum = FXSYS_atoui(word.c_str());
     54       if (!objnum)
     55         break;
     56 
     57       word = parser.GetNextWord(&bNumber);
     58       if (!bNumber)
     59         break;
     60 
     61       word = parser.GetNextWord(nullptr);
     62       if (word != "obj")
     63         break;
     64 
     65       std::unique_ptr<CPDF_Object> pObj =
     66           parser.GetObject(this, objnum, 0, true);
     67       if (!pObj)
     68         break;
     69 
     70       ReplaceIndirectObjectIfHigherGeneration(objnum, std::move(pObj));
     71       word = parser.GetNextWord(nullptr);
     72       if (word != "endobj")
     73         break;
     74     } else {
     75       if (word != "trailer")
     76         break;
     77 
     78       std::unique_ptr<CPDF_Dictionary> pMainDict =
     79           ToDictionary(parser.GetObject(this, 0, 0, true));
     80       if (pMainDict)
     81         m_pRootDict = pMainDict->GetDictFor("Root");
     82 
     83       break;
     84     }
     85   }
     86 }
     87 
     88 bool CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const {
     89   if (!m_pRootDict)
     90     return false;
     91 
     92   buf << "%FDF-1.2\r\n";
     93   for (const auto& pair : *this)
     94     buf << pair.first << " 0 obj\r\n"
     95         << pair.second.get() << "\r\nendobj\r\n\r\n";
     96 
     97   buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum()
     98       << " 0 R>>\r\n%%EOF\r\n";
     99   return true;
    100 }
    101