// Copyright 2014 PDFium Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license that can be | |
// found in the LICENSE file. | |
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
#include "../../../include/fpdfapi/fpdf_serial.h" | |
CFDF_Document::CFDF_Document() : CPDF_IndirectObjects(NULL) | |
{ | |
m_pRootDict = NULL; | |
m_pFile = NULL; | |
m_bOwnFile = FALSE; | |
} | |
CFDF_Document::~CFDF_Document() | |
{ | |
if (m_bOwnFile && m_pFile) { | |
m_pFile->Release(); | |
} | |
} | |
CFDF_Document* CFDF_Document::CreateNewDoc() | |
{ | |
CFDF_Document* pDoc = FX_NEW CFDF_Document; | |
pDoc->m_pRootDict = FX_NEW CPDF_Dictionary; | |
pDoc->AddIndirectObject(pDoc->m_pRootDict); | |
CPDF_Dictionary* pFDFDict = FX_NEW CPDF_Dictionary; | |
pDoc->m_pRootDict->SetAt(FX_BSTRC("FDF"), pFDFDict); | |
return pDoc; | |
} | |
CFDF_Document* CFDF_Document::ParseFile(FX_LPCSTR file_path) | |
{ | |
return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE); | |
} | |
CFDF_Document* CFDF_Document::ParseFile(FX_LPCWSTR file_path) | |
{ | |
return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE); | |
} | |
CFDF_Document* CFDF_Document::ParseFile(IFX_FileRead *pFile, FX_BOOL bOwnFile) | |
{ | |
if (!pFile) { | |
return NULL; | |
} | |
CFDF_Document* pDoc = FX_NEW CFDF_Document; | |
pDoc->ParseStream(pFile, bOwnFile); | |
if (pDoc->m_pRootDict == NULL) { | |
delete pDoc; | |
return NULL; | |
} | |
return pDoc; | |
} | |
CFDF_Document* CFDF_Document::ParseMemory(FX_LPCBYTE pData, FX_DWORD size) | |
{ | |
return CFDF_Document::ParseFile(FX_CreateMemoryStream((FX_LPBYTE)pData, size), TRUE); | |
} | |
void CFDF_Document::ParseStream(IFX_FileRead *pFile, FX_BOOL bOwnFile) | |
{ | |
m_pFile = pFile; | |
m_bOwnFile = bOwnFile; | |
CPDF_SyntaxParser parser; | |
parser.InitParser(m_pFile, 0); | |
while (1) { | |
FX_BOOL bNumber; | |
CFX_ByteString word = parser.GetNextWord(bNumber); | |
if (bNumber) { | |
FX_DWORD objnum = FXSYS_atoi(word); | |
word = parser.GetNextWord(bNumber); | |
if (!bNumber) { | |
break; | |
} | |
word = parser.GetNextWord(bNumber); | |
if (word != FX_BSTRC("obj")) { | |
break; | |
} | |
CPDF_Object* pObj = parser.GetObject(this, objnum, 0, FALSE); | |
if (pObj == NULL) { | |
break; | |
} | |
InsertIndirectObject(objnum, pObj); | |
word = parser.GetNextWord(bNumber); | |
if (word != FX_BSTRC("endobj")) { | |
break; | |
} | |
} else { | |
if (word != FX_BSTRC("trailer")) { | |
break; | |
} | |
CPDF_Dictionary* pMainDict = (CPDF_Dictionary*)parser.GetObject(this, 0, 0, 0); | |
if (pMainDict == NULL || pMainDict->GetType() != PDFOBJ_DICTIONARY) { | |
break; | |
} | |
m_pRootDict = pMainDict->GetDict(FX_BSTRC("Root")); | |
pMainDict->Release(); | |
break; | |
} | |
} | |
} | |
FX_BOOL CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const | |
{ | |
if (m_pRootDict == NULL) { | |
return FALSE; | |
} | |
buf << FX_BSTRC("%FDF-1.2\r\n"); | |
FX_POSITION pos = m_IndirectObjs.GetStartPosition(); | |
while(pos) { | |
size_t objnum; | |
CPDF_Object* pObj; | |
m_IndirectObjs.GetNextAssoc(pos, (FX_LPVOID&)objnum, (FX_LPVOID&)pObj); | |
buf << (FX_DWORD)objnum << FX_BSTRC(" 0 obj\r\n") << pObj << FX_BSTRC("\r\nendobj\r\n\r\n"); | |
} | |
buf << FX_BSTRC("trailer\r\n<</Root ") << m_pRootDict->GetObjNum() << FX_BSTRC(" 0 R>>\r\n%%EOF\r\n"); | |
return TRUE; | |
} | |
CFX_WideString CFDF_Document::GetWin32Path() const | |
{ | |
CPDF_Object* pFileSpec = m_pRootDict->GetDict(FX_BSTRC("FDF"))->GetElementValue(FX_BSTRC("F")); | |
if (pFileSpec == NULL) { | |
return CFX_WideString(); | |
} | |
if (pFileSpec->GetType() == PDFOBJ_STRING) { | |
return FPDF_FileSpec_GetWin32Path(m_pRootDict->GetDict(FX_BSTRC("FDF"))); | |
} | |
return FPDF_FileSpec_GetWin32Path(pFileSpec); | |
} | |
FX_BOOL CFDF_Document::WriteFile(FX_LPCSTR file_path) const | |
{ | |
IFX_FileWrite *pFile = FX_CreateFileWrite(file_path); | |
if (!pFile) { | |
return FALSE; | |
} | |
FX_BOOL bRet = WriteFile(pFile); | |
pFile->Release(); | |
return bRet; | |
} | |
FX_BOOL CFDF_Document::WriteFile(FX_LPCWSTR file_path) const | |
{ | |
IFX_FileWrite *pFile = FX_CreateFileWrite(file_path); | |
if (!pFile) { | |
return FALSE; | |
} | |
FX_BOOL bRet = WriteFile(pFile); | |
pFile->Release(); | |
return bRet; | |
} | |
FX_BOOL CFDF_Document::WriteFile(IFX_FileWrite *pFile) const | |
{ | |
CFX_ByteTextBuf buf; | |
WriteBuf(buf); | |
FX_BOOL bRet = pFile->WriteBlock(buf.GetBuffer(), buf.GetSize()); | |
if (bRet) { | |
pFile->Flush(); | |
} | |
return bRet; | |
} | |
static CFX_WideString ChangeSlash(FX_LPCWSTR str) | |
{ | |
CFX_WideString result; | |
while (*str) { | |
if (*str == '\\') { | |
result += '/'; | |
} else if (*str == '/') { | |
result += '\\'; | |
} else { | |
result += *str; | |
} | |
str ++; | |
} | |
return result; | |
} | |
void FPDF_FileSpec_SetWin32Path(CPDF_Object* pFileSpec, const CFX_WideString& filepath) | |
{ | |
CFX_WideString result; | |
if (filepath.GetLength() > 1 && filepath[1] == ':') { | |
result = L"/"; | |
result += filepath[0]; | |
if (filepath[2] != '\\') { | |
result += '/'; | |
} | |
result += ChangeSlash((FX_LPCWSTR)filepath + 2); | |
} else if (filepath.GetLength() > 1 && filepath[0] == '\\' && filepath[1] == '\\') { | |
result = ChangeSlash((FX_LPCWSTR)filepath + 1); | |
} else { | |
result = ChangeSlash(filepath); | |
} | |
if (pFileSpec->GetType() == PDFOBJ_STRING) { | |
pFileSpec->SetString(CFX_ByteString::FromUnicode(result)); | |
} else if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) { | |
((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(result)); | |
((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(result)); | |
((CPDF_Dictionary*)pFileSpec)->RemoveAt(FX_BSTRC("FS")); | |
} | |
} | |
CFX_WideString FPDF_FileSpec_GetWin32Path(const CPDF_Object* pFileSpec) | |
{ | |
CFX_WideString wsFileName; | |
if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) { | |
CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFileSpec; | |
wsFileName = pDict->GetUnicodeText(FX_BSTRC("UF")); | |
if (wsFileName.IsEmpty()) { | |
wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("F"))); | |
} | |
if (pDict->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL")) { | |
return wsFileName; | |
} | |
if (wsFileName.IsEmpty() && pDict->KeyExist(FX_BSTRC("DOS"))) { | |
wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("DOS"))); | |
} | |
} else { | |
wsFileName = CFX_WideString::FromLocal(pFileSpec->GetString()); | |
} | |
if (wsFileName[0] != '/') { | |
return ChangeSlash(wsFileName); | |
} | |
if (wsFileName[2] == '/') { | |
CFX_WideString result; | |
result += wsFileName[1]; | |
result += ':'; | |
result += ChangeSlash(((FX_LPCWSTR)wsFileName) + 2); | |
return result; | |
} else { | |
CFX_WideString result; | |
result += '\\'; | |
result += ChangeSlash(wsFileName); | |
return result; | |
} | |
} |