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