• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/include/fpdfapi/fpdf_parser.h"
8 
9 #include "core/include/fpdfapi/fpdf_serial.h"
10 
CFDF_Document()11 CFDF_Document::CFDF_Document() : CPDF_IndirectObjectHolder(NULL) {
12   m_pRootDict = NULL;
13   m_pFile = NULL;
14   m_bOwnFile = FALSE;
15 }
~CFDF_Document()16 CFDF_Document::~CFDF_Document() {
17   if (m_bOwnFile && m_pFile) {
18     m_pFile->Release();
19   }
20 }
CreateNewDoc()21 CFDF_Document* CFDF_Document::CreateNewDoc() {
22   CFDF_Document* pDoc = new CFDF_Document;
23   pDoc->m_pRootDict = new CPDF_Dictionary;
24   pDoc->AddIndirectObject(pDoc->m_pRootDict);
25   CPDF_Dictionary* pFDFDict = new CPDF_Dictionary;
26   pDoc->m_pRootDict->SetAt("FDF", pFDFDict);
27   return pDoc;
28 }
ParseFile(IFX_FileRead * pFile,FX_BOOL bOwnFile)29 CFDF_Document* CFDF_Document::ParseFile(IFX_FileRead* pFile, FX_BOOL bOwnFile) {
30   if (!pFile) {
31     return NULL;
32   }
33   CFDF_Document* pDoc = new CFDF_Document;
34   pDoc->ParseStream(pFile, bOwnFile);
35   if (!pDoc->m_pRootDict) {
36     delete pDoc;
37     return NULL;
38   }
39   return pDoc;
40 }
ParseMemory(const uint8_t * pData,FX_DWORD size)41 CFDF_Document* CFDF_Document::ParseMemory(const uint8_t* pData, FX_DWORD size) {
42   return CFDF_Document::ParseFile(FX_CreateMemoryStream((uint8_t*)pData, size),
43                                   TRUE);
44 }
ParseStream(IFX_FileRead * pFile,FX_BOOL bOwnFile)45 void CFDF_Document::ParseStream(IFX_FileRead* pFile, FX_BOOL bOwnFile) {
46   m_pFile = pFile;
47   m_bOwnFile = bOwnFile;
48   CPDF_SyntaxParser parser;
49   parser.InitParser(m_pFile, 0);
50   while (1) {
51     bool bNumber;
52     CFX_ByteString word = parser.GetNextWord(&bNumber);
53     if (bNumber) {
54       FX_DWORD objnum = FXSYS_atoi(word);
55       word = parser.GetNextWord(&bNumber);
56       if (!bNumber) {
57         break;
58       }
59       word = parser.GetNextWord(nullptr);
60       if (word != "obj") {
61         break;
62       }
63       CPDF_Object* pObj = parser.GetObject(this, objnum, 0, nullptr, true);
64       if (!pObj) {
65         break;
66       }
67       InsertIndirectObject(objnum, pObj);
68       word = parser.GetNextWord(nullptr);
69       if (word != "endobj") {
70         break;
71       }
72     } else {
73       if (word != "trailer") {
74         break;
75       }
76       if (CPDF_Dictionary* pMainDict =
77               ToDictionary(parser.GetObject(this, 0, 0, nullptr, true))) {
78         m_pRootDict = pMainDict->GetDict("Root");
79         pMainDict->Release();
80       }
81       break;
82     }
83   }
84 }
WriteBuf(CFX_ByteTextBuf & buf) const85 FX_BOOL CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const {
86   if (!m_pRootDict) {
87     return FALSE;
88   }
89   buf << "%FDF-1.2\r\n";
90   for (const auto& pair : m_IndirectObjs) {
91     buf << pair.first << " 0 obj\r\n" << pair.second << "\r\nendobj\r\n\r\n";
92   }
93   buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum()
94       << " 0 R>>\r\n%%EOF\r\n";
95   return TRUE;
96 }
GetWin32Path() const97 CFX_WideString CFDF_Document::GetWin32Path() const {
98   CPDF_Dictionary* pDict = m_pRootDict ? m_pRootDict->GetDict("FDF") : NULL;
99   CPDF_Object* pFileSpec = pDict ? pDict->GetElementValue("F") : NULL;
100   if (!pFileSpec)
101     return CFX_WideString();
102   if (pFileSpec->IsString())
103     return FPDF_FileSpec_GetWin32Path(m_pRootDict->GetDict("FDF"));
104   return FPDF_FileSpec_GetWin32Path(pFileSpec);
105 }
ChangeSlash(const FX_WCHAR * str)106 static CFX_WideString ChangeSlash(const FX_WCHAR* str) {
107   CFX_WideString result;
108   while (*str) {
109     if (*str == '\\') {
110       result += '/';
111     } else if (*str == '/') {
112       result += '\\';
113     } else {
114       result += *str;
115     }
116     str++;
117   }
118   return result;
119 }
FPDF_FileSpec_SetWin32Path(CPDF_Object * pFileSpec,const CFX_WideString & filepath)120 void FPDF_FileSpec_SetWin32Path(CPDF_Object* pFileSpec,
121                                 const CFX_WideString& filepath) {
122   CFX_WideString result;
123   if (filepath.GetLength() > 1 && filepath[1] == ':') {
124     result = L"/";
125     result += filepath[0];
126     if (filepath[2] != '\\') {
127       result += '/';
128     }
129     result += ChangeSlash(filepath.c_str() + 2);
130   } else if (filepath.GetLength() > 1 && filepath[0] == '\\' &&
131              filepath[1] == '\\') {
132     result = ChangeSlash(filepath.c_str() + 1);
133   } else {
134     result = ChangeSlash(filepath.c_str());
135   }
136 
137   if (pFileSpec->IsString()) {
138     pFileSpec->SetString(CFX_ByteString::FromUnicode(result));
139   } else if (CPDF_Dictionary* pFileDict = pFileSpec->AsDictionary()) {
140     pFileDict->SetAtString("F", CFX_ByteString::FromUnicode(result));
141     pFileDict->SetAtString("UF", PDF_EncodeText(result));
142     pFileDict->RemoveAt("FS");
143   }
144 }
FPDF_FileSpec_GetWin32Path(const CPDF_Object * pFileSpec)145 CFX_WideString FPDF_FileSpec_GetWin32Path(const CPDF_Object* pFileSpec) {
146   CFX_WideString wsFileName;
147   if (!pFileSpec) {
148     wsFileName = CFX_WideString();
149   } else if (const CPDF_Dictionary* pDict = pFileSpec->AsDictionary()) {
150     wsFileName = pDict->GetUnicodeText("UF");
151     if (wsFileName.IsEmpty()) {
152       wsFileName = CFX_WideString::FromLocal(pDict->GetString("F"));
153     }
154     if (pDict->GetString("FS") == "URL") {
155       return wsFileName;
156     }
157     if (wsFileName.IsEmpty() && pDict->KeyExist("DOS")) {
158       wsFileName = CFX_WideString::FromLocal(pDict->GetString("DOS"));
159     }
160   } else {
161     wsFileName = CFX_WideString::FromLocal(pFileSpec->GetString());
162   }
163   if (wsFileName[0] != '/') {
164     return ChangeSlash(wsFileName.c_str());
165   }
166   if (wsFileName[2] == '/') {
167     CFX_WideString result;
168     result += wsFileName[1];
169     result += ':';
170     result += ChangeSlash(wsFileName.c_str() + 2);
171     return result;
172   }
173   CFX_WideString result;
174   result += '\\';
175   result += ChangeSlash(wsFileName.c_str());
176   return result;
177 }
178