• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 "core/fxcrt/xml/cfx_xmldoc.h"
8 
9 #include <utility>
10 #include <vector>
11 
12 #include "core/fxcrt/fx_codepage.h"
13 #include "core/fxcrt/xml/cfx_xmlchardata.h"
14 #include "core/fxcrt/xml/cfx_xmlelement.h"
15 #include "core/fxcrt/xml/cfx_xmlinstruction.h"
16 #include "core/fxcrt/xml/cfx_xmlnode.h"
17 #include "core/fxcrt/xml/cfx_xmltext.h"
18 #include "third_party/base/ptr_util.h"
19 #include "third_party/base/stl_util.h"
20 
CFX_XMLDoc()21 CFX_XMLDoc::CFX_XMLDoc()
22     : m_iStatus(0), m_pRoot(pdfium::MakeUnique<CFX_XMLNode>()) {
23   m_pRoot->InsertChildNode(new CFX_XMLInstruction(L"xml"));
24 }
25 
~CFX_XMLDoc()26 CFX_XMLDoc::~CFX_XMLDoc() {}
27 
LoadXML(std::unique_ptr<CFX_XMLParser> pXMLParser)28 bool CFX_XMLDoc::LoadXML(std::unique_ptr<CFX_XMLParser> pXMLParser) {
29   if (!pXMLParser)
30     return false;
31 
32   m_iStatus = 0;
33   m_pStream.Reset();
34   m_pRoot->DeleteChildren();
35   m_pXMLParser = std::move(pXMLParser);
36   return true;
37 }
38 
DoLoad()39 int32_t CFX_XMLDoc::DoLoad() {
40   if (m_iStatus < 100)
41     m_iStatus = m_pXMLParser->DoParser();
42 
43   return m_iStatus;
44 }
45 
CloseXML()46 void CFX_XMLDoc::CloseXML() {
47   m_pXMLParser.reset();
48 }
49 
SaveXMLNode(const RetainPtr<CFX_SeekableStreamProxy> & pXMLStream,CFX_XMLNode * pINode)50 void CFX_XMLDoc::SaveXMLNode(
51     const RetainPtr<CFX_SeekableStreamProxy>& pXMLStream,
52     CFX_XMLNode* pINode) {
53   CFX_XMLNode* pNode = (CFX_XMLNode*)pINode;
54   switch (pNode->GetType()) {
55     case FX_XMLNODE_Instruction: {
56       CFX_XMLInstruction* pInstruction = (CFX_XMLInstruction*)pNode;
57       if (pInstruction->GetName().CompareNoCase(L"xml") == 0) {
58         WideString ws = L"<?xml version=\"1.0\" encoding=\"";
59         uint16_t wCodePage = pXMLStream->GetCodePage();
60         if (wCodePage == FX_CODEPAGE_UTF16LE) {
61           ws += L"UTF-16";
62         } else if (wCodePage == FX_CODEPAGE_UTF16BE) {
63           ws += L"UTF-16be";
64         } else {
65           ws += L"UTF-8";
66         }
67         ws += L"\"?>";
68         pXMLStream->WriteString(ws.AsStringView());
69       } else {
70         WideString ws =
71             WideString::Format(L"<?%ls", pInstruction->GetName().c_str());
72         pXMLStream->WriteString(ws.AsStringView());
73 
74         for (auto it : pInstruction->GetAttributes()) {
75           WideString wsValue = it.second;
76           wsValue.Replace(L"&", L"&amp;");
77           wsValue.Replace(L"<", L"&lt;");
78           wsValue.Replace(L">", L"&gt;");
79           wsValue.Replace(L"\'", L"&apos;");
80           wsValue.Replace(L"\"", L"&quot;");
81 
82           ws = L" ";
83           ws += it.first;
84           ws += L"=\"";
85           ws += wsValue;
86           ws += L"\"";
87           pXMLStream->WriteString(ws.AsStringView());
88         }
89 
90         for (auto target : pInstruction->GetTargetData()) {
91           ws = L" \"";
92           ws += target;
93           ws += L"\"";
94           pXMLStream->WriteString(ws.AsStringView());
95         }
96         ws = L"?>";
97         pXMLStream->WriteString(ws.AsStringView());
98       }
99       break;
100     }
101     case FX_XMLNODE_Element: {
102       WideString ws;
103       ws = L"<";
104       ws += static_cast<CFX_XMLElement*>(pNode)->GetName();
105       pXMLStream->WriteString(ws.AsStringView());
106 
107       for (auto it : static_cast<CFX_XMLElement*>(pNode)->GetAttributes()) {
108         WideString wsValue = it.second;
109         wsValue.Replace(L"&", L"&amp;");
110         wsValue.Replace(L"<", L"&lt;");
111         wsValue.Replace(L">", L"&gt;");
112         wsValue.Replace(L"\'", L"&apos;");
113         wsValue.Replace(L"\"", L"&quot;");
114 
115         ws = L" ";
116         ws += it.first;
117         ws += L"=\"";
118         ws += wsValue;
119         ws += L"\"";
120         pXMLStream->WriteString(ws.AsStringView());
121       }
122       if (pNode->m_pChild) {
123         ws = L"\n>";
124         pXMLStream->WriteString(ws.AsStringView());
125         CFX_XMLNode* pChild = pNode->m_pChild;
126         while (pChild) {
127           SaveXMLNode(pXMLStream, static_cast<CFX_XMLNode*>(pChild));
128           pChild = pChild->m_pNext;
129         }
130         ws = L"</";
131         ws += static_cast<CFX_XMLElement*>(pNode)->GetName();
132         ws += L"\n>";
133       } else {
134         ws = L"\n/>";
135       }
136       pXMLStream->WriteString(ws.AsStringView());
137       break;
138     }
139     case FX_XMLNODE_Text: {
140       WideString ws = static_cast<CFX_XMLText*>(pNode)->GetText();
141       ws.Replace(L"&", L"&amp;");
142       ws.Replace(L"<", L"&lt;");
143       ws.Replace(L">", L"&gt;");
144       ws.Replace(L"\'", L"&apos;");
145       ws.Replace(L"\"", L"&quot;");
146       pXMLStream->WriteString(ws.AsStringView());
147       break;
148     }
149     case FX_XMLNODE_CharData: {
150       WideString ws = L"<![CDATA[";
151       ws += static_cast<CFX_XMLCharData*>(pNode)->GetText();
152       ws += L"]]>";
153       pXMLStream->WriteString(ws.AsStringView());
154       break;
155     }
156     case FX_XMLNODE_Unknown:
157     default:
158       break;
159   }
160 }
161