1 // Copyright 2014 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 "xfa/src/foxitlib.h"
8 #include "xfa/src/fxfa/src/common/xfa_utils.h"
9 #include "xfa/src/fxfa/src/common/xfa_object.h"
10 #include "xfa/src/fxfa/src/common/xfa_document.h"
11 #include "xfa/src/fxfa/src/common/xfa_parser.h"
12 #include "xfa/src/fxfa/src/common/xfa_script.h"
13 #include "xfa/src/fxfa/src/common/xfa_docdata.h"
14 #include "xfa/src/fxfa/src/common/xfa_doclayout.h"
15 #include "xfa/src/fxfa/src/common/xfa_localemgr.h"
16 #include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h"
17 #include "xfa_document_serialize.h"
Create(CXFA_Document * pDocument)18 IXFA_PacketImport* IXFA_PacketImport::Create(CXFA_Document* pDocument) {
19   return new CXFA_DataImporter(pDocument);
20 }
CXFA_DataImporter(CXFA_Document * pDocument)21 CXFA_DataImporter::CXFA_DataImporter(CXFA_Document* pDocument)
22     : m_pDocument(pDocument) {
23   ASSERT(m_pDocument != NULL);
24 }
ImportData(IFX_FileRead * pDataDocument)25 FX_BOOL CXFA_DataImporter::ImportData(IFX_FileRead* pDataDocument) {
26   IXFA_Parser* pDataDocumentParser = IXFA_Parser::Create(m_pDocument);
27   if (!pDataDocumentParser) {
28     return FALSE;
29   }
30   if (pDataDocumentParser->StartParse(pDataDocument, XFA_XDPPACKET_Datasets) !=
31       XFA_PARSESTATUS_Ready) {
32     pDataDocumentParser->Release();
33     return FALSE;
34   }
35   if (pDataDocumentParser->DoParse(NULL) < XFA_PARSESTATUS_Done) {
36     pDataDocumentParser->Release();
37     return FALSE;
38   }
39   CXFA_Node* pImportDataRoot = pDataDocumentParser->GetRootNode();
40   if (!pImportDataRoot) {
41     pDataDocumentParser->Release();
42     return FALSE;
43   }
44   CXFA_Node* pDataModel =
45       (CXFA_Node*)m_pDocument->GetXFANode(XFA_HASHCODE_Datasets);
46   if (!pDataModel) {
47     pDataDocumentParser->Release();
48     return FALSE;
49   }
50   CXFA_Node* pDataNode = (CXFA_Node*)m_pDocument->GetXFANode(XFA_HASHCODE_Data);
51   if (pDataNode) {
52     pDataModel->RemoveChild(pDataNode);
53   }
54   if (pImportDataRoot->GetClassID() == XFA_ELEMENT_DataModel) {
55     while (CXFA_Node* pChildNode =
56                pImportDataRoot->GetNodeItem(XFA_NODEITEM_FirstChild)) {
57       pImportDataRoot->RemoveChild(pChildNode);
58       pDataModel->InsertChild(pChildNode);
59     }
60   } else {
61     IFDE_XMLNode* pXMLNode = pImportDataRoot->GetXMLMappingNode();
62     IFDE_XMLNode* pParentXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::Parent);
63     if (pParentXMLNode) {
64       pParentXMLNode->RemoveChildNode(pXMLNode);
65     }
66     pDataModel->InsertChild(pImportDataRoot);
67   }
68   m_pDocument->DoDataRemerge(FALSE);
69   pDataDocumentParser->Release();
70   return TRUE;
71 }
XFA_ExportEncodeAttribute(const CFX_WideString & str)72 CFX_WideString XFA_ExportEncodeAttribute(const CFX_WideString& str) {
73   CFX_WideTextBuf textBuf;
74   int32_t iLen = str.GetLength();
75   for (int32_t i = 0; i < iLen; i++) {
76     switch (str[i]) {
77       case '&':
78         textBuf << FX_WSTRC(L"&amp;");
79         break;
80       case '<':
81         textBuf << FX_WSTRC(L"&lt;");
82         break;
83       case '>':
84         textBuf << FX_WSTRC(L"&gt;");
85         break;
86       case '\'':
87         textBuf << FX_WSTRC(L"&apos;");
88         break;
89       case '\"':
90         textBuf << FX_WSTRC(L"&quot;");
91         break;
92       default:
93         textBuf.AppendChar(str[i]);
94     }
95   }
96   return textBuf.GetWideString();
97 }
XFA_ExportEncodeContent(const CFX_WideStringC & str)98 CFX_WideString XFA_ExportEncodeContent(const CFX_WideStringC& str) {
99   CFX_WideTextBuf textBuf;
100   int32_t iLen = str.GetLength();
101   for (int32_t i = 0; i < iLen; i++) {
102     FX_WCHAR ch = str.GetAt(i);
103     if (!FDE_IsXMLValidChar(ch)) {
104       continue;
105     }
106     if (ch == '&') {
107       textBuf << FX_WSTRC(L"&amp;");
108     } else if (ch == '<') {
109       textBuf << FX_WSTRC(L"&lt;");
110     } else if (ch == '>') {
111       textBuf << FX_WSTRC(L"&gt;");
112     } else if (ch == '\'') {
113       textBuf << FX_WSTRC(L"&apos;");
114     } else if (ch == '\"') {
115       textBuf << FX_WSTRC(L"&quot;");
116     } else if (ch == ' ') {
117       if (i && str.GetAt(i - 1) != ' ') {
118         textBuf.AppendChar(' ');
119       } else {
120         textBuf << FX_WSTRC(L"&#x20;");
121       }
122     } else {
123       textBuf.AppendChar(str.GetAt(i));
124     }
125   }
126   return textBuf.GetWideString();
127 }
XFA_SaveAttribute(CXFA_Node * pNode,XFA_ATTRIBUTE eName,const CFX_WideStringC & wsName,FX_BOOL bProto,CFX_WideString & wsOutput)128 static void XFA_SaveAttribute(CXFA_Node* pNode,
129                               XFA_ATTRIBUTE eName,
130                               const CFX_WideStringC& wsName,
131                               FX_BOOL bProto,
132                               CFX_WideString& wsOutput) {
133   CFX_WideString wsValue;
134   if ((!bProto && !pNode->HasAttribute((XFA_ATTRIBUTE)eName, bProto)) ||
135       !pNode->GetAttribute((XFA_ATTRIBUTE)eName, wsValue, FALSE)) {
136     return;
137   }
138   wsValue = XFA_ExportEncodeAttribute(wsValue);
139   wsOutput += FX_WSTRC(L" ");
140   wsOutput += wsName;
141   wsOutput += FX_WSTRC(L"=\"");
142   wsOutput += wsValue;
143   wsOutput += FX_WSTRC(L"\"");
144 }
XFA_DataExporter_AttributeSaveInDataModel(CXFA_Node * pNode,XFA_ATTRIBUTE eAttribute)145 static FX_BOOL XFA_DataExporter_AttributeSaveInDataModel(
146     CXFA_Node* pNode,
147     XFA_ATTRIBUTE eAttribute) {
148   FX_BOOL bSaveInDataModel = FALSE;
149   if (pNode->GetClassID() != XFA_ELEMENT_Image) {
150     return bSaveInDataModel;
151   }
152   CXFA_Node* pValueNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
153   if (!pValueNode || pValueNode->GetClassID() != XFA_ELEMENT_Value) {
154     return bSaveInDataModel;
155   }
156   CXFA_Node* pFieldNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent);
157   if (pFieldNode && pFieldNode->GetBindData() &&
158       eAttribute == XFA_ATTRIBUTE_Href) {
159     bSaveInDataModel = TRUE;
160   }
161   return bSaveInDataModel;
162 }
XFA_DataExporter_ContentNodeNeedtoExport(CXFA_Node * pContentNode)163 FX_BOOL XFA_DataExporter_ContentNodeNeedtoExport(CXFA_Node* pContentNode) {
164   CFX_WideString wsContent;
165   if (!pContentNode->TryContent(wsContent, FALSE, FALSE)) {
166     return FALSE;
167   }
168   FXSYS_assert(pContentNode->GetObjectType() == XFA_OBJECTTYPE_ContentNode);
169   CXFA_Node* pParentNode = pContentNode->GetNodeItem(XFA_NODEITEM_Parent);
170   if (!pParentNode || pParentNode->GetClassID() != XFA_ELEMENT_Value) {
171     return TRUE;
172   }
173   CXFA_Node* pGrandParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
174   if (!pGrandParentNode ||
175       pGrandParentNode->GetObjectType() != XFA_OBJECTTYPE_ContainerNode) {
176     return TRUE;
177   }
178   if (pGrandParentNode->GetBindData()) {
179     return FALSE;
180   }
181   CXFA_WidgetData* pWidgetData = pGrandParentNode->GetWidgetData();
182   XFA_ELEMENT eUIType = pWidgetData->GetUIType();
183   if (eUIType == XFA_ELEMENT_PasswordEdit) {
184     return FALSE;
185   }
186   return TRUE;
187 }
XFA_DataExporter_RecognizeXFAVersionNumber(CXFA_Node * pTemplateRoot,CFX_WideString & wsVersionNumber)188 static void XFA_DataExporter_RecognizeXFAVersionNumber(
189     CXFA_Node* pTemplateRoot,
190     CFX_WideString& wsVersionNumber) {
191   wsVersionNumber.Empty();
192   if (!pTemplateRoot) {
193     return;
194   }
195   CFX_WideString wsTemplateNS;
196   if (!pTemplateRoot->TryNamespace(wsTemplateNS)) {
197     return;
198   }
199   XFA_VERSION eVersion =
200       pTemplateRoot->GetDocument()->RecognizeXFAVersionNumber(wsTemplateNS);
201   if (eVersion == XFA_VERSION_UNKNOWN) {
202     eVersion = XFA_VERSION_DEFAULT;
203   }
204   wsVersionNumber.Format(L"%i.%i", eVersion / 100, eVersion % 100);
205 }
XFA_DataExporter_RegenerateFormFile_Changed(CXFA_Node * pNode,CFX_WideTextBuf & buf,FX_BOOL bSaveXML=FALSE)206 static void XFA_DataExporter_RegenerateFormFile_Changed(
207     CXFA_Node* pNode,
208     CFX_WideTextBuf& buf,
209     FX_BOOL bSaveXML = FALSE) {
210   CFX_WideString wsAttrs;
211   int32_t iAttrs = 0;
212   const uint8_t* pAttrs = XFA_GetElementAttributes(pNode->GetClassID(), iAttrs);
213   while (iAttrs--) {
214     XFA_LPCATTRIBUTEINFO pAttr =
215         XFA_GetAttributeByID((XFA_ATTRIBUTE)pAttrs[iAttrs]);
216     if (pAttr->eName == XFA_ATTRIBUTE_Name ||
217         (XFA_DataExporter_AttributeSaveInDataModel(pNode, pAttr->eName) &&
218          !bSaveXML)) {
219       continue;
220     }
221     CFX_WideString wsAttr;
222     XFA_SaveAttribute(pNode, pAttr->eName, pAttr->pName, bSaveXML, wsAttr);
223     wsAttrs += wsAttr;
224   }
225   CFX_WideString wsChildren;
226   switch (pNode->GetObjectType()) {
227     case XFA_OBJECTTYPE_ContentNode: {
228       if (!bSaveXML && !XFA_DataExporter_ContentNodeNeedtoExport(pNode)) {
229         break;
230       }
231       CXFA_Node* pRawValueNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
232       while (pRawValueNode &&
233              pRawValueNode->GetClassID() != XFA_ELEMENT_SharpxHTML &&
234              pRawValueNode->GetClassID() != XFA_ELEMENT_Sharptext &&
235              pRawValueNode->GetClassID() != XFA_ELEMENT_Sharpxml) {
236         pRawValueNode = pRawValueNode->GetNodeItem(XFA_NODEITEM_NextSibling);
237       }
238       if (!pRawValueNode) {
239         break;
240       }
241       CFX_WideString wsContentType;
242       pNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, FALSE);
243       if (pRawValueNode->GetClassID() == XFA_ELEMENT_SharpxHTML &&
244           wsContentType.Equal(FX_WSTRC(L"text/html"))) {
245         IFDE_XMLNode* pExDataXML = pNode->GetXMLMappingNode();
246         if (!pExDataXML) {
247           break;
248         }
249         IFDE_XMLNode* pRichTextXML =
250             pExDataXML->GetNodeItem(IFDE_XMLNode::FirstChild);
251         if (!pRichTextXML) {
252           break;
253         }
254         IFX_MemoryStream* pMemStream = FX_CreateMemoryStream(TRUE);
255         IFX_Stream* pTempStream = IFX_Stream::CreateStream(
256             (IFX_FileWrite*)pMemStream, FX_STREAMACCESS_Text |
257                                             FX_STREAMACCESS_Write |
258                                             FX_STREAMACCESS_Append);
259         pTempStream->SetCodePage(FX_CODEPAGE_UTF8);
260         pRichTextXML->SaveXMLNode(pTempStream);
261         wsChildren += CFX_WideString::FromUTF8(
262             (const FX_CHAR*)pMemStream->GetBuffer(), pMemStream->GetSize());
263         pTempStream->Release();
264         pMemStream->Release();
265       } else if (pRawValueNode->GetClassID() == XFA_ELEMENT_Sharpxml &&
266                  wsContentType.Equal(FX_WSTRC(L"text/xml"))) {
267         CFX_WideString wsRawValue;
268         pRawValueNode->GetAttribute(XFA_ATTRIBUTE_Value, wsRawValue, FALSE);
269         if (wsRawValue.IsEmpty()) {
270           break;
271         }
272         CFX_WideStringArray wsSelTextArray;
273         int32_t iStart = 0;
274         int32_t iEnd = wsRawValue.Find(L'\n', iStart);
275         iEnd = (iEnd == -1) ? wsRawValue.GetLength() : iEnd;
276         while (iEnd >= iStart) {
277           wsSelTextArray.Add(wsRawValue.Mid(iStart, iEnd - iStart));
278           iStart = iEnd + 1;
279           if (iStart >= wsRawValue.GetLength()) {
280             break;
281           }
282           iEnd = wsRawValue.Find(L'\n', iStart);
283         }
284         CXFA_Node* pParentNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
285         FXSYS_assert(pParentNode);
286         CXFA_Node* pGrandparentNode =
287             pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
288         FXSYS_assert(pGrandparentNode);
289         CFX_WideString bodyTagName;
290         bodyTagName = pGrandparentNode->GetCData(XFA_ATTRIBUTE_Name);
291         if (bodyTagName.IsEmpty()) {
292           bodyTagName = FX_WSTRC(L"ListBox1");
293         }
294         buf << FX_WSTRC(L"<");
295         buf << bodyTagName;
296         buf << FX_WSTRC(L" xmlns=\"\"\n>");
297         for (int32_t i = 0; i < wsSelTextArray.GetSize(); i++) {
298           buf << FX_WSTRC(L"<value\n>");
299           buf << XFA_ExportEncodeContent(wsSelTextArray[i]);
300           buf << FX_WSTRC(L"</value\n>");
301         }
302         buf << FX_WSTRC(L"</");
303         buf << bodyTagName;
304         buf << FX_WSTRC(L"\n>");
305         wsChildren += buf.GetWideString();
306         buf.Clear();
307       } else {
308         CFX_WideStringC wsValue = pRawValueNode->GetCData(XFA_ATTRIBUTE_Value);
309         wsChildren += XFA_ExportEncodeContent(wsValue);
310       }
311     } break;
312     case XFA_OBJECTTYPE_TextNode:
313     case XFA_OBJECTTYPE_NodeC:
314     case XFA_OBJECTTYPE_NodeV: {
315       CFX_WideStringC wsValue = pNode->GetCData(XFA_ATTRIBUTE_Value);
316       wsChildren += XFA_ExportEncodeContent(wsValue);
317     } break;
318     default:
319       if (pNode->GetClassID() == XFA_ELEMENT_Items) {
320         CXFA_Node* pTemplateNode = pNode->GetTemplateNode();
321         if (!pTemplateNode ||
322             pTemplateNode->CountChildren(XFA_ELEMENT_UNKNOWN) !=
323                 pNode->CountChildren(XFA_ELEMENT_UNKNOWN)) {
324           bSaveXML = TRUE;
325         }
326       }
327       CFX_WideTextBuf newBuf;
328       CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
329       while (pChildNode) {
330         XFA_DataExporter_RegenerateFormFile_Changed(pChildNode, newBuf,
331                                                     bSaveXML);
332         wsChildren += newBuf.GetWideString();
333         newBuf.Clear();
334         pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
335       }
336       if (!bSaveXML && !wsChildren.IsEmpty() &&
337           pNode->GetClassID() == XFA_ELEMENT_Items) {
338         wsChildren.Empty();
339         bSaveXML = TRUE;
340         CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
341         while (pChildNode) {
342           XFA_DataExporter_RegenerateFormFile_Changed(pChildNode, newBuf,
343                                                       bSaveXML);
344           wsChildren += newBuf.GetWideString();
345           newBuf.Clear();
346           pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
347         }
348       }
349       break;
350   }
351   if (!wsChildren.IsEmpty() || !wsAttrs.IsEmpty() ||
352       pNode->HasAttribute(XFA_ATTRIBUTE_Name)) {
353     CFX_WideStringC wsElement;
354     pNode->GetClassName(wsElement);
355     CFX_WideString wsName;
356     XFA_SaveAttribute(pNode, XFA_ATTRIBUTE_Name, FX_WSTRC(L"name"), TRUE,
357                       wsName);
358     buf << FX_WSTRC(L"<");
359     buf << wsElement;
360     buf << wsName;
361     buf << wsAttrs;
362     if (wsChildren.IsEmpty()) {
363       buf << FX_WSTRC(L"\n/>");
364     } else {
365       buf << FX_WSTRC(L"\n>");
366       buf << wsChildren;
367       buf << FX_WSTRC(L"</");
368       buf << wsElement;
369       buf << FX_WSTRC(L"\n>");
370     }
371   }
372 }
XFA_DataExporter_RegenerateFormFile_Container(CXFA_Node * pNode,IFX_Stream * pStream,FX_BOOL bSaveXML=FALSE)373 static void XFA_DataExporter_RegenerateFormFile_Container(
374     CXFA_Node* pNode,
375     IFX_Stream* pStream,
376     FX_BOOL bSaveXML = FALSE) {
377   XFA_ELEMENT eElement = pNode->GetClassID();
378   if (eElement == XFA_ELEMENT_Field || eElement == XFA_ELEMENT_Draw ||
379       !pNode->IsContainerNode()) {
380     CFX_WideTextBuf buf;
381     XFA_DataExporter_RegenerateFormFile_Changed(pNode, buf, bSaveXML);
382     FX_STRSIZE nLen = buf.GetLength();
383     if (nLen > 0) {
384       pStream->WriteString((const FX_WCHAR*)buf.GetBuffer(), nLen);
385     }
386     return;
387   }
388   CFX_WideStringC wsElement;
389   pNode->GetClassName(wsElement);
390   pStream->WriteString(L"<", 1);
391   pStream->WriteString(wsElement.GetPtr(), wsElement.GetLength());
392   CFX_WideString wsOutput;
393   XFA_SaveAttribute(pNode, XFA_ATTRIBUTE_Name, FX_WSTRC(L"name"), TRUE,
394                     wsOutput);
395   CFX_WideString wsAttrs;
396   int32_t iAttrs = 0;
397   const uint8_t* pAttrs = XFA_GetElementAttributes(pNode->GetClassID(), iAttrs);
398   while (iAttrs--) {
399     XFA_LPCATTRIBUTEINFO pAttr =
400         XFA_GetAttributeByID((XFA_ATTRIBUTE)pAttrs[iAttrs]);
401     if (pAttr->eName == XFA_ATTRIBUTE_Name) {
402       continue;
403     }
404     CFX_WideString wsAttr;
405     XFA_SaveAttribute(pNode, pAttr->eName, pAttr->pName, FALSE, wsAttr);
406     wsOutput += wsAttr;
407   }
408   if (!wsOutput.IsEmpty()) {
409     pStream->WriteString((const FX_WCHAR*)wsOutput, wsOutput.GetLength());
410   }
411   CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
412   if (pChildNode) {
413     pStream->WriteString(L"\n>", 2);
414     while (pChildNode) {
415       XFA_DataExporter_RegenerateFormFile_Container(pChildNode, pStream,
416                                                     bSaveXML);
417       pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
418     }
419     pStream->WriteString(L"</", 2);
420     pStream->WriteString(wsElement.GetPtr(), wsElement.GetLength());
421     pStream->WriteString(L"\n>", 2);
422   } else {
423     pStream->WriteString(L"\n/>", 3);
424   }
425 }
XFA_DataExporter_RegenerateFormFile(CXFA_Node * pNode,IFX_Stream * pStream,const FX_CHAR * pChecksum,FX_BOOL bSaveXML)426 void XFA_DataExporter_RegenerateFormFile(CXFA_Node* pNode,
427                                          IFX_Stream* pStream,
428                                          const FX_CHAR* pChecksum,
429                                          FX_BOOL bSaveXML) {
430   if (pNode->GetObjectType() == XFA_OBJECTTYPE_ModelNode) {
431     static const FX_WCHAR* s_pwsTagName = L"<form";
432     static const FX_WCHAR* s_pwsClose = L"</form\n>";
433     pStream->WriteString(s_pwsTagName, FXSYS_wcslen(s_pwsTagName));
434     if (pChecksum != NULL) {
435       static const FX_WCHAR* s_pwChecksum = L" checksum=\"";
436       CFX_WideString wsChecksum =
437           CFX_WideString::FromUTF8(pChecksum, FXSYS_strlen(pChecksum));
438       pStream->WriteString(s_pwChecksum, FXSYS_wcslen(s_pwChecksum));
439       pStream->WriteString((const FX_WCHAR*)wsChecksum, wsChecksum.GetLength());
440       pStream->WriteString(L"\"", 1);
441     }
442     pStream->WriteString(L" xmlns=\"", FXSYS_wcslen(L" xmlns=\""));
443     const FX_WCHAR* pURI = XFA_GetPacketByIndex(XFA_PACKET_Form)->pURI;
444     pStream->WriteString(pURI, FXSYS_wcslen(pURI));
445     CFX_WideString wsVersionNumber;
446     XFA_DataExporter_RecognizeXFAVersionNumber(
447         (CXFA_Node*)pNode->GetDocument()->GetXFANode(XFA_XDPPACKET_Template),
448         wsVersionNumber);
449     if (wsVersionNumber.IsEmpty()) {
450       wsVersionNumber = FX_WSTRC(L"2.8");
451     }
452     wsVersionNumber += FX_WSTRC(L"/\"\n>");
453     pStream->WriteString((const FX_WCHAR*)wsVersionNumber,
454                          wsVersionNumber.GetLength());
455     CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
456     while (pChildNode) {
457       XFA_DataExporter_RegenerateFormFile_Container(pChildNode, pStream);
458       pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
459     }
460     pStream->WriteString(s_pwsClose, FXSYS_wcslen(s_pwsClose));
461   } else {
462     XFA_DataExporter_RegenerateFormFile_Container(pNode, pStream, bSaveXML);
463   }
464 }
Create(CXFA_Document * pDocument,XFA_DATAFORMAT eFormat)465 IXFA_PacketExport* IXFA_PacketExport::Create(CXFA_Document* pDocument,
466                                              XFA_DATAFORMAT eFormat) {
467   return new CXFA_DataExporter(pDocument);
468 }
CXFA_DataExporter(CXFA_Document * pDocument)469 CXFA_DataExporter::CXFA_DataExporter(CXFA_Document* pDocument)
470     : m_pDocument(pDocument) {
471   ASSERT(m_pDocument != NULL);
472 }
Export(IFX_FileWrite * pWrite)473 FX_BOOL CXFA_DataExporter::Export(IFX_FileWrite* pWrite) {
474   return Export(pWrite, m_pDocument->GetRoot());
475 }
Export(IFX_FileWrite * pWrite,CXFA_Node * pNode,FX_DWORD dwFlag,const FX_CHAR * pChecksum)476 FX_BOOL CXFA_DataExporter::Export(IFX_FileWrite* pWrite,
477                                   CXFA_Node* pNode,
478                                   FX_DWORD dwFlag,
479                                   const FX_CHAR* pChecksum) {
480   ASSERT(pWrite != NULL);
481   if (pWrite == NULL) {
482     return FALSE;
483   }
484   IFX_Stream* pStream = IFX_Stream::CreateStream(
485       pWrite,
486       FX_STREAMACCESS_Text | FX_STREAMACCESS_Write | FX_STREAMACCESS_Append);
487   if (pStream == NULL) {
488     return FALSE;
489   }
490   pStream->SetCodePage(FX_CODEPAGE_UTF8);
491   FX_BOOL bRet = Export(pStream, pNode, dwFlag, pChecksum);
492   pStream->Release();
493   return bRet;
494 }
Export(IFX_Stream * pStream,CXFA_Node * pNode,FX_DWORD dwFlag,const FX_CHAR * pChecksum)495 FX_BOOL CXFA_DataExporter::Export(IFX_Stream* pStream,
496                                   CXFA_Node* pNode,
497                                   FX_DWORD dwFlag,
498                                   const FX_CHAR* pChecksum) {
499   IFDE_XMLDoc* pXMLDoc = m_pDocument->GetParser()->GetXMLDoc();
500   if (pNode->GetObjectType() == XFA_OBJECTTYPE_ModelNode) {
501     switch (pNode->GetPacketID()) {
502       case XFA_XDPPACKET_XDP: {
503         static const FX_WCHAR* s_pwsPreamble =
504             L"<xdp:xdp xmlns:xdp=\"http://ns.adobe.com/xdp/\">";
505         pStream->WriteString(s_pwsPreamble, FXSYS_wcslen(s_pwsPreamble));
506         for (CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
507              pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
508           Export(pStream, pChild, dwFlag, pChecksum);
509         }
510         static const FX_WCHAR* s_pwsPostamble = L"</xdp:xdp\n>";
511         pStream->WriteString(s_pwsPostamble, FXSYS_wcslen(s_pwsPostamble));
512       } break;
513       case XFA_XDPPACKET_Datasets: {
514         IFDE_XMLElement* pElement =
515             (IFDE_XMLElement*)pNode->GetXMLMappingNode();
516         if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) {
517           return FALSE;
518         }
519         CXFA_Node* pDataNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
520         FXSYS_assert(pDataNode != NULL);
521         XFA_DataExporter_DealWithDataGroupNode(pDataNode);
522         pXMLDoc->SaveXMLNode(pStream, pElement);
523       } break;
524       case XFA_XDPPACKET_Form: {
525         XFA_DataExporter_RegenerateFormFile(pNode, pStream, pChecksum);
526       } break;
527       case XFA_XDPPACKET_Template:
528       default: {
529         IFDE_XMLElement* pElement =
530             (IFDE_XMLElement*)pNode->GetXMLMappingNode();
531         if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) {
532           return FALSE;
533         }
534         pXMLDoc->SaveXMLNode(pStream, pElement);
535       } break;
536     }
537   } else {
538     CXFA_Node* pDataNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
539     CXFA_Node* pExportNode = pNode;
540     for (CXFA_Node* pChildNode =
541              pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild);
542          pChildNode;
543          pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
544       if (pChildNode != pNode) {
545         pExportNode = pDataNode;
546         break;
547       }
548     }
549     IFDE_XMLElement* pElement =
550         (IFDE_XMLElement*)pExportNode->GetXMLMappingNode();
551     if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) {
552       return FALSE;
553     }
554     XFA_DataExporter_DealWithDataGroupNode(pExportNode);
555     pElement->SetString(FX_WSTRC(L"xmlns:xfa"),
556                         FX_WSTRC(L"http://www.xfa.org/schema/xfa-data/1.0/"));
557     pXMLDoc->SaveXMLNode(pStream, pElement);
558     pElement->RemoveAttribute(L"xmlns:xfa");
559   }
560   return TRUE;
561 }
XFA_DataExporter_DealWithDataGroupNode(CXFA_Node * pDataNode)562 void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode) {
563   if (!pDataNode || pDataNode->GetClassID() == XFA_ELEMENT_DataValue) {
564     return;
565   }
566   int32_t iChildNum = 0;
567   for (CXFA_Node* pChildNode = pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild);
568        pChildNode;
569        pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
570     iChildNum++;
571     XFA_DataExporter_DealWithDataGroupNode(pChildNode);
572   }
573   if (pDataNode->GetClassID() == XFA_ELEMENT_DataGroup) {
574     if (iChildNum > 0) {
575       IFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode();
576       FXSYS_assert(pXMLNode->GetType() == FDE_XMLNODE_Element);
577       IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode;
578       if (pXMLElement->HasAttribute(L"xfa:dataNode")) {
579         pXMLElement->RemoveAttribute(L"xfa:dataNode");
580       }
581     } else {
582       IFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode();
583       FXSYS_assert(pXMLNode->GetType() == FDE_XMLNODE_Element);
584       ((IFDE_XMLElement*)pXMLNode)
585           ->SetString(FX_WSTRC(L"xfa:dataNode"), FX_WSTRC(L"dataGroup"));
586     }
587   }
588 }
589