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/fpdfdoc/fpdf_doc.h" 8 #include "../../include/fxcrt/fx_xml.h" 9 typedef struct _PDFDOC_METADATA { 10 CPDF_Document *m_pDoc; 11 CXML_Element *m_pXmlElmnt; 12 CXML_Element *m_pElmntRdf; 13 CFX_CMapByteStringToPtr *m_pStringMap; 14 } PDFDOC_METADATA, * PDFDOC_LPMETADATA; 15 typedef PDFDOC_METADATA const * PDFDOC_LPCMETADATA; 16 const FX_LPCSTR gs_FPDFDOC_Metadata_Titles[] = { 17 "Title", "title", 18 "Subject", "description", 19 "Author", "creator", 20 "Keywords", "Keywords", 21 "Producer", "Producer", 22 "Creator", "CreatorTool", 23 "CreationDate", "CreateDate", 24 "ModDate", "ModifyDate", 25 "MetadataDate", "MetadataDate" 26 }; 27 CPDF_Metadata::CPDF_Metadata() 28 { 29 m_pData = FX_Alloc(PDFDOC_METADATA, 1); 30 CFX_CMapByteStringToPtr *&pStringMap = ((PDFDOC_LPMETADATA)m_pData)->m_pStringMap; 31 pStringMap = new CFX_CMapByteStringToPtr; 32 CFX_ByteString bstr; 33 for (int i = 0; i < 18; i += 2) { 34 bstr = gs_FPDFDOC_Metadata_Titles[i]; 35 pStringMap->AddValue(bstr, (void*)gs_FPDFDOC_Metadata_Titles[i + 1]); 36 } 37 38 } 39 CPDF_Metadata::~CPDF_Metadata() 40 { 41 FXSYS_assert(m_pData != NULL); 42 CXML_Element *&p = ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt; 43 delete p; 44 CFX_CMapByteStringToPtr *pStringMap = ((PDFDOC_LPMETADATA)m_pData)->m_pStringMap; 45 if (pStringMap) { 46 pStringMap->RemoveAll(); 47 delete pStringMap; 48 } 49 FX_Free(m_pData); 50 } 51 void CPDF_Metadata::LoadDoc(CPDF_Document *pDoc) 52 { 53 FXSYS_assert(pDoc != NULL); 54 ((PDFDOC_LPMETADATA)m_pData)->m_pDoc = pDoc; 55 CPDF_Dictionary *pRoot = pDoc->GetRoot(); 56 CPDF_Stream *pStream = pRoot->GetStream(FX_BSTRC("Metadata")); 57 if (!pStream) { 58 return; 59 } 60 CPDF_StreamAcc acc; 61 acc.LoadAllData(pStream, FALSE); 62 int size = acc.GetSize(); 63 FX_LPCBYTE pBuf = acc.GetData(); 64 CXML_Element *&pXmlElmnt = ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt; 65 pXmlElmnt = CXML_Element::Parse(pBuf, size); 66 if (!pXmlElmnt) { 67 return; 68 } 69 CXML_Element *&pElmntRdf = ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf; 70 if (pXmlElmnt->GetTagName() == FX_BSTRC("RDF")) { 71 pElmntRdf = pXmlElmnt; 72 } else { 73 pElmntRdf = pXmlElmnt->GetElement(NULL, FX_BSTRC("RDF")); 74 } 75 } 76 FX_INT32 CPDF_Metadata::GetString(FX_BSTR bsItem, CFX_WideString &wsStr) 77 { 78 if (!((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt) { 79 return -1; 80 } 81 if (!((PDFDOC_LPMETADATA)m_pData)->m_pStringMap) { 82 return -1; 83 } 84 void *szTag; 85 if (!((PDFDOC_LPMETADATA)m_pData)->m_pStringMap->Lookup(bsItem, szTag)) { 86 return -1; 87 } 88 CFX_ByteString bsTag = (FX_LPCSTR)szTag; 89 wsStr = L""; 90 CXML_Element *pElmntRdf = ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf; 91 if (!pElmntRdf) { 92 return -1; 93 } 94 int nChild = pElmntRdf->CountChildren(); 95 for (int i = 0; i < nChild; i++) { 96 CXML_Element *pTag = pElmntRdf->GetElement(NULL, FX_BSTRC("Description"), i); 97 if (!pTag) { 98 continue; 99 } 100 if (bsItem == FX_BSTRC("Title") || bsItem == FX_BSTRC("Subject")) { 101 CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag); 102 if (!pElmnt) { 103 continue; 104 } 105 pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("Alt")); 106 if (!pElmnt) { 107 continue; 108 } 109 pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("li")); 110 if (!pElmnt) { 111 continue; 112 } 113 wsStr = pElmnt->GetContent(0); 114 return wsStr.GetLength(); 115 } else if (bsItem == FX_BSTRC("Author")) { 116 CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag); 117 if (!pElmnt) { 118 continue; 119 } 120 pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("Seq")); 121 if (!pElmnt) { 122 continue; 123 } 124 pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("li")); 125 if (!pElmnt) { 126 continue; 127 } 128 wsStr = pElmnt->GetContent(0); 129 return wsStr.GetLength(); 130 } else { 131 CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag); 132 if (!pElmnt) { 133 continue; 134 } 135 wsStr = pElmnt->GetContent(0); 136 return wsStr.GetLength(); 137 } 138 } 139 return -1; 140 } 141 CXML_Element* CPDF_Metadata::GetRoot() const 142 { 143 return ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt; 144 } 145 CXML_Element* CPDF_Metadata::GetRDF() const 146 { 147 return ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf; 148 } 149