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