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