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