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