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