1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// found in the LICENSE file.
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/fpdfdoc/fpdf_doc.h"
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/fxcrt/fx_xml.h"
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct _PDFDOC_METADATA {
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CPDF_Document *m_pDoc;
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CXML_Element *m_pXmlElmnt;
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CXML_Element *m_pElmntRdf;
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_CMapByteStringToPtr *m_pStringMap;
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} PDFDOC_METADATA, * PDFDOC_LPMETADATA;
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef PDFDOC_METADATA const * PDFDOC_LPCMETADATA;
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovconst FX_LPCSTR gs_FPDFDOC_Metadata_Titles[] = {
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "Title", "title",
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "Subject", "description",
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "Author", "creator",
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "Keywords", "Keywords",
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "Producer", "Producer",
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "Creator", "CreatorTool",
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "CreationDate", "CreateDate",
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "ModDate", "ModifyDate",
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "MetadataDate", "MetadataDate"
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCPDF_Metadata::CPDF_Metadata()
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pData = FX_Alloc(PDFDOC_METADATA, 1);
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_memset32(m_pData, 0, sizeof(PDFDOC_METADATA));
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_CMapByteStringToPtr *&pStringMap = ((PDFDOC_LPMETADATA)m_pData)->m_pStringMap;
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pStringMap = FX_NEW(CFX_CMapByteStringToPtr);
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pStringMap != NULL) {
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_ByteString bstr;
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int i = 0; i < 18; i += 2) {
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            bstr = gs_FPDFDOC_Metadata_Titles[i];
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pStringMap->AddValue(bstr, (void*)gs_FPDFDOC_Metadata_Titles[i + 1]);
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCPDF_Metadata::~CPDF_Metadata()
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(m_pData != NULL);
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CXML_Element *&p = ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt;
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p) {
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        delete p;
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_CMapByteStringToPtr *pStringMap = ((PDFDOC_LPMETADATA)m_pData)->m_pStringMap;
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pStringMap) {
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pStringMap->RemoveAll();
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_Free(pStringMap);
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_Free(m_pData);
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CPDF_Metadata::LoadDoc(CPDF_Document *pDoc)
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXSYS_assert(pDoc != NULL);
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ((PDFDOC_LPMETADATA)m_pData)->m_pDoc = pDoc;
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CPDF_Dictionary *pRoot = pDoc->GetRoot();
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CPDF_Stream *pStream = pRoot->GetStream(FX_BSTRC("Metadata"));
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pStream) {
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CPDF_StreamAcc acc;
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    acc.LoadAllData(pStream, FALSE);
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int size = acc.GetSize();
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPCBYTE pBuf = acc.GetData();
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CXML_Element *&pXmlElmnt = ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt;
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pXmlElmnt = CXML_Element::Parse(pBuf, size);
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pXmlElmnt) {
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CXML_Element *&pElmntRdf = ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf;
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pXmlElmnt->GetTagName() == FX_BSTRC("RDF")) {
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pElmntRdf = pXmlElmnt;
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pElmntRdf = pXmlElmnt->GetElement(NULL, FX_BSTRC("RDF"));
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_INT32 CPDF_Metadata::GetString(FX_BSTR bsItem, CFX_WideString &wsStr)
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt) {
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return -1;
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!((PDFDOC_LPMETADATA)m_pData)->m_pStringMap) {
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return -1;
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void *szTag;
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!((PDFDOC_LPMETADATA)m_pData)->m_pStringMap->Lookup(bsItem, szTag)) {
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return -1;
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ByteString bsTag = (FX_LPCSTR)szTag;
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    wsStr = L"";
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CXML_Element *pElmntRdf = ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf;
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pElmntRdf) {
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return -1;
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int nChild = pElmntRdf->CountChildren();
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (int i = 0; i < nChild; i++) {
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CXML_Element *pTag = pElmntRdf->GetElement(NULL, FX_BSTRC("Description"), i);
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!pTag) {
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            continue;
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bsItem == FX_BSTRC("Title") || bsItem == FX_BSTRC("Subject")) {
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag);
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!pElmnt) {
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                continue;
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("Alt"));
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!pElmnt) {
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                continue;
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("li"));
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!pElmnt) {
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                continue;
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            wsStr = pElmnt->GetContent(0);
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return wsStr.GetLength();
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (bsItem == FX_BSTRC("Author")) {
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag);
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!pElmnt) {
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                continue;
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("Seq"));
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!pElmnt) {
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                continue;
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("li"));
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!pElmnt) {
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                continue;
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            wsStr = pElmnt->GetContent(0);
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return wsStr.GetLength();
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag);
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!pElmnt) {
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                continue;
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            wsStr = pElmnt->GetContent(0);
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return wsStr.GetLength();
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return -1;
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCXML_Element* CPDF_Metadata::GetRoot() const
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt;
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCXML_Element* CPDF_Metadata::GetRDF() const
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf;
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
153