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