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 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 26 CFX_XMLDoc::~CFX_XMLDoc() {} 27 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 39 int32_t CFX_XMLDoc::DoLoad() { 40 if (m_iStatus < 100) 41 m_iStatus = m_pXMLParser->DoParser(); 42 43 return m_iStatus; 44 } 45 46 void CFX_XMLDoc::CloseXML() { 47 m_pXMLParser.reset(); 48 } 49 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