blob: 22f9aa713f376889550fd24bde5f21dca6f9b0af [file] [log] [blame]
// 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;
}
}