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.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../../include/fpdfapi/fpdf_serial.h"
8 CFDF_Document::CFDF_Document() : CPDF_IndirectObjects(NULL)
14 CFDF_Document::~CFDF_Document()
16 if (m_bOwnFile && m_pFile) {
20 CFDF_Document* CFDF_Document::CreateNewDoc()
22 CFDF_Document* pDoc = FX_NEW CFDF_Document;
23 pDoc->m_pRootDict = FX_NEW CPDF_Dictionary;
24 pDoc->AddIndirectObject(pDoc->m_pRootDict);
25 CPDF_Dictionary* pFDFDict = FX_NEW CPDF_Dictionary;
26 pDoc->m_pRootDict->SetAt(FX_BSTRC("FDF"), pFDFDict);
29 CFDF_Document* CFDF_Document::ParseFile(FX_LPCSTR file_path)
31 return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE);
33 CFDF_Document* CFDF_Document::ParseFile(FX_LPCWSTR file_path)
35 return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE);
37 CFDF_Document* CFDF_Document::ParseFile(IFX_FileRead *pFile, FX_BOOL bOwnFile)
42 CFDF_Document* pDoc = FX_NEW CFDF_Document;
43 pDoc->ParseStream(pFile, bOwnFile);
44 if (pDoc->m_pRootDict == NULL) {
50 CFDF_Document* CFDF_Document::ParseMemory(FX_LPCBYTE pData, FX_DWORD size)
52 return CFDF_Document::ParseFile(FX_CreateMemoryStream((FX_LPBYTE)pData, size), TRUE);
54 void CFDF_Document::ParseStream(IFX_FileRead *pFile, FX_BOOL bOwnFile)
57 m_bOwnFile = bOwnFile;
58 CPDF_SyntaxParser parser;
59 parser.InitParser(m_pFile, 0);
62 CFX_ByteString word = parser.GetNextWord(bNumber);
64 FX_DWORD objnum = FXSYS_atoi(word);
65 word = parser.GetNextWord(bNumber);
69 word = parser.GetNextWord(bNumber);
70 if (word != FX_BSTRC("obj")) {
73 CPDF_Object* pObj = parser.GetObject(this, objnum, 0, FALSE);
77 InsertIndirectObject(objnum, pObj);
78 word = parser.GetNextWord(bNumber);
79 if (word != FX_BSTRC("endobj")) {
83 if (word != FX_BSTRC("trailer")) {
86 CPDF_Dictionary* pMainDict = (CPDF_Dictionary*)parser.GetObject(this, 0, 0, 0);
87 if (pMainDict == NULL || pMainDict->GetType() != PDFOBJ_DICTIONARY) {
90 m_pRootDict = pMainDict->GetDict(FX_BSTRC("Root"));
96 FX_BOOL CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const
98 if (m_pRootDict == NULL) {
101 buf << FX_BSTRC("%FDF-1.2\r\n");
102 FX_POSITION pos = m_IndirectObjs.GetStartPosition();
106 m_IndirectObjs.GetNextAssoc(pos, (FX_LPVOID&)objnum, (FX_LPVOID&)pObj);
107 buf << (FX_DWORD)objnum << FX_BSTRC(" 0 obj\r\n") << pObj << FX_BSTRC("\r\nendobj\r\n\r\n");
109 buf << FX_BSTRC("trailer\r\n<</Root ") << m_pRootDict->GetObjNum() << FX_BSTRC(" 0 R>>\r\n%%EOF\r\n");
112 CFX_WideString CFDF_Document::GetWin32Path() const
114 CPDF_Dictionary* pDict = m_pRootDict ? m_pRootDict->GetDict(FX_BSTRC("FDF")) : NULL;
115 CPDF_Object* pFileSpec = pDict ? pDict->GetElementValue(FX_BSTRC("F")) : NULL;
116 if (pFileSpec == NULL) {
117 return CFX_WideString();
119 if (pFileSpec->GetType() == PDFOBJ_STRING) {
120 return FPDF_FileSpec_GetWin32Path(m_pRootDict->GetDict(FX_BSTRC("FDF")));
122 return FPDF_FileSpec_GetWin32Path(pFileSpec);
124 FX_BOOL CFDF_Document::WriteFile(FX_LPCSTR file_path) const
126 IFX_FileWrite *pFile = FX_CreateFileWrite(file_path);
130 FX_BOOL bRet = WriteFile(pFile);
134 FX_BOOL CFDF_Document::WriteFile(FX_LPCWSTR file_path) const
136 IFX_FileWrite *pFile = FX_CreateFileWrite(file_path);
140 FX_BOOL bRet = WriteFile(pFile);
144 FX_BOOL CFDF_Document::WriteFile(IFX_FileWrite *pFile) const
148 FX_BOOL bRet = pFile->WriteBlock(buf.GetBuffer(), buf.GetSize());
154 static CFX_WideString ChangeSlash(FX_LPCWSTR str)
156 CFX_WideString result;
160 } else if (*str == '/') {
169 void FPDF_FileSpec_SetWin32Path(CPDF_Object* pFileSpec, const CFX_WideString& filepath)
171 CFX_WideString result;
172 if (filepath.GetLength() > 1 && filepath[1] == ':') {
174 result += filepath[0];
175 if (filepath[2] != '\\') {
178 result += ChangeSlash((FX_LPCWSTR)filepath + 2);
179 } else if (filepath.GetLength() > 1 && filepath[0] == '\\' && filepath[1] == '\\') {
180 result = ChangeSlash((FX_LPCWSTR)filepath + 1);
182 result = ChangeSlash(filepath);
184 if (pFileSpec->GetType() == PDFOBJ_STRING) {
185 pFileSpec->SetString(CFX_ByteString::FromUnicode(result));
186 } else if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) {
187 ((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(result));
188 ((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(result));
189 ((CPDF_Dictionary*)pFileSpec)->RemoveAt(FX_BSTRC("FS"));
192 CFX_WideString FPDF_FileSpec_GetWin32Path(const CPDF_Object* pFileSpec)
194 CFX_WideString wsFileName;
195 if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) {
196 CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFileSpec;
197 wsFileName = pDict->GetUnicodeText(FX_BSTRC("UF"));
198 if (wsFileName.IsEmpty()) {
199 wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("F")));
201 if (pDict->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL")) {
204 if (wsFileName.IsEmpty() && pDict->KeyExist(FX_BSTRC("DOS"))) {
205 wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("DOS")));
209 wsFileName = CFX_WideString();
211 wsFileName = CFX_WideString::FromLocal(pFileSpec->GetString());
213 if (wsFileName[0] != '/') {
214 return ChangeSlash(wsFileName);
216 if (wsFileName[2] == '/') {
217 CFX_WideString result;
218 result += wsFileName[1];
220 result += ChangeSlash(((FX_LPCWSTR)wsFileName) + 2);
223 CFX_WideString result;
225 result += ChangeSlash(wsFileName);