Home | History | Annotate | Download | only in xml
      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"&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