8c00157990a5f47a6fb63084e3066d020c1a96ae
[pdfium.git] / core / src / fpdfdoc / doc_metadata.cpp
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 }