| // Copyright 2016 PDFium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| #include "xfa/fxfa/parser/cxfa_simple_parser.h" | |
| #include <utility> | |
| #include <vector> | |
| #include "core/fxcrt/cfx_checksumcontext.h" | |
| #include "core/fxcrt/cfx_seekablestreamproxy.h" | |
| #include "core/fxcrt/cfx_widetextbuf.h" | |
| #include "core/fxcrt/fx_codepage.h" | |
| #include "core/fxcrt/fx_extension.h" | |
| #include "core/fxcrt/xml/cfx_xmlchardata.h" | |
| #include "core/fxcrt/xml/cfx_xmldoc.h" | |
| #include "core/fxcrt/xml/cfx_xmlelement.h" | |
| #include "core/fxcrt/xml/cfx_xmlinstruction.h" | |
| #include "core/fxcrt/xml/cfx_xmlnode.h" | |
| #include "core/fxcrt/xml/cfx_xmlparser.h" | |
| #include "core/fxcrt/xml/cfx_xmltext.h" | |
| #include "third_party/base/logging.h" | |
| #include "third_party/base/ptr_util.h" | |
| #include "xfa/fxfa/fxfa.h" | |
| #include "xfa/fxfa/parser/cxfa_document.h" | |
| #include "xfa/fxfa/parser/cxfa_node.h" | |
| #include "xfa/fxfa/parser/xfa_basic_data.h" | |
| #include "xfa/fxfa/parser/xfa_utils.h" | |
| namespace { | |
| struct PacketInfo { | |
| uint32_t hash; | |
| const wchar_t* name; | |
| XFA_PacketType packet_type; | |
| const wchar_t* uri; | |
| uint32_t flags; | |
| }; | |
| const PacketInfo PacketData[] = { | |
| {0x0, nullptr, XFA_PacketType::User, nullptr, | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, | |
| {0x811929d, L"sourceSet", XFA_PacketType::SourceSet, | |
| L"http://www.xfa.org/schema/xfa-source-set/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0xb843dba, L"pdf", XFA_PacketType::Pdf, L"http://ns.adobe.com/xdp/pdf/", | |
| XFA_XDPPACKET_FLAGS_COMPLETEMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0xc56afbf, L"xdc", XFA_PacketType::Xdc, L"http://www.xfa.org/schema/xdc/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0xc56afcc, L"xdp", XFA_PacketType::Xdp, L"http://ns.adobe.com/xdp/", | |
| XFA_XDPPACKET_FLAGS_COMPLETEMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0x132a8fbc, L"xmpmeta", XFA_PacketType::Xmpmeta, | |
| L"http://ns.adobe.com/xmpmeta/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, | |
| {0x48d004a8, L"xfdf", XFA_PacketType::Xfdf, L"http://ns.adobe.com/xfdf/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0x4e1e39b6, L"config", XFA_PacketType::Config, | |
| L"http://www.xfa.org/schema/xci/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0x5473b6dc, L"localeSet", XFA_PacketType::LocaleSet, | |
| L"http://www.xfa.org/schema/xfa-locale-set/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0x6038580a, L"stylesheet", XFA_PacketType::Stylesheet, | |
| L"http://www.w3.org/1999/XSL/Transform", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, | |
| {0x803550fc, L"template", XFA_PacketType::Template, | |
| L"http://www.xfa.org/schema/xfa-template/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0x8b036f32, L"signature", XFA_PacketType::Signature, | |
| L"http://www.w3.org/2000/09/xmldsig#", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0x99b95079, L"datasets", XFA_PacketType::Datasets, | |
| L"http://www.xfa.org/schema/xfa-data/", | |
| XFA_XDPPACKET_FLAGS_PREFIXMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0xcd309ff4, L"form", XFA_PacketType::Form, | |
| L"http://www.xfa.org/schema/xfa-form/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| {0xe14c801c, L"connectionSet", XFA_PacketType::ConnectionSet, | |
| L"http://www.xfa.org/schema/xfa-connection-set/", | |
| XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, | |
| }; | |
| const PacketInfo* GetPacketByIndex(XFA_PacketType ePacket) { | |
| return PacketData + static_cast<uint8_t>(ePacket); | |
| } | |
| const PacketInfo* GetPacketByName(const WideStringView& wsName) { | |
| if (wsName.IsEmpty()) | |
| return nullptr; | |
| uint32_t hash = FX_HashCode_GetW(wsName, false); | |
| auto* elem = std::lower_bound( | |
| std::begin(PacketData), std::end(PacketData), hash, | |
| [](const PacketInfo& a, uint32_t hash) { return a.hash < hash; }); | |
| if (elem != std::end(PacketData) && elem->hash == hash) | |
| return elem; | |
| return nullptr; | |
| } | |
| CFX_XMLNode* GetDocumentNode(CFX_XMLDoc* pXMLDoc, | |
| bool bVerifyWellFormness = false) { | |
| if (!pXMLDoc) | |
| return nullptr; | |
| for (CFX_XMLNode* pXMLNode = | |
| pXMLDoc->GetRoot()->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| if (pXMLNode->GetType() != FX_XMLNODE_Element) | |
| continue; | |
| if (!bVerifyWellFormness) | |
| return pXMLNode; | |
| for (CFX_XMLNode* pNextNode = | |
| pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling); | |
| pNextNode; | |
| pNextNode = pNextNode->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| if (pNextNode->GetType() == FX_XMLNODE_Element) | |
| return nullptr; | |
| } | |
| return pXMLNode; | |
| } | |
| return nullptr; | |
| } | |
| WideString GetElementTagNamespaceURI(CFX_XMLElement* pElement) { | |
| WideString wsNodeStr = pElement->GetNamespacePrefix(); | |
| WideString wsNamespaceURI; | |
| if (!XFA_FDEExtension_ResolveNamespaceQualifier(pElement, wsNodeStr, | |
| &wsNamespaceURI)) { | |
| return WideString(); | |
| } | |
| return wsNamespaceURI; | |
| } | |
| bool MatchNodeName(CFX_XMLNode* pNode, | |
| const WideStringView& wsLocalTagName, | |
| const WideStringView& wsNamespaceURIPrefix, | |
| uint32_t eMatchFlags = XFA_XDPPACKET_FLAGS_NOMATCH) { | |
| if (!pNode || pNode->GetType() != FX_XMLNODE_Element) | |
| return false; | |
| CFX_XMLElement* pElement = reinterpret_cast<CFX_XMLElement*>(pNode); | |
| WideString wsNodeStr = pElement->GetLocalTagName(); | |
| if (wsNodeStr != wsLocalTagName) | |
| return false; | |
| wsNodeStr = GetElementTagNamespaceURI(pElement); | |
| if (eMatchFlags & XFA_XDPPACKET_FLAGS_NOMATCH) | |
| return true; | |
| if (eMatchFlags & XFA_XDPPACKET_FLAGS_PREFIXMATCH) { | |
| return wsNodeStr.Left(wsNamespaceURIPrefix.GetLength()) == | |
| wsNamespaceURIPrefix; | |
| } | |
| return wsNodeStr == wsNamespaceURIPrefix; | |
| } | |
| bool GetAttributeLocalName(const WideStringView& wsAttributeName, | |
| WideString& wsLocalAttrName) { | |
| WideString wsAttrName(wsAttributeName); | |
| auto pos = wsAttrName.Find(L':', 0); | |
| if (!pos.has_value()) { | |
| wsLocalAttrName = wsAttrName; | |
| return false; | |
| } | |
| wsLocalAttrName = wsAttrName.Right(wsAttrName.GetLength() - pos.value() - 1); | |
| return true; | |
| } | |
| bool ResolveAttribute(CFX_XMLElement* pElement, | |
| const WideString& wsAttrName, | |
| WideString& wsLocalAttrName, | |
| WideString& wsNamespaceURI) { | |
| WideString wsNSPrefix; | |
| if (GetAttributeLocalName(wsAttrName.AsStringView(), wsLocalAttrName)) { | |
| wsNSPrefix = wsAttrName.Left(wsAttrName.GetLength() - | |
| wsLocalAttrName.GetLength() - 1); | |
| } | |
| if (wsLocalAttrName == L"xmlns" || wsNSPrefix == L"xmlns" || | |
| wsNSPrefix == L"xml") { | |
| return false; | |
| } | |
| if (!XFA_FDEExtension_ResolveNamespaceQualifier(pElement, wsNSPrefix, | |
| &wsNamespaceURI)) { | |
| wsNamespaceURI.clear(); | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool FindAttributeWithNS(CFX_XMLElement* pElement, | |
| const WideStringView& wsLocalAttributeName, | |
| const WideStringView& wsNamespaceURIPrefix, | |
| WideString& wsValue, | |
| bool bMatchNSAsPrefix = false) { | |
| if (!pElement) | |
| return false; | |
| WideString wsAttrNS; | |
| for (auto it : pElement->GetAttributes()) { | |
| auto pos = it.first.Find(L':', 0); | |
| WideString wsNSPrefix; | |
| if (!pos.has_value()) { | |
| if (wsLocalAttributeName != it.first) | |
| continue; | |
| } else { | |
| if (wsLocalAttributeName != | |
| it.first.Right(it.first.GetLength() - pos.value() - 1)) { | |
| continue; | |
| } | |
| wsNSPrefix = it.first.Left(pos.value()); | |
| } | |
| if (!XFA_FDEExtension_ResolveNamespaceQualifier(pElement, wsNSPrefix, | |
| &wsAttrNS)) { | |
| continue; | |
| } | |
| if (bMatchNSAsPrefix) { | |
| if (wsAttrNS.Left(wsNamespaceURIPrefix.GetLength()) != | |
| wsNamespaceURIPrefix) { | |
| continue; | |
| } | |
| } else { | |
| if (wsAttrNS != wsNamespaceURIPrefix) | |
| continue; | |
| } | |
| wsValue = it.second; | |
| return true; | |
| } | |
| return false; | |
| } | |
| CFX_XMLNode* GetDataSetsFromXDP(CFX_XMLNode* pXMLDocumentNode) { | |
| const PacketInfo* datasets_packet = | |
| GetPacketByIndex(XFA_PacketType::Datasets); | |
| if (MatchNodeName(pXMLDocumentNode, datasets_packet->name, | |
| datasets_packet->uri, datasets_packet->flags)) { | |
| return pXMLDocumentNode; | |
| } | |
| const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Xdp); | |
| if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, | |
| packet->flags)) { | |
| return nullptr; | |
| } | |
| for (CFX_XMLNode* pDatasetsNode = | |
| pXMLDocumentNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pDatasetsNode; | |
| pDatasetsNode = pDatasetsNode->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| if (MatchNodeName(pDatasetsNode, datasets_packet->name, | |
| datasets_packet->uri, datasets_packet->flags)) { | |
| return pDatasetsNode; | |
| } | |
| } | |
| return nullptr; | |
| } | |
| bool IsStringAllWhitespace(WideString wsText) { | |
| wsText.TrimRight(L"\x20\x9\xD\xA"); | |
| return wsText.IsEmpty(); | |
| } | |
| void ConvertXMLToPlainText(CFX_XMLElement* pRootXMLNode, WideString& wsOutput) { | |
| for (CFX_XMLNode* pXMLChild = | |
| pRootXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pXMLChild; | |
| pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| switch (pXMLChild->GetType()) { | |
| case FX_XMLNODE_Element: { | |
| WideString wsTextData = | |
| static_cast<CFX_XMLElement*>(pXMLChild)->GetTextData(); | |
| wsTextData += L"\n"; | |
| wsOutput += wsTextData; | |
| break; | |
| } | |
| case FX_XMLNODE_Text: | |
| case FX_XMLNODE_CharData: { | |
| WideString wsText = static_cast<CFX_XMLText*>(pXMLChild)->GetText(); | |
| if (IsStringAllWhitespace(wsText)) | |
| continue; | |
| wsOutput = wsText; | |
| break; | |
| } | |
| default: | |
| NOTREACHED(); | |
| break; | |
| } | |
| } | |
| } | |
| WideString GetPlainTextFromRichText(CFX_XMLNode* pXMLNode) { | |
| if (!pXMLNode) | |
| return L""; | |
| WideString wsPlainText; | |
| switch (pXMLNode->GetType()) { | |
| case FX_XMLNODE_Element: { | |
| CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode); | |
| WideString wsTag = pXMLElement->GetLocalTagName(); | |
| uint32_t uTag = FX_HashCode_GetW(wsTag.AsStringView(), true); | |
| if (uTag == 0x0001f714) { | |
| wsPlainText += L"\n"; | |
| } else if (uTag == 0x00000070) { | |
| if (!wsPlainText.IsEmpty()) { | |
| wsPlainText += L"\n"; | |
| } | |
| } else if (uTag == 0xa48ac63) { | |
| if (!wsPlainText.IsEmpty() && | |
| wsPlainText[wsPlainText.GetLength() - 1] != '\n') { | |
| wsPlainText += L"\n"; | |
| } | |
| } | |
| break; | |
| } | |
| case FX_XMLNODE_Text: | |
| case FX_XMLNODE_CharData: { | |
| WideString wsContent = static_cast<CFX_XMLText*>(pXMLNode)->GetText(); | |
| wsPlainText += wsContent; | |
| break; | |
| } | |
| default: | |
| break; | |
| } | |
| for (CFX_XMLNode* pChildXML = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pChildXML; | |
| pChildXML = pChildXML->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| wsPlainText += GetPlainTextFromRichText(pChildXML); | |
| } | |
| return wsPlainText; | |
| } | |
| } // namespace | |
| bool XFA_RecognizeRichText(CFX_XMLElement* pRichTextXMLNode) { | |
| return pRichTextXMLNode && GetElementTagNamespaceURI(pRichTextXMLNode) == | |
| L"http://www.w3.org/1999/xhtml"; | |
| } | |
| CXFA_SimpleParser::CXFA_SimpleParser() : m_bDocumentParser(true) {} | |
| CXFA_SimpleParser::CXFA_SimpleParser(CXFA_Document* pFactory) | |
| : m_pFactory(pFactory), m_bDocumentParser(false) {} | |
| CXFA_SimpleParser::~CXFA_SimpleParser() {} | |
| void CXFA_SimpleParser::SetFactory(CXFA_Document* pFactory) { | |
| ASSERT(m_bDocumentParser); | |
| m_pFactory = pFactory; | |
| } | |
| int32_t CXFA_SimpleParser::StartParse( | |
| const RetainPtr<IFX_SeekableStream>& pStream, | |
| XFA_PacketType ePacketID) { | |
| CloseParser(); | |
| m_pFileRead = pStream; | |
| m_pStream = pdfium::MakeRetain<CFX_SeekableStreamProxy>(pStream, false); | |
| uint16_t wCodePage = m_pStream->GetCodePage(); | |
| if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE && | |
| wCodePage != FX_CODEPAGE_UTF8) { | |
| m_pStream->SetCodePage(FX_CODEPAGE_UTF8); | |
| } | |
| m_pXMLDoc = pdfium::MakeUnique<CFX_XMLDoc>(); | |
| auto pNewParser = | |
| pdfium::MakeUnique<CFX_XMLParser>(m_pXMLDoc->GetRoot(), m_pStream); | |
| m_pXMLParser = pNewParser.get(); | |
| if (!m_pXMLDoc->LoadXML(std::move(pNewParser))) | |
| return XFA_PARSESTATUS_StatusErr; | |
| m_bParseStarted = true; | |
| m_ePacketID = ePacketID; | |
| return XFA_PARSESTATUS_Ready; | |
| } | |
| int32_t CXFA_SimpleParser::DoParse() { | |
| if (!m_pXMLDoc || !m_bParseStarted) | |
| return XFA_PARSESTATUS_StatusErr; | |
| int32_t iRet = m_pXMLDoc->DoLoad(); | |
| if (iRet < 0) | |
| return XFA_PARSESTATUS_SyntaxErr; | |
| if (iRet < 100) | |
| return iRet / 2; | |
| m_pRootNode = ParseAsXDPPacket(GetDocumentNode(m_pXMLDoc.get()), m_ePacketID); | |
| m_pXMLParser.Release(); | |
| m_pXMLDoc->CloseXML(); | |
| m_pStream.Reset(); | |
| if (!m_pRootNode) | |
| return XFA_PARSESTATUS_StatusErr; | |
| return XFA_PARSESTATUS_Done; | |
| } | |
| CFX_XMLNode* CXFA_SimpleParser::ParseXMLData(const ByteString& wsXML) { | |
| CloseParser(); | |
| m_pXMLDoc = pdfium::MakeUnique<CFX_XMLDoc>(); | |
| auto pStream = pdfium::MakeRetain<CFX_SeekableStreamProxy>( | |
| const_cast<uint8_t*>(wsXML.raw_str()), wsXML.GetLength()); | |
| auto pParser = | |
| pdfium::MakeUnique<CFX_XMLParser>(m_pXMLDoc->GetRoot(), pStream); | |
| pParser->m_dwCheckStatus = 0x03; | |
| if (!m_pXMLDoc->LoadXML(std::move(pParser))) | |
| return nullptr; | |
| int32_t iRet = m_pXMLDoc->DoLoad(); | |
| if (iRet < 0 || iRet >= 100) | |
| m_pXMLDoc->CloseXML(); | |
| return iRet < 100 ? nullptr : GetDocumentNode(m_pXMLDoc.get()); | |
| } | |
| void CXFA_SimpleParser::ConstructXFANode(CXFA_Node* pXFANode, | |
| CFX_XMLNode* pXMLNode) { | |
| XFA_PacketType ePacketID = pXFANode->GetPacketType(); | |
| if (ePacketID == XFA_PacketType::Datasets) { | |
| if (pXFANode->GetElementType() == XFA_Element::DataValue) { | |
| for (CFX_XMLNode* pXMLChild = | |
| pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pXMLChild; | |
| pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| FX_XMLNODETYPE eNodeType = pXMLChild->GetType(); | |
| if (eNodeType == FX_XMLNODE_Instruction) | |
| continue; | |
| if (eNodeType == FX_XMLNODE_Element) { | |
| CXFA_Node* pXFAChild = m_pFactory->CreateNode( | |
| XFA_PacketType::Datasets, XFA_Element::DataValue); | |
| if (!pXFAChild) | |
| return; | |
| CFX_XMLElement* child = static_cast<CFX_XMLElement*>(pXMLChild); | |
| WideString wsNodeStr = child->GetLocalTagName(); | |
| pXFAChild->JSNode()->SetCData(XFA_Attribute::Name, wsNodeStr, false, | |
| false); | |
| WideString wsChildValue = GetPlainTextFromRichText(child); | |
| if (!wsChildValue.IsEmpty()) | |
| pXFAChild->JSNode()->SetCData(XFA_Attribute::Value, wsChildValue, | |
| false, false); | |
| pXFANode->InsertChild(pXFAChild, nullptr); | |
| pXFAChild->SetXMLMappingNode(pXMLChild); | |
| pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); | |
| break; | |
| } | |
| } | |
| m_pRootNode = pXFANode; | |
| } else { | |
| m_pRootNode = DataLoader(pXFANode, pXMLNode, true); | |
| } | |
| } else if (pXFANode->IsContentNode()) { | |
| ParseContentNode(pXFANode, pXMLNode, ePacketID); | |
| m_pRootNode = pXFANode; | |
| } else { | |
| m_pRootNode = NormalLoader(pXFANode, pXMLNode, ePacketID, true); | |
| } | |
| } | |
| CXFA_Node* CXFA_SimpleParser::GetRootNode() const { | |
| return m_pRootNode; | |
| } | |
| CFX_XMLDoc* CXFA_SimpleParser::GetXMLDoc() const { | |
| return m_pXMLDoc.get(); | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket(CFX_XMLNode* pXMLDocumentNode, | |
| XFA_PacketType ePacketID) { | |
| switch (ePacketID) { | |
| case XFA_PacketType::Xdp: | |
| return ParseAsXDPPacket_XDP(pXMLDocumentNode); | |
| case XFA_PacketType::Config: | |
| return ParseAsXDPPacket_Config(pXMLDocumentNode); | |
| case XFA_PacketType::Template: | |
| return ParseAsXDPPacket_Template(pXMLDocumentNode); | |
| case XFA_PacketType::Form: | |
| return ParseAsXDPPacket_Form(pXMLDocumentNode); | |
| case XFA_PacketType::Datasets: | |
| return ParseAsXDPPacket_Data(pXMLDocumentNode); | |
| case XFA_PacketType::Xdc: | |
| return ParseAsXDPPacket_Xdc(pXMLDocumentNode); | |
| case XFA_PacketType::LocaleSet: | |
| return ParseAsXDPPacket_LocaleConnectionSourceSet( | |
| pXMLDocumentNode, XFA_PacketType::LocaleSet, XFA_Element::LocaleSet); | |
| case XFA_PacketType::ConnectionSet: | |
| return ParseAsXDPPacket_LocaleConnectionSourceSet( | |
| pXMLDocumentNode, XFA_PacketType::ConnectionSet, | |
| XFA_Element::ConnectionSet); | |
| case XFA_PacketType::SourceSet: | |
| return ParseAsXDPPacket_LocaleConnectionSourceSet( | |
| pXMLDocumentNode, XFA_PacketType::SourceSet, XFA_Element::SourceSet); | |
| default: | |
| return ParseAsXDPPacket_User(pXMLDocumentNode); | |
| } | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_XDP( | |
| CFX_XMLNode* pXMLDocumentNode) { | |
| const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Xdp); | |
| if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, | |
| packet->flags)) { | |
| return nullptr; | |
| } | |
| CXFA_Node* pXFARootNode = | |
| m_pFactory->CreateNode(XFA_PacketType::Xdp, XFA_Element::Xfa); | |
| if (!pXFARootNode) | |
| return nullptr; | |
| m_pRootNode = pXFARootNode; | |
| pXFARootNode->JSNode()->SetCData(XFA_Attribute::Name, L"xfa", false, false); | |
| CFX_XMLElement* pElement = static_cast<CFX_XMLElement*>(pXMLDocumentNode); | |
| for (auto it : pElement->GetAttributes()) { | |
| if (it.first == L"uuid") | |
| pXFARootNode->JSNode()->SetCData(XFA_Attribute::Uuid, it.second, false, | |
| false); | |
| else if (it.first == L"timeStamp") | |
| pXFARootNode->JSNode()->SetCData(XFA_Attribute::TimeStamp, it.second, | |
| false, false); | |
| } | |
| CFX_XMLNode* pXMLConfigDOMRoot = nullptr; | |
| CXFA_Node* pXFAConfigDOMRoot = nullptr; | |
| for (CFX_XMLNode* pChildItem = | |
| pXMLDocumentNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pChildItem; | |
| pChildItem = pChildItem->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| const PacketInfo* pPacketInfo = GetPacketByIndex(XFA_PacketType::Config); | |
| if (!MatchNodeName(pChildItem, pPacketInfo->name, pPacketInfo->uri, | |
| pPacketInfo->flags)) { | |
| continue; | |
| } | |
| if (pXFARootNode->GetFirstChildByName(pPacketInfo->hash)) | |
| return nullptr; | |
| pXMLConfigDOMRoot = pChildItem; | |
| pXFAConfigDOMRoot = ParseAsXDPPacket_Config(pXMLConfigDOMRoot); | |
| if (pXFAConfigDOMRoot) | |
| pXFARootNode->InsertChild(pXFAConfigDOMRoot, nullptr); | |
| } | |
| CFX_XMLNode* pXMLDatasetsDOMRoot = nullptr; | |
| CFX_XMLNode* pXMLFormDOMRoot = nullptr; | |
| CFX_XMLNode* pXMLTemplateDOMRoot = nullptr; | |
| for (CFX_XMLNode* pChildItem = | |
| pXMLDocumentNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pChildItem; | |
| pChildItem = pChildItem->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| if (!pChildItem || pChildItem->GetType() != FX_XMLNODE_Element) | |
| continue; | |
| if (pChildItem == pXMLConfigDOMRoot) | |
| continue; | |
| CFX_XMLElement* pElement = reinterpret_cast<CFX_XMLElement*>(pChildItem); | |
| WideString wsPacketName = pElement->GetLocalTagName(); | |
| const PacketInfo* pPacketInfo = | |
| GetPacketByName(wsPacketName.AsStringView()); | |
| if (pPacketInfo && pPacketInfo->uri) { | |
| if (!MatchNodeName(pElement, pPacketInfo->name, pPacketInfo->uri, | |
| pPacketInfo->flags)) { | |
| pPacketInfo = nullptr; | |
| } | |
| } | |
| XFA_PacketType ePacket = | |
| pPacketInfo ? pPacketInfo->packet_type : XFA_PacketType::User; | |
| if (ePacket == XFA_PacketType::Xdp) | |
| continue; | |
| if (ePacket == XFA_PacketType::Datasets) { | |
| if (pXMLDatasetsDOMRoot) | |
| return nullptr; | |
| pXMLDatasetsDOMRoot = pElement; | |
| } else if (ePacket == XFA_PacketType::Form) { | |
| if (pXMLFormDOMRoot) | |
| return nullptr; | |
| pXMLFormDOMRoot = pElement; | |
| } else if (ePacket == XFA_PacketType::Template) { | |
| // Found a duplicate template packet. | |
| if (pXMLTemplateDOMRoot) | |
| return nullptr; | |
| CXFA_Node* pPacketNode = ParseAsXDPPacket(pElement, ePacket); | |
| if (pPacketNode) { | |
| pXMLTemplateDOMRoot = pElement; | |
| pXFARootNode->InsertChild(pPacketNode, nullptr); | |
| } | |
| } else { | |
| CXFA_Node* pPacketNode = ParseAsXDPPacket(pElement, ePacket); | |
| if (pPacketNode) { | |
| if (pPacketInfo && | |
| (pPacketInfo->flags & XFA_XDPPACKET_FLAGS_SUPPORTONE) && | |
| pXFARootNode->GetFirstChildByName(pPacketInfo->hash)) { | |
| return nullptr; | |
| } | |
| pXFARootNode->InsertChild(pPacketNode, nullptr); | |
| } | |
| } | |
| } | |
| // No template is found. | |
| if (!pXMLTemplateDOMRoot) | |
| return nullptr; | |
| if (pXMLDatasetsDOMRoot) { | |
| CXFA_Node* pPacketNode = | |
| ParseAsXDPPacket(pXMLDatasetsDOMRoot, XFA_PacketType::Datasets); | |
| if (pPacketNode) | |
| pXFARootNode->InsertChild(pPacketNode, nullptr); | |
| } | |
| if (pXMLFormDOMRoot) { | |
| CXFA_Node* pPacketNode = | |
| ParseAsXDPPacket(pXMLFormDOMRoot, XFA_PacketType::Form); | |
| if (pPacketNode) | |
| pXFARootNode->InsertChild(pPacketNode, nullptr); | |
| } | |
| pXFARootNode->SetXMLMappingNode(pXMLDocumentNode); | |
| return pXFARootNode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Config( | |
| CFX_XMLNode* pXMLDocumentNode) { | |
| const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Config); | |
| if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, | |
| packet->flags)) { | |
| return nullptr; | |
| } | |
| CXFA_Node* pNode = | |
| m_pFactory->CreateNode(XFA_PacketType::Config, XFA_Element::Config); | |
| if (!pNode) | |
| return nullptr; | |
| pNode->JSNode()->SetCData(XFA_Attribute::Name, packet->name, false, false); | |
| if (!NormalLoader(pNode, pXMLDocumentNode, XFA_PacketType::Config, true)) | |
| return nullptr; | |
| pNode->SetXMLMappingNode(pXMLDocumentNode); | |
| return pNode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Template( | |
| CFX_XMLNode* pXMLDocumentNode) { | |
| const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Template); | |
| if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, | |
| packet->flags)) { | |
| return nullptr; | |
| } | |
| CXFA_Node* pNode = | |
| m_pFactory->CreateNode(XFA_PacketType::Template, XFA_Element::Template); | |
| if (!pNode) | |
| return nullptr; | |
| pNode->JSNode()->SetCData(XFA_Attribute::Name, packet->name, false, false); | |
| if (m_bDocumentParser) { | |
| CFX_XMLElement* pXMLDocumentElement = | |
| static_cast<CFX_XMLElement*>(pXMLDocumentNode); | |
| WideString wsNamespaceURI = pXMLDocumentElement->GetNamespaceURI(); | |
| if (wsNamespaceURI.IsEmpty()) | |
| wsNamespaceURI = pXMLDocumentElement->GetString(L"xmlns:xfa"); | |
| pNode->GetDocument()->RecognizeXFAVersionNumber(wsNamespaceURI); | |
| } | |
| if (!NormalLoader(pNode, pXMLDocumentNode, XFA_PacketType::Template, true)) | |
| return nullptr; | |
| pNode->SetXMLMappingNode(pXMLDocumentNode); | |
| return pNode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Form( | |
| CFX_XMLNode* pXMLDocumentNode) { | |
| const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Form); | |
| if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, | |
| packet->flags)) { | |
| return nullptr; | |
| } | |
| CFX_XMLElement* pXMLDocumentElement = | |
| static_cast<CFX_XMLElement*>(pXMLDocumentNode); | |
| WideString wsChecksum = pXMLDocumentElement->GetString(L"checksum"); | |
| if (wsChecksum.GetLength() != 28 || m_pXMLParser->m_dwCheckStatus != 0x03) { | |
| return nullptr; | |
| } | |
| auto pChecksum = pdfium::MakeUnique<CFX_ChecksumContext>(); | |
| pChecksum->StartChecksum(); | |
| pChecksum->UpdateChecksum(m_pFileRead, m_pXMLParser->m_nStart[0], | |
| m_pXMLParser->m_nSize[0]); | |
| pChecksum->UpdateChecksum(m_pFileRead, m_pXMLParser->m_nStart[1], | |
| m_pXMLParser->m_nSize[1]); | |
| pChecksum->FinishChecksum(); | |
| ByteString bsCheck = pChecksum->GetChecksum(); | |
| if (bsCheck != wsChecksum.UTF8Encode()) | |
| return nullptr; | |
| CXFA_Node* pNode = | |
| m_pFactory->CreateNode(XFA_PacketType::Form, XFA_Element::Form); | |
| if (!pNode) | |
| return nullptr; | |
| pNode->JSNode()->SetCData(XFA_Attribute::Name, packet->name, false, false); | |
| pNode->JSNode()->SetAttribute(XFA_Attribute::Checksum, | |
| wsChecksum.AsStringView(), false); | |
| CXFA_Node* pTemplateRoot = | |
| m_pRootNode->GetFirstChildByClass(XFA_Element::Template); | |
| CXFA_Node* pTemplateChosen = | |
| pTemplateRoot ? pTemplateRoot->GetFirstChildByClass(XFA_Element::Subform) | |
| : nullptr; | |
| bool bUseAttribute = true; | |
| if (pTemplateChosen && | |
| pTemplateChosen->JSNode()->GetEnum(XFA_Attribute::RestoreState) != | |
| XFA_AttributeEnum::Auto) { | |
| bUseAttribute = false; | |
| } | |
| if (!NormalLoader(pNode, pXMLDocumentNode, XFA_PacketType::Form, | |
| bUseAttribute)) | |
| return nullptr; | |
| pNode->SetXMLMappingNode(pXMLDocumentNode); | |
| return pNode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Data( | |
| CFX_XMLNode* pXMLDocumentNode) { | |
| CFX_XMLNode* pDatasetsXMLNode = GetDataSetsFromXDP(pXMLDocumentNode); | |
| const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Datasets); | |
| if (pDatasetsXMLNode) { | |
| CXFA_Node* pNode = m_pFactory->CreateNode(XFA_PacketType::Datasets, | |
| XFA_Element::DataModel); | |
| if (!pNode) | |
| return nullptr; | |
| pNode->JSNode()->SetCData(XFA_Attribute::Name, packet->name, false, false); | |
| if (!DataLoader(pNode, pDatasetsXMLNode, false)) | |
| return nullptr; | |
| pNode->SetXMLMappingNode(pDatasetsXMLNode); | |
| return pNode; | |
| } | |
| CFX_XMLNode* pDataXMLNode = nullptr; | |
| if (MatchNodeName(pXMLDocumentNode, L"data", packet->uri, packet->flags)) { | |
| static_cast<CFX_XMLElement*>(pXMLDocumentNode) | |
| ->RemoveAttribute(L"xmlns:xfa"); | |
| pDataXMLNode = pXMLDocumentNode; | |
| } else { | |
| CFX_XMLElement* pDataElement = new CFX_XMLElement(L"xfa:data"); | |
| CFX_XMLNode* pParentXMLNode = | |
| pXMLDocumentNode->GetNodeItem(CFX_XMLNode::Parent); | |
| if (pParentXMLNode) | |
| pParentXMLNode->RemoveChildNode(pXMLDocumentNode); | |
| ASSERT(pXMLDocumentNode->GetType() == FX_XMLNODE_Element); | |
| if (pXMLDocumentNode->GetType() == FX_XMLNODE_Element) { | |
| static_cast<CFX_XMLElement*>(pXMLDocumentNode) | |
| ->RemoveAttribute(L"xmlns:xfa"); | |
| } | |
| pDataElement->InsertChildNode(pXMLDocumentNode); | |
| pDataXMLNode = pDataElement; | |
| } | |
| if (pDataXMLNode) { | |
| CXFA_Node* pNode = m_pFactory->CreateNode(XFA_PacketType::Datasets, | |
| XFA_Element::DataGroup); | |
| if (!pNode) { | |
| if (pDataXMLNode != pXMLDocumentNode) | |
| delete pDataXMLNode; | |
| return nullptr; | |
| } | |
| WideString wsLocalName = | |
| static_cast<CFX_XMLElement*>(pDataXMLNode)->GetLocalTagName(); | |
| pNode->JSNode()->SetCData(XFA_Attribute::Name, wsLocalName, false, false); | |
| if (!DataLoader(pNode, pDataXMLNode, true)) | |
| return nullptr; | |
| pNode->SetXMLMappingNode(pDataXMLNode); | |
| if (pDataXMLNode != pXMLDocumentNode) | |
| pNode->SetFlag(XFA_NodeFlag_OwnXMLNode, false); | |
| return pNode; | |
| } | |
| return nullptr; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_LocaleConnectionSourceSet( | |
| CFX_XMLNode* pXMLDocumentNode, | |
| XFA_PacketType packet_type, | |
| XFA_Element element) { | |
| const PacketInfo* packet = GetPacketByIndex(packet_type); | |
| if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, | |
| packet->flags)) { | |
| return nullptr; | |
| } | |
| CXFA_Node* pNode = m_pFactory->CreateNode(packet_type, element); | |
| if (!pNode) | |
| return nullptr; | |
| pNode->JSNode()->SetCData(XFA_Attribute::Name, packet->name, false, false); | |
| if (!NormalLoader(pNode, pXMLDocumentNode, packet_type, true)) | |
| return nullptr; | |
| pNode->SetXMLMappingNode(pXMLDocumentNode); | |
| return pNode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Xdc( | |
| CFX_XMLNode* pXMLDocumentNode) { | |
| const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Xdc); | |
| if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, | |
| packet->flags)) | |
| return nullptr; | |
| CXFA_Node* pNode = | |
| m_pFactory->CreateNode(XFA_PacketType::Xdc, XFA_Element::Xdc); | |
| if (!pNode) | |
| return nullptr; | |
| pNode->JSNode()->SetCData(XFA_Attribute::Name, packet->name, false, false); | |
| pNode->SetXMLMappingNode(pXMLDocumentNode); | |
| return pNode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_User( | |
| CFX_XMLNode* pXMLDocumentNode) { | |
| CXFA_Node* pNode = | |
| m_pFactory->CreateNode(XFA_PacketType::Xdp, XFA_Element::Packet); | |
| if (!pNode) | |
| return nullptr; | |
| WideString wsName = | |
| static_cast<CFX_XMLElement*>(pXMLDocumentNode)->GetLocalTagName(); | |
| pNode->JSNode()->SetCData(XFA_Attribute::Name, wsName, false, false); | |
| if (!UserPacketLoader(pNode, pXMLDocumentNode)) | |
| return nullptr; | |
| pNode->SetXMLMappingNode(pXMLDocumentNode); | |
| return pNode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::UserPacketLoader(CXFA_Node* pXFANode, | |
| CFX_XMLNode* pXMLDoc) { | |
| return pXFANode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::DataLoader(CXFA_Node* pXFANode, | |
| CFX_XMLNode* pXMLDoc, | |
| bool bDoTransform) { | |
| ParseDataGroup(pXFANode, pXMLDoc, XFA_PacketType::Datasets); | |
| return pXFANode; | |
| } | |
| CXFA_Node* CXFA_SimpleParser::NormalLoader(CXFA_Node* pXFANode, | |
| CFX_XMLNode* pXMLDoc, | |
| XFA_PacketType ePacketID, | |
| bool bUseAttribute) { | |
| bool bOneOfPropertyFound = false; | |
| for (CFX_XMLNode* pXMLChild = pXMLDoc->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pXMLChild; | |
| pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| switch (pXMLChild->GetType()) { | |
| case FX_XMLNODE_Element: { | |
| CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLChild); | |
| WideString wsTagName = pXMLElement->GetLocalTagName(); | |
| XFA_Element eType = CXFA_Node::NameToElement(wsTagName); | |
| if (eType == XFA_Element::Unknown) | |
| continue; | |
| if (pXFANode->HasPropertyFlags( | |
| eType, | |
| XFA_PROPERTYFLAG_OneOf | XFA_PROPERTYFLAG_DefaultOneOf)) { | |
| if (bOneOfPropertyFound) | |
| break; | |
| bOneOfPropertyFound = true; | |
| } | |
| CXFA_Node* pXFAChild = m_pFactory->CreateNode(ePacketID, eType); | |
| if (!pXFAChild) | |
| return nullptr; | |
| if (ePacketID == XFA_PacketType::Config) { | |
| pXFAChild->JSNode()->SetAttribute(XFA_Attribute::Name, | |
| wsTagName.AsStringView(), false); | |
| } | |
| bool IsNeedValue = true; | |
| for (auto it : pXMLElement->GetAttributes()) { | |
| WideString wsAttrName; | |
| GetAttributeLocalName(it.first.AsStringView(), wsAttrName); | |
| if (wsAttrName == L"nil" && it.second == L"true") | |
| IsNeedValue = false; | |
| XFA_Attribute attr = | |
| CXFA_Node::NameToAttribute(wsAttrName.AsStringView()); | |
| if (attr == XFA_Attribute::Unknown) | |
| continue; | |
| if (!bUseAttribute && attr != XFA_Attribute::Name && | |
| attr != XFA_Attribute::Save) { | |
| continue; | |
| } | |
| pXFAChild->JSNode()->SetAttribute(attr, it.second.AsStringView(), | |
| false); | |
| } | |
| pXFANode->InsertChild(pXFAChild, nullptr); | |
| if (eType == XFA_Element::Validate || eType == XFA_Element::Locale) { | |
| if (ePacketID == XFA_PacketType::Config) | |
| ParseContentNode(pXFAChild, pXMLElement, ePacketID); | |
| else | |
| NormalLoader(pXFAChild, pXMLElement, ePacketID, bUseAttribute); | |
| break; | |
| } | |
| switch (pXFAChild->GetObjectType()) { | |
| case XFA_ObjectType::ContentNode: | |
| case XFA_ObjectType::TextNode: | |
| case XFA_ObjectType::NodeC: | |
| case XFA_ObjectType::NodeV: | |
| if (IsNeedValue) | |
| ParseContentNode(pXFAChild, pXMLElement, ePacketID); | |
| break; | |
| default: | |
| NormalLoader(pXFAChild, pXMLElement, ePacketID, bUseAttribute); | |
| break; | |
| } | |
| } break; | |
| case FX_XMLNODE_Instruction: | |
| ParseInstruction(pXFANode, static_cast<CFX_XMLInstruction*>(pXMLChild), | |
| ePacketID); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| return pXFANode; | |
| } | |
| void CXFA_SimpleParser::ParseContentNode(CXFA_Node* pXFANode, | |
| CFX_XMLNode* pXMLNode, | |
| XFA_PacketType ePacketID) { | |
| XFA_Element element = XFA_Element::Sharptext; | |
| if (pXFANode->GetElementType() == XFA_Element::ExData) { | |
| WideString wsContentType = | |
| pXFANode->JSNode()->GetCData(XFA_Attribute::ContentType); | |
| if (wsContentType == L"text/html") | |
| element = XFA_Element::SharpxHTML; | |
| else if (wsContentType == L"text/xml") | |
| element = XFA_Element::Sharpxml; | |
| } | |
| if (element == XFA_Element::SharpxHTML) | |
| pXFANode->SetXMLMappingNode(pXMLNode); | |
| WideString wsValue; | |
| for (CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pXMLChild; | |
| pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| FX_XMLNODETYPE eNodeType = pXMLChild->GetType(); | |
| if (eNodeType == FX_XMLNODE_Instruction) | |
| continue; | |
| if (element == XFA_Element::SharpxHTML) { | |
| if (eNodeType != FX_XMLNODE_Element) | |
| break; | |
| if (XFA_RecognizeRichText(static_cast<CFX_XMLElement*>(pXMLChild))) | |
| wsValue += | |
| GetPlainTextFromRichText(static_cast<CFX_XMLElement*>(pXMLChild)); | |
| } else if (element == XFA_Element::Sharpxml) { | |
| if (eNodeType != FX_XMLNODE_Element) | |
| break; | |
| ConvertXMLToPlainText(static_cast<CFX_XMLElement*>(pXMLChild), wsValue); | |
| } else { | |
| if (eNodeType == FX_XMLNODE_Element) | |
| break; | |
| if (eNodeType == FX_XMLNODE_Text || eNodeType == FX_XMLNODE_CharData) | |
| wsValue = static_cast<CFX_XMLText*>(pXMLChild)->GetText(); | |
| } | |
| break; | |
| } | |
| if (!wsValue.IsEmpty()) { | |
| if (pXFANode->IsContentNode()) { | |
| CXFA_Node* pContentRawDataNode = | |
| m_pFactory->CreateNode(ePacketID, element); | |
| ASSERT(pContentRawDataNode); | |
| pContentRawDataNode->JSNode()->SetCData(XFA_Attribute::Value, wsValue, | |
| false, false); | |
| pXFANode->InsertChild(pContentRawDataNode, nullptr); | |
| } else { | |
| pXFANode->JSNode()->SetCData(XFA_Attribute::Value, wsValue, false, false); | |
| } | |
| } | |
| } | |
| void CXFA_SimpleParser::ParseDataGroup(CXFA_Node* pXFANode, | |
| CFX_XMLNode* pXMLNode, | |
| XFA_PacketType ePacketID) { | |
| for (CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pXMLChild; | |
| pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| switch (pXMLChild->GetType()) { | |
| case FX_XMLNODE_Element: { | |
| CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLChild); | |
| { | |
| WideString wsNamespaceURI = GetElementTagNamespaceURI(pXMLElement); | |
| if (wsNamespaceURI == L"http://www.xfa.com/schema/xfa-package/" || | |
| wsNamespaceURI == L"http://www.xfa.org/schema/xfa-package/" || | |
| wsNamespaceURI == L"http://www.w3.org/2001/XMLSchema-instance") { | |
| continue; | |
| } | |
| } | |
| XFA_Element eNodeType = XFA_Element::DataModel; | |
| if (eNodeType == XFA_Element::DataModel) { | |
| WideString wsDataNodeAttr; | |
| if (FindAttributeWithNS(pXMLElement, L"dataNode", | |
| L"http://www.xfa.org/schema/xfa-data/1.0/", | |
| wsDataNodeAttr)) { | |
| if (wsDataNodeAttr == L"dataGroup") | |
| eNodeType = XFA_Element::DataGroup; | |
| else if (wsDataNodeAttr == L"dataValue") | |
| eNodeType = XFA_Element::DataValue; | |
| } | |
| } | |
| WideString wsContentType; | |
| if (eNodeType == XFA_Element::DataModel) { | |
| if (FindAttributeWithNS(pXMLElement, L"contentType", | |
| L"http://www.xfa.org/schema/xfa-data/1.0/", | |
| wsContentType)) { | |
| if (!wsContentType.IsEmpty()) | |
| eNodeType = XFA_Element::DataValue; | |
| } | |
| } | |
| if (eNodeType == XFA_Element::DataModel) { | |
| for (CFX_XMLNode* pXMLDataChild = | |
| pXMLElement->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pXMLDataChild; pXMLDataChild = pXMLDataChild->GetNodeItem( | |
| CFX_XMLNode::NextSibling)) { | |
| if (pXMLDataChild->GetType() == FX_XMLNODE_Element) { | |
| if (!XFA_RecognizeRichText( | |
| static_cast<CFX_XMLElement*>(pXMLDataChild))) { | |
| eNodeType = XFA_Element::DataGroup; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| if (eNodeType == XFA_Element::DataModel) | |
| eNodeType = XFA_Element::DataValue; | |
| CXFA_Node* pXFAChild = | |
| m_pFactory->CreateNode(XFA_PacketType::Datasets, eNodeType); | |
| if (!pXFAChild) | |
| return; | |
| pXFAChild->JSNode()->SetCData( | |
| XFA_Attribute::Name, pXMLElement->GetLocalTagName(), false, false); | |
| bool bNeedValue = true; | |
| for (auto it : pXMLElement->GetAttributes()) { | |
| WideString wsName; | |
| WideString wsNS; | |
| if (!ResolveAttribute(pXMLElement, it.first, wsName, wsNS)) { | |
| continue; | |
| } | |
| if (wsName == L"nil" && it.second == L"true") { | |
| bNeedValue = false; | |
| continue; | |
| } | |
| if (wsNS == L"http://www.xfa.com/schema/xfa-package/" || | |
| wsNS == L"http://www.xfa.org/schema/xfa-package/" || | |
| wsNS == L"http://www.w3.org/2001/XMLSchema-instance" || | |
| wsNS == L"http://www.xfa.org/schema/xfa-data/1.0/") { | |
| continue; | |
| } | |
| CXFA_Node* pXFAMetaData = m_pFactory->CreateNode( | |
| XFA_PacketType::Datasets, XFA_Element::DataValue); | |
| if (!pXFAMetaData) | |
| return; | |
| pXFAMetaData->JSNode()->SetCData(XFA_Attribute::Name, wsName, false, | |
| false); | |
| pXFAMetaData->JSNode()->SetCData(XFA_Attribute::QualifiedName, | |
| it.first, false, false); | |
| pXFAMetaData->JSNode()->SetCData(XFA_Attribute::Value, it.second, | |
| false, false); | |
| pXFAMetaData->JSNode()->SetEnum(XFA_Attribute::Contains, | |
| XFA_AttributeEnum::MetaData, false); | |
| pXFAChild->InsertChild(pXFAMetaData, nullptr); | |
| pXFAMetaData->SetXMLMappingNode(pXMLElement); | |
| pXFAMetaData->SetFlag(XFA_NodeFlag_Initialized, false); | |
| } | |
| if (!bNeedValue) { | |
| WideString wsNilName(L"xsi:nil"); | |
| pXMLElement->RemoveAttribute(wsNilName.c_str()); | |
| } | |
| pXFANode->InsertChild(pXFAChild, nullptr); | |
| if (eNodeType == XFA_Element::DataGroup) | |
| ParseDataGroup(pXFAChild, pXMLElement, ePacketID); | |
| else if (bNeedValue) | |
| ParseDataValue(pXFAChild, pXMLChild, XFA_PacketType::Datasets); | |
| pXFAChild->SetXMLMappingNode(pXMLElement); | |
| pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); | |
| continue; | |
| } | |
| case FX_XMLNODE_CharData: | |
| case FX_XMLNODE_Text: { | |
| CFX_XMLText* pXMLText = static_cast<CFX_XMLText*>(pXMLChild); | |
| WideString wsText = pXMLText->GetText(); | |
| if (IsStringAllWhitespace(wsText)) | |
| continue; | |
| CXFA_Node* pXFAChild = m_pFactory->CreateNode(XFA_PacketType::Datasets, | |
| XFA_Element::DataValue); | |
| if (!pXFAChild) | |
| return; | |
| pXFAChild->JSNode()->SetCData(XFA_Attribute::Value, wsText, false, | |
| false); | |
| pXFANode->InsertChild(pXFAChild, nullptr); | |
| pXFAChild->SetXMLMappingNode(pXMLText); | |
| pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); | |
| continue; | |
| } | |
| default: | |
| continue; | |
| } | |
| } | |
| } | |
| void CXFA_SimpleParser::ParseDataValue(CXFA_Node* pXFANode, | |
| CFX_XMLNode* pXMLNode, | |
| XFA_PacketType ePacketID) { | |
| CFX_WideTextBuf wsValueTextBuf; | |
| CFX_WideTextBuf wsCurValueTextBuf; | |
| bool bMarkAsCompound = false; | |
| CFX_XMLNode* pXMLCurValueNode = nullptr; | |
| for (CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); | |
| pXMLChild; | |
| pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { | |
| FX_XMLNODETYPE eNodeType = pXMLChild->GetType(); | |
| if (eNodeType == FX_XMLNODE_Instruction) | |
| continue; | |
| if (eNodeType == FX_XMLNODE_Text || eNodeType == FX_XMLNODE_CharData) { | |
| WideString wsText = static_cast<CFX_XMLText*>(pXMLChild)->GetText(); | |
| if (!pXMLCurValueNode) | |
| pXMLCurValueNode = pXMLChild; | |
| wsCurValueTextBuf << wsText; | |
| } else if (XFA_RecognizeRichText(static_cast<CFX_XMLElement*>(pXMLChild))) { | |
| WideString wsText = | |
| GetPlainTextFromRichText(static_cast<CFX_XMLElement*>(pXMLChild)); | |
| if (!pXMLCurValueNode) | |
| pXMLCurValueNode = pXMLChild; | |
| wsCurValueTextBuf << wsText; | |
| } else { | |
| bMarkAsCompound = true; | |
| if (pXMLCurValueNode) { | |
| WideString wsCurValue = wsCurValueTextBuf.MakeString(); | |
| if (!wsCurValue.IsEmpty()) { | |
| CXFA_Node* pXFAChild = | |
| m_pFactory->CreateNode(ePacketID, XFA_Element::DataValue); | |
| if (!pXFAChild) | |
| return; | |
| pXFAChild->JSNode()->SetCData(XFA_Attribute::Name, L"", false, false); | |
| pXFAChild->JSNode()->SetCData(XFA_Attribute::Value, wsCurValue, false, | |
| false); | |
| pXFANode->InsertChild(pXFAChild, nullptr); | |
| pXFAChild->SetXMLMappingNode(pXMLCurValueNode); | |
| pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); | |
| wsValueTextBuf << wsCurValue; | |
| wsCurValueTextBuf.Clear(); | |
| } | |
| pXMLCurValueNode = nullptr; | |
| } | |
| CXFA_Node* pXFAChild = | |
| m_pFactory->CreateNode(ePacketID, XFA_Element::DataValue); | |
| if (!pXFAChild) | |
| return; | |
| WideString wsNodeStr = | |
| static_cast<CFX_XMLElement*>(pXMLChild)->GetLocalTagName(); | |
| pXFAChild->JSNode()->SetCData(XFA_Attribute::Name, wsNodeStr, false, | |
| false); | |
| ParseDataValue(pXFAChild, pXMLChild, ePacketID); | |
| pXFANode->InsertChild(pXFAChild, nullptr); | |
| pXFAChild->SetXMLMappingNode(pXMLChild); | |
| pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); | |
| WideString wsCurValue = | |
| pXFAChild->JSNode()->GetCData(XFA_Attribute::Value); | |
| wsValueTextBuf << wsCurValue; | |
| } | |
| } | |
| if (pXMLCurValueNode) { | |
| WideString wsCurValue = wsCurValueTextBuf.MakeString(); | |
| if (!wsCurValue.IsEmpty()) { | |
| if (bMarkAsCompound) { | |
| CXFA_Node* pXFAChild = | |
| m_pFactory->CreateNode(ePacketID, XFA_Element::DataValue); | |
| if (!pXFAChild) | |
| return; | |
| pXFAChild->JSNode()->SetCData(XFA_Attribute::Name, L"", false, false); | |
| pXFAChild->JSNode()->SetCData(XFA_Attribute::Value, wsCurValue, false, | |
| false); | |
| pXFANode->InsertChild(pXFAChild, nullptr); | |
| pXFAChild->SetXMLMappingNode(pXMLCurValueNode); | |
| pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); | |
| } | |
| wsValueTextBuf << wsCurValue; | |
| wsCurValueTextBuf.Clear(); | |
| } | |
| pXMLCurValueNode = nullptr; | |
| } | |
| WideString wsNodeValue = wsValueTextBuf.MakeString(); | |
| pXFANode->JSNode()->SetCData(XFA_Attribute::Value, wsNodeValue, false, false); | |
| } | |
| void CXFA_SimpleParser::ParseInstruction(CXFA_Node* pXFANode, | |
| CFX_XMLInstruction* pXMLInstruction, | |
| XFA_PacketType ePacketID) { | |
| if (!m_bDocumentParser) | |
| return; | |
| WideString wsTargetName = pXMLInstruction->GetName(); | |
| const std::vector<WideString>& target_data = pXMLInstruction->GetTargetData(); | |
| if (wsTargetName == L"originalXFAVersion") { | |
| if (target_data.size() > 1 && | |
| (pXFANode->GetDocument()->RecognizeXFAVersionNumber(target_data[0]) != | |
| XFA_VERSION_UNKNOWN) && | |
| target_data[1] == L"v2.7-scripting:1") { | |
| pXFANode->GetDocument()->SetFlag(XFA_DOCFLAG_Scripting, true); | |
| } | |
| } else if (wsTargetName == L"acrobat") { | |
| if (target_data.size() > 1 && target_data[0] == L"JavaScript" && | |
| target_data[1] == L"strictScoping") { | |
| pXFANode->GetDocument()->SetFlag(XFA_DOCFLAG_StrictScoping, true); | |
| } | |
| } | |
| } | |
| void CXFA_SimpleParser::CloseParser() { | |
| m_pXMLDoc.reset(); | |
| m_pStream.Reset(); | |
| } |