Home | History | Annotate | Download | only in fpdf_parser
      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 {
     10     m_pRootDict = NULL;
     11     m_pFile = NULL;
     12     m_bOwnFile = FALSE;
     13 }
     14 CFDF_Document::~CFDF_Document()
     15 {
     16     if (m_bOwnFile && m_pFile) {
     17         m_pFile->Release();
     18     }
     19 }
     20 CFDF_Document* CFDF_Document::CreateNewDoc()
     21 {
     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);
     27     return pDoc;
     28 }
     29 CFDF_Document* CFDF_Document::ParseFile(FX_LPCSTR file_path)
     30 {
     31     return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE);
     32 }
     33 CFDF_Document* CFDF_Document::ParseFile(FX_LPCWSTR file_path)
     34 {
     35     return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE);
     36 }
     37 CFDF_Document* CFDF_Document::ParseFile(IFX_FileRead *pFile, FX_BOOL bOwnFile)
     38 {
     39     if (!pFile) {
     40         return NULL;
     41     }
     42     CFDF_Document* pDoc = FX_NEW CFDF_Document;
     43     pDoc->ParseStream(pFile, bOwnFile);
     44     if (pDoc->m_pRootDict == NULL) {
     45         delete pDoc;
     46         return NULL;
     47     }
     48     return pDoc;
     49 }
     50 CFDF_Document* CFDF_Document::ParseMemory(FX_LPCBYTE pData, FX_DWORD size)
     51 {
     52     return CFDF_Document::ParseFile(FX_CreateMemoryStream((FX_LPBYTE)pData, size), TRUE);
     53 }
     54 void CFDF_Document::ParseStream(IFX_FileRead *pFile, FX_BOOL bOwnFile)
     55 {
     56     m_pFile = pFile;
     57     m_bOwnFile = bOwnFile;
     58     CPDF_SyntaxParser parser;
     59     parser.InitParser(m_pFile, 0);
     60     while (1) {
     61         FX_BOOL bNumber;
     62         CFX_ByteString word = parser.GetNextWord(bNumber);
     63         if (bNumber) {
     64             FX_DWORD objnum = FXSYS_atoi(word);
     65             word = parser.GetNextWord(bNumber);
     66             if (!bNumber) {
     67                 break;
     68             }
     69             word = parser.GetNextWord(bNumber);
     70             if (word != FX_BSTRC("obj")) {
     71                 break;
     72             }
     73             CPDF_Object* pObj = parser.GetObject(this, objnum, 0, FALSE);
     74             if (pObj == NULL) {
     75                 break;
     76             }
     77             InsertIndirectObject(objnum, pObj);
     78             word = parser.GetNextWord(bNumber);
     79             if (word != FX_BSTRC("endobj")) {
     80                 break;
     81             }
     82         } else {
     83             if (word != FX_BSTRC("trailer")) {
     84                 break;
     85             }
     86             CPDF_Dictionary* pMainDict = (CPDF_Dictionary*)parser.GetObject(this, 0, 0, 0);
     87             if (pMainDict == NULL || pMainDict->GetType() != PDFOBJ_DICTIONARY) {
     88                 break;
     89             }
     90             m_pRootDict = pMainDict->GetDict(FX_BSTRC("Root"));
     91             pMainDict->Release();
     92             break;
     93         }
     94     }
     95 }
     96 FX_BOOL CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const
     97 {
     98     if (m_pRootDict == NULL) {
     99         return FALSE;
    100     }
    101     buf << FX_BSTRC("%FDF-1.2\r\n");
    102     FX_POSITION pos = m_IndirectObjs.GetStartPosition();
    103     while(pos) {
    104         size_t objnum;
    105         CPDF_Object* pObj;
    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");
    108     }
    109     buf << FX_BSTRC("trailer\r\n<</Root ") << m_pRootDict->GetObjNum() << FX_BSTRC(" 0 R>>\r\n%%EOF\r\n");
    110     return TRUE;
    111 }
    112 CFX_WideString CFDF_Document::GetWin32Path() const
    113 {
    114     CPDF_Object* pFileSpec = m_pRootDict->GetDict(FX_BSTRC("FDF"))->GetElementValue(FX_BSTRC("F"));
    115     if (pFileSpec == NULL) {
    116         return CFX_WideString();
    117     }
    118     if (pFileSpec->GetType() == PDFOBJ_STRING) {
    119         return FPDF_FileSpec_GetWin32Path(m_pRootDict->GetDict(FX_BSTRC("FDF")));
    120     }
    121     return FPDF_FileSpec_GetWin32Path(pFileSpec);
    122 }
    123 FX_BOOL CFDF_Document::WriteFile(FX_LPCSTR file_path) const
    124 {
    125     IFX_FileWrite *pFile = FX_CreateFileWrite(file_path);
    126     if (!pFile) {
    127         return FALSE;
    128     }
    129     FX_BOOL bRet = WriteFile(pFile);
    130     pFile->Release();
    131     return bRet;
    132 }
    133 FX_BOOL CFDF_Document::WriteFile(FX_LPCWSTR file_path) const
    134 {
    135     IFX_FileWrite *pFile = FX_CreateFileWrite(file_path);
    136     if (!pFile) {
    137         return FALSE;
    138     }
    139     FX_BOOL bRet = WriteFile(pFile);
    140     pFile->Release();
    141     return bRet;
    142 }
    143 FX_BOOL CFDF_Document::WriteFile(IFX_FileWrite *pFile) const
    144 {
    145     CFX_ByteTextBuf buf;
    146     WriteBuf(buf);
    147     FX_BOOL bRet = pFile->WriteBlock(buf.GetBuffer(), buf.GetSize());
    148     if (bRet) {
    149         pFile->Flush();
    150     }
    151     return bRet;
    152 }
    153 static CFX_WideString ChangeSlash(FX_LPCWSTR str)
    154 {
    155     CFX_WideString result;
    156     while (*str) {
    157         if (*str == '\\') {
    158             result += '/';
    159         } else if (*str == '/') {
    160             result += '\\';
    161         } else {
    162             result += *str;
    163         }
    164         str ++;
    165     }
    166     return result;
    167 }
    168 void FPDF_FileSpec_SetWin32Path(CPDF_Object* pFileSpec, const CFX_WideString& filepath)
    169 {
    170     CFX_WideString result;
    171     if (filepath.GetLength() > 1 && filepath[1] == ':') {
    172         result = L"/";
    173         result += filepath[0];
    174         if (filepath[2] != '\\') {
    175             result += '/';
    176         }
    177         result += ChangeSlash((FX_LPCWSTR)filepath + 2);
    178     } else if (filepath.GetLength() > 1 && filepath[0] == '\\' && filepath[1] == '\\') {
    179         result = ChangeSlash((FX_LPCWSTR)filepath + 1);
    180     } else {
    181         result = ChangeSlash(filepath);
    182     }
    183     if (pFileSpec->GetType() == PDFOBJ_STRING) {
    184         pFileSpec->SetString(CFX_ByteString::FromUnicode(result));
    185     } else if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) {
    186         ((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(result));
    187         ((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(result));
    188         ((CPDF_Dictionary*)pFileSpec)->RemoveAt(FX_BSTRC("FS"));
    189     }
    190 }
    191 CFX_WideString	FPDF_FileSpec_GetWin32Path(const CPDF_Object* pFileSpec)
    192 {
    193     CFX_WideString wsFileName;
    194     if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) {
    195         CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFileSpec;
    196         wsFileName = pDict->GetUnicodeText(FX_BSTRC("UF"));
    197         if (wsFileName.IsEmpty()) {
    198             wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("F")));
    199         }
    200         if (pDict->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL")) {
    201             return wsFileName;
    202         }
    203         if (wsFileName.IsEmpty() && pDict->KeyExist(FX_BSTRC("DOS"))) {
    204             wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("DOS")));
    205         }
    206     } else {
    207         wsFileName = CFX_WideString::FromLocal(pFileSpec->GetString());
    208     }
    209     if (wsFileName[0] != '/') {
    210         return ChangeSlash(wsFileName);
    211     }
    212     if (wsFileName[2] == '/') {
    213         CFX_WideString result;
    214         result += wsFileName[1];
    215         result += ':';
    216         result += ChangeSlash(((FX_LPCWSTR)wsFileName) + 2);
    217         return result;
    218     } else {
    219         CFX_WideString result;
    220         result += '\\';
    221         result += ChangeSlash(wsFileName);
    222         return result;
    223     }
    224 }
    225