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"&");
79 break;
80 case '<':
81 textBuf << FX_WSTRC(L"<");
82 break;
83 case '>':
84 textBuf << FX_WSTRC(L">");
85 break;
86 case '\'':
87 textBuf << FX_WSTRC(L"'");
88 break;
89 case '\"':
90 textBuf << FX_WSTRC(L""");
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"&");
108 } else if (ch == '<') {
109 textBuf << FX_WSTRC(L"<");
110 } else if (ch == '>') {
111 textBuf << FX_WSTRC(L">");
112 } else if (ch == '\'') {
113 textBuf << FX_WSTRC(L"'");
114 } else if (ch == '\"') {
115 textBuf << FX_WSTRC(L""");
116 } else if (ch == ' ') {
117 if (i && str.GetAt(i - 1) != ' ') {
118 textBuf.AppendChar(' ');
119 } else {
120 textBuf << FX_WSTRC(L" ");
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