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"&");
77 wsValue.Replace(L"<", L"<");
78 wsValue.Replace(L">", L">");
79 wsValue.Replace(L"\'", L"'");
80 wsValue.Replace(L"\"", L""");
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"&");
110 wsValue.Replace(L"<", L"<");
111 wsValue.Replace(L">", L">");
112 wsValue.Replace(L"\'", L"'");
113 wsValue.Replace(L"\"", L""");
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"&");
142 ws.Replace(L"<", L"<");
143 ws.Replace(L">", L">");
144 ws.Replace(L"\'", L"'");
145 ws.Replace(L"\"", L""");
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