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 };
CPDF_Metadata()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 }
~CPDF_Metadata()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 }
LoadDoc(CPDF_Document * pDoc)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 }
GetString(FX_BSTR bsItem,CFX_WideString & wsStr)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 }
GetRoot() const141 CXML_Element* CPDF_Metadata::GetRoot() const
142 {
143 return ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt;
144 }
GetRDF() const145 CXML_Element* CPDF_Metadata::GetRDF() const
146 {
147 return ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf;
148 }
149