• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #ifndef XFA_FXFA_PARSER_CXFA_NODE_H_
8 #define XFA_FXFA_PARSER_CXFA_NODE_H_
9 
10 #include <memory>
11 #include <utility>
12 #include <vector>
13 
14 #include "core/fxcrt/fx_string.h"
15 #include "core/fxcrt/tree_node.h"
16 #include "core/fxge/fx_dib.h"
17 #include "third_party/base/optional.h"
18 #include "third_party/base/span.h"
19 #include "xfa/fxfa/cxfa_ffwidget_type.h"
20 #include "xfa/fxfa/fxfa.h"
21 #include "xfa/fxfa/parser/cxfa_object.h"
22 
23 class CFGAS_GEFont;
24 class CFX_DIBitmap;
25 class CFX_XMLDocument;
26 class CFX_XMLNode;
27 class CXFA_Bind;
28 class CXFA_Border;
29 class CXFA_Calculate;
30 class CXFA_Caption;
31 class CXFA_Event;
32 class CXFA_EventParam;
33 class CXFA_FFDoc;
34 class CXFA_FFDocView;
35 class CXFA_Font;
36 class CXFA_Keep;
37 class CXFA_Margin;
38 class CXFA_Occur;
39 class CXFA_Para;
40 class CXFA_Script;
41 class CXFA_TextLayout;
42 class CXFA_Ui;
43 class CXFA_Validate;
44 class CXFA_Value;
45 class CXFA_WidgetLayoutData;
46 class LocaleIface;
47 
48 #define XFA_NODEFILTER_Children 0x01
49 #define XFA_NODEFILTER_Properties 0x02
50 #define XFA_NODEFILTER_OneOfProperty 0x04
51 
52 enum XFA_CHECKSTATE {
53   XFA_CHECKSTATE_On = 0,
54   XFA_CHECKSTATE_Off = 1,
55   XFA_CHECKSTATE_Neutral = 2,
56 };
57 
58 enum XFA_VALUEPICTURE {
59   XFA_VALUEPICTURE_Raw = 0,
60   XFA_VALUEPICTURE_Display,
61   XFA_VALUEPICTURE_Edit,
62   XFA_VALUEPICTURE_DataBind,
63 };
64 
65 enum XFA_NodeFlag {
66   XFA_NodeFlag_None = 0,
67   XFA_NodeFlag_Initialized = 1 << 0,
68   XFA_NodeFlag_HasRemovedChildren = 1 << 1,
69   XFA_NodeFlag_NeedsInitApp = 1 << 2,
70   XFA_NodeFlag_BindFormItems = 1 << 3,
71   XFA_NodeFlag_UserInteractive = 1 << 4,
72   XFA_NodeFlag_UnusedNode = 1 << 5,
73   XFA_NodeFlag_LayoutGeneratedNode = 1 << 6
74 };
75 
76 class CXFA_Node : public CXFA_Object, public TreeNode<CXFA_Node> {
77  public:
78   struct PropertyData {
79     XFA_Element property;
80     uint8_t occurance_count;
81     uint8_t flags;
82   };
83 
84   struct AttributeData {
85     XFA_Attribute attribute;
86     XFA_AttributeType type;
87     void* default_value;
88   };
89 
90   static std::unique_ptr<CXFA_Node> Create(CXFA_Document* doc,
91                                            XFA_Element element,
92                                            XFA_PacketType packet);
93 
94   ~CXFA_Node() override;
95 
96   bool HasProperty(XFA_Element property) const;
97   bool HasPropertyFlags(XFA_Element property, uint8_t flags) const;
98   uint8_t PropertyOccuranceCount(XFA_Element property) const;
99 
100   std::pair<CXFA_Node*, int32_t> GetProperty(int32_t index,
101                                              XFA_Element eProperty) const;
102   CXFA_Node* GetOrCreateProperty(int32_t index, XFA_Element eProperty);
103 
104   void SendAttributeChangeMessage(XFA_Attribute eAttribute, bool bScriptModify);
105 
106   bool HasAttribute(XFA_Attribute attr) const;
107   XFA_AttributeType GetAttributeType(XFA_Attribute type) const;
108 
109   // Note: returns XFA_Attribute::Unknown for invalid indicies.
110   XFA_Attribute GetAttribute(size_t i) const;
111 
GetPacketType()112   XFA_PacketType GetPacketType() const { return m_ePacket; }
113 
114   void SetFlag(uint32_t dwFlag);
115   void SetFlagAndNotify(uint32_t dwFlag);
116   void ClearFlag(uint32_t dwFlag);
117 
118   CXFA_Node* CreateInstanceIfPossible(bool bDataMerge);
119   int32_t GetCount();
120   CXFA_Node* GetItemIfExists(int32_t iIndex);
121   void RemoveItem(CXFA_Node* pRemoveInstance, bool bRemoveDataBinding);
122   void InsertItem(CXFA_Node* pNewInstance,
123                   int32_t iPos,
124                   int32_t iCount,
125                   bool bMoveDataBindingNodes);
126 
IsInitialized()127   bool IsInitialized() const { return HasFlag(XFA_NodeFlag_Initialized); }
IsUserInteractive()128   bool IsUserInteractive() const {
129     return HasFlag(XFA_NodeFlag_UserInteractive);
130   }
IsUnusedNode()131   bool IsUnusedNode() const { return HasFlag(XFA_NodeFlag_UnusedNode); }
IsLayoutGeneratedNode()132   bool IsLayoutGeneratedNode() const {
133     return HasFlag(XFA_NodeFlag_LayoutGeneratedNode);
134   }
135 
136   bool PresenceRequiresSpace() const;
137   void SetBindingNode(CXFA_Node* node);
138   void SetNodeAndDescendantsUnused();
139 
HasRemovedChildren()140   bool HasRemovedChildren() const {
141     return HasFlag(XFA_NodeFlag_HasRemovedChildren);
142   }
143 
144   bool IsAttributeInXML();
IsFormContainer()145   bool IsFormContainer() const {
146     return m_ePacket == XFA_PacketType::Form && IsContainerNode();
147   }
148 
SetXMLMappingNode(CFX_XMLNode * node)149   void SetXMLMappingNode(CFX_XMLNode* node) { xml_node_ = node; }
GetXMLMappingNode()150   CFX_XMLNode* GetXMLMappingNode() const { return xml_node_.Get(); }
151   CFX_XMLNode* CreateXMLMappingNode();
152   bool IsNeedSavingXMLNode() const;
153 
154   void SetToXML(const WideString& value);
155 
GetNameHash()156   uint32_t GetNameHash() const { return m_dwNameHash; }
IsUnnamed()157   bool IsUnnamed() const { return m_dwNameHash == 0; }
158   CXFA_Node* GetModelNode();
159   void UpdateNameHash();
160 
161   size_t CountChildren(XFA_Element eType, bool bOnlyChild);
162 
163   template <typename T>
GetChild(size_t index,XFA_Element eType,bool bOnlyChild)164   T* GetChild(size_t index, XFA_Element eType, bool bOnlyChild) {
165     return static_cast<T*>(GetChildInternal(index, eType, bOnlyChild));
166   }
167 
168   void InsertChildAndNotify(int32_t index, CXFA_Node* pNode);
169   void InsertChildAndNotify(CXFA_Node* pNode, CXFA_Node* pBeforeNode);
170   void RemoveChildAndNotify(CXFA_Node* pNode, bool bNotify);
171 
172   CXFA_Node* Clone(bool bRecursive);
173 
174   CXFA_Node* GetNextContainerSibling() const;
175   CXFA_Node* GetPrevContainerSibling() const;
176   CXFA_Node* GetFirstContainerChild() const;
177   CXFA_Node* GetContainerParent() const;
178 
179   std::vector<CXFA_Node*> GetNodeListForType(XFA_Element eTypeFilter);
180   std::vector<CXFA_Node*> GetNodeListWithFilter(uint32_t dwTypeFilter);
181   CXFA_Node* CreateSamePacketNode(XFA_Element eType);
182   CXFA_Node* CloneTemplateToForm(bool bRecursive);
183   CXFA_Node* GetTemplateNodeIfExists() const;
184   void SetTemplateNode(CXFA_Node* pTemplateNode);
185   CXFA_Node* GetDataDescriptionNode();
186   void SetDataDescriptionNode(CXFA_Node* pDataDescriptionNode);
187   CXFA_Node* GetBindData();
HasBindItems()188   bool HasBindItems() const { return !binding_nodes_.empty(); }
GetBindItemsCopy()189   std::vector<CXFA_Node*> GetBindItemsCopy() { return binding_nodes_; }
190   int32_t AddBindItem(CXFA_Node* pFormNode);
191   int32_t RemoveBindItem(CXFA_Node* pFormNode);
192   bool HasBindItem() const;
193   CXFA_Node* GetContainerNode();
194   LocaleIface* GetLocale();
195   Optional<WideString> GetLocaleName();
196   XFA_AttributeValue GetIntact();
197   WideString GetNameExpression();
198 
199   CXFA_Node* GetFirstChildByName(WideStringView wsNodeName) const;
200   CXFA_Node* GetFirstChildByName(uint32_t dwNodeNameHash) const;
201   template <typename T>
GetFirstChildByClass(XFA_Element eType)202   T* GetFirstChildByClass(XFA_Element eType) const {
203     return static_cast<T*>(GetFirstChildByClassInternal(eType));
204   }
205   CXFA_Node* GetNextSameNameSibling(uint32_t dwNodeNameHash) const;
206   template <typename T>
GetNextSameNameSibling(WideStringView wsNodeName)207   T* GetNextSameNameSibling(WideStringView wsNodeName) const {
208     return static_cast<T*>(GetNextSameNameSiblingInternal(wsNodeName));
209   }
210   template <typename T>
GetNextSameClassSibling(XFA_Element eType)211   T* GetNextSameClassSibling(XFA_Element eType) const {
212     return static_cast<T*>(GetNextSameClassSiblingInternal(eType));
213   }
214 
215   CXFA_Node* GetOneChildNamed(WideStringView wsName);
216   CXFA_Node* GetOneChildOfClass(WideStringView wsClass);
217 
218   std::vector<CXFA_Node*> GetSiblings(bool bIsClassName);
219   size_t GetIndex(bool bIsProperty, bool bIsClassIndex);
220   size_t GetIndexByName();
221   size_t GetIndexByClassName();
222 
223   CXFA_Node* GetInstanceMgrOfSubform();
224 
225   Optional<bool> GetDefaultBoolean(XFA_Attribute attr) const;
226   Optional<int32_t> GetDefaultInteger(XFA_Attribute attr) const;
227   Optional<CXFA_Measurement> GetDefaultMeasurement(XFA_Attribute attr) const;
228   Optional<WideString> GetDefaultCData(XFA_Attribute attr) const;
229   Optional<XFA_AttributeValue> GetDefaultEnum(XFA_Attribute attr) const;
230 
231   bool IsOpenAccess() const;
232 
233   CXFA_Occur* GetOccurIfExists();
234   CXFA_Border* GetBorderIfExists() const;
235   CXFA_Border* GetOrCreateBorderIfPossible();
236   CXFA_Caption* GetCaptionIfExists() const;
237   CXFA_Font* GetFontIfExists() const;
238   CXFA_Font* GetOrCreateFontIfPossible();
239 
240   float GetFontSize() const;
241   FX_ARGB GetTextColor() const;
242   float GetLineHeight() const;
243 
244   CXFA_Margin* GetMarginIfExists() const;
245   CXFA_Para* GetParaIfExists() const;
246   CXFA_Calculate* GetCalculateIfExists() const;
247   CXFA_Validate* GetValidateIfExists() const;
248   CXFA_Validate* GetOrCreateValidateIfPossible();
249 
250   CXFA_Value* GetFormValueIfExists() const;
251   WideString GetRawValue();
252 
253   int32_t GetRotate() const;
254   Optional<float> TryWidth();
255 
256   CXFA_Node* GetExclGroupIfExists();
257 
258   XFA_EventError ProcessEvent(CXFA_FFDocView* pDocView,
259                               XFA_AttributeValue iActivity,
260                               CXFA_EventParam* pEventParam);
261   XFA_EventError ProcessCalculate(CXFA_FFDocView* pDocView);
262   XFA_EventError ProcessValidate(CXFA_FFDocView* pDocView, int32_t iFlags);
263   XFA_EventError ExecuteScript(CXFA_FFDocView* pDocView,
264                                CXFA_Script* script,
265                                CXFA_EventParam* pEventParam);
266   std::pair<XFA_EventError, bool> ExecuteBoolScript(
267       CXFA_FFDocView* pDocView,
268       CXFA_Script* script,
269       CXFA_EventParam* pEventParam);
270 
271   CXFA_Node* GetUIChildNode();
272 
273   // NOTE: value returned is often determined by child UI node, and
274   // can't be used to infer anything about this particual node itself.
275   XFA_FFWidgetType GetFFWidgetType();
276 
277   CFX_RectF GetUIMargin();
278   CXFA_Border* GetUIBorder();
279 
SetPreNull(bool val)280   void SetPreNull(bool val) { m_bPreNull = val; }
IsNull()281   bool IsNull() const { return m_bIsNull; }
SetIsNull(bool val)282   void SetIsNull(bool val) { m_bIsNull = val; }
283 
SetWidgetReady()284   void SetWidgetReady() { is_widget_ready_ = true; }
IsWidgetReady()285   bool IsWidgetReady() const { return is_widget_ready_; }
286   std::vector<CXFA_Event*> GetEventByActivity(XFA_AttributeValue iActivity,
287                                               bool bIsFormReady);
288 
289   void ResetData();
290   void StartWidgetLayout(CXFA_FFDoc* doc,
291                          float* pCalcWidth,
292                          float* pCalcHeight);
293   Optional<float> FindSplitPos(CXFA_FFDocView* pDocView,
294                                size_t szBlockIndex,
295                                float fCalcHeight);
296 
297   bool LoadCaption(CXFA_FFDoc* doc);
298   CXFA_TextLayout* GetCaptionTextLayout();
299   CXFA_TextLayout* GetTextLayout();
300 
301   bool LoadImageImage(CXFA_FFDoc* doc);
302   bool LoadImageEditImage(CXFA_FFDoc* doc);
303   CFX_Size GetImageDpi() const;
304   CFX_Size GetImageEditDpi() const;
305 
306   RetainPtr<CFX_DIBitmap> GetImageImage();
307   RetainPtr<CFX_DIBitmap> GetImageEditImage();
308   void SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage);
309   void SetImageEditImage(const RetainPtr<CFX_DIBitmap>& newImage);
310 
311   RetainPtr<CFGAS_GEFont> GetFDEFont(CXFA_FFDoc* doc);
312 
313   bool IsListBox();
314   bool IsRadioButton();
315   bool IsMultiLine();
316 
317   bool HasButtonRollover();
318   bool HasButtonDown();
319 
320   float GetCheckButtonSize();
321 
322   XFA_CHECKSTATE GetCheckState();
323   void SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify);
324 
325   CXFA_Node* GetSelectedMember();
326   CXFA_Node* SetSelectedMember(WideStringView wsName, bool bNotify);
327   void SetSelectedMemberByValue(WideStringView wsValue,
328                                 bool bNotify,
329                                 bool bScriptModify,
330                                 bool bSyncData);
331 
332   CXFA_Node* GetExclGroupFirstMember();
333   CXFA_Node* GetExclGroupNextMember(CXFA_Node* pNode);
334 
335   bool IsChoiceListAllowTextEntry();
336   int32_t CountChoiceListItems(bool bSaveValue);
337   Optional<WideString> GetChoiceListItem(int32_t nIndex, bool bSaveValue);
338   bool IsChoiceListMultiSelect();
339   bool IsChoiceListCommitOnSelect();
340   std::vector<WideString> GetChoiceListItems(bool bSaveValue);
341 
342   int32_t CountSelectedItems();
343   int32_t GetSelectedItem(int32_t nIndex);
344   std::vector<int32_t> GetSelectedItems();
345   std::vector<WideString> GetSelectedItemsValue();
346   void SetSelectedItems(const std::vector<int32_t>& iSelArray,
347                         bool bNotify,
348                         bool bScriptModify,
349                         bool bSyncData);
350   void InsertItem(const WideString& wsLabel,
351                   const WideString& wsValue,
352                   bool bNotify);
353   bool DeleteItem(int32_t nIndex, bool bNotify, bool bScriptModify);
354   void ClearAllSelections();
355 
356   bool GetItemState(int32_t nIndex);
357   void SetItemState(int32_t nIndex,
358                     bool bSelected,
359                     bool bNotify,
360                     bool bScriptModify,
361                     bool bSyncData);
362 
363   WideString GetItemValue(WideStringView wsLabel);
364 
365   bool IsHorizontalScrollPolicyOff();
366   bool IsVerticalScrollPolicyOff();
367   Optional<int32_t> GetNumberOfCells();
368 
369   bool SetValue(XFA_VALUEPICTURE eValueType, const WideString& wsValue);
370   WideString GetValue(XFA_VALUEPICTURE eValueType);
371 
372   WideString GetPictureContent(XFA_VALUEPICTURE ePicture);
373   WideString GetNormalizeDataValue(const WideString& wsValue);
374   WideString GetFormatDataValue(const WideString& wsValue);
375   WideString NormalizeNumStr(const WideString& wsValue);
376 
377   std::pair<XFA_Element, int32_t> GetMaxChars();
378   int32_t GetFracDigits();
379   int32_t GetLeadDigits();
380 
381   WideString NumericLimit(const WideString& wsValue);
382 
383   bool IsTransparent() const;
384   bool IsProperty() const;
385 
386  protected:
387   CXFA_Node(CXFA_Document* pDoc,
388             XFA_PacketType ePacket,
389             uint32_t validPackets,
390             XFA_ObjectType oType,
391             XFA_Element eType,
392             pdfium::span<const PropertyData> properties,
393             pdfium::span<const AttributeData> attributes,
394             std::unique_ptr<CJX_Object> js_object);
395 
396   virtual XFA_Element GetValueNodeType() const;
397   virtual XFA_FFWidgetType GetDefaultFFWidgetType() const;
398 
399  private:
400   void ProcessScriptTestValidate(CXFA_FFDocView* pDocView,
401                                  CXFA_Validate* validate,
402                                  XFA_EventError iRet,
403                                  bool pRetValue,
404                                  bool bVersionFlag);
405   XFA_EventError ProcessFormatTestValidate(CXFA_FFDocView* pDocView,
406                                            CXFA_Validate* validate,
407                                            bool bVersionFlag);
408   XFA_EventError ProcessNullTestValidate(CXFA_FFDocView* pDocView,
409                                          CXFA_Validate* validate,
410                                          int32_t iFlags,
411                                          bool bVersionFlag);
412   WideString GetValidateCaptionName(bool bVersionFlag);
413   WideString GetValidateMessage(bool bError, bool bVersionFlag);
414 
415   bool HasFlag(XFA_NodeFlag dwFlag) const;
416   const PropertyData* GetPropertyData(XFA_Element property) const;
417   const AttributeData* GetAttributeData(XFA_Attribute attr) const;
418   Optional<XFA_Element> GetFirstPropertyWithFlag(uint8_t flag) const;
419   void OnRemoved(bool bNotify) const;
420   Optional<void*> GetDefaultValue(XFA_Attribute attr,
421                                   XFA_AttributeType eType) const;
422   CXFA_Node* GetChildInternal(size_t index,
423                               XFA_Element eType,
424                               bool bOnlyChild) const;
425   CXFA_Node* GetFirstChildByClassInternal(XFA_Element eType) const;
426   CXFA_Node* GetNextSameNameSiblingInternal(WideStringView wsNodeName) const;
427   CXFA_Node* GetNextSameClassSiblingInternal(XFA_Element eType) const;
428   void CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF* pszCap);
429   bool CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize);
430   bool CalculateWidgetAutoSize(CFX_SizeF* pSize);
431   bool CalculateTextEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize);
432   bool CalculateCheckButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize);
433   bool CalculatePushButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize);
434   CFX_SizeF CalculateImageSize(float img_width,
435                                float img_height,
436                                const CFX_Size& dpi);
437   bool CalculateImageEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize);
438   bool CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize);
439   float CalculateWidgetAutoHeight(float fHeightCalc);
440   float CalculateWidgetAutoWidth(float fWidthCalc);
441   float GetWidthWithoutMargin(float fWidthCalc) const;
442   float GetHeightWithoutMargin(float fHeightCalc) const;
443   void CalculateTextContentSize(CXFA_FFDoc* doc, CFX_SizeF* pSize);
444   CFX_SizeF CalculateAccWidthAndHeight(CXFA_FFDoc* doc, float fWidth);
445   void InitLayoutData();
446   void StartTextLayout(CXFA_FFDoc* doc, float* pCalcWidth, float* pCalcHeight);
447 
448   void InsertListTextItem(CXFA_Node* pItems,
449                           const WideString& wsText,
450                           int32_t nIndex);
451   WideString GetItemLabel(WideStringView wsValue) const;
452 
453   std::pair<XFA_FFWidgetType, CXFA_Ui*> CreateChildUIAndValueNodesIfNeeded();
454   void CreateValueNodeIfNeeded(CXFA_Value* value, CXFA_Node* pUIChild);
455   CXFA_Node* CreateUINodeIfNeeded(CXFA_Ui* ui, XFA_Element type);
456   bool IsValidInPacket(XFA_PacketType packet) const;
457   void SetImageEdit(const WideString& wsContentType,
458                     const WideString& wsHref,
459                     const WideString& wsData);
GetBindingNode()460   CXFA_Node* GetBindingNode() const {
461     if (binding_nodes_.empty())
462       return nullptr;
463     return binding_nodes_[0];
464   }
BindsFormItems()465   bool BindsFormItems() const { return HasFlag(XFA_NodeFlag_BindFormItems); }
NeedsInitApp()466   bool NeedsInitApp() const { return HasFlag(XFA_NodeFlag_NeedsInitApp); }
467   void SyncValue(const WideString& wsValue, bool bNotify);
468   CXFA_Value* GetDefaultValueIfExists();
469   CXFA_Bind* GetBindIfExists() const;
470   Optional<XFA_AttributeValue> GetIntactFromKeep(
471       const CXFA_Keep* pKeep,
472       XFA_AttributeValue eLayoutType) const;
473   CXFA_Node* GetTransparentParent();
474 
475   Optional<float> TryHeight();
476   Optional<float> TryMinWidth();
477   Optional<float> TryMinHeight();
478   Optional<float> TryMaxWidth();
479   Optional<float> TryMaxHeight();
480   XFA_EventError ProcessEventInternal(CXFA_FFDocView* pDocView,
481                                       XFA_AttributeValue iActivity,
482                                       CXFA_Event* event,
483                                       CXFA_EventParam* pEventParam);
484 
485   CFX_XMLDocument* GetXMLDocument() const;
486 
487   const pdfium::span<const PropertyData> m_Properties;
488   const pdfium::span<const AttributeData> m_Attributes;
489   const uint32_t m_ValidPackets;
490   UnownedPtr<CFX_XMLNode> xml_node_;
491   const XFA_PacketType m_ePacket;
492   uint8_t m_ExecuteRecursionDepth = 0;
493   uint16_t m_uNodeFlags = XFA_NodeFlag_None;
494   uint32_t m_dwNameHash = 0;
495   CXFA_Node* m_pAuxNode = nullptr;         // Raw, node tree cleanup order.
496   std::vector<CXFA_Node*> binding_nodes_;  // Raw, node tree cleanup order.
497   bool m_bIsNull = true;
498   bool m_bPreNull = true;
499   bool is_widget_ready_ = false;
500   std::unique_ptr<CXFA_WidgetLayoutData> m_pLayoutData;
501   CXFA_Ui* ui_ = nullptr;
502   XFA_FFWidgetType ff_widget_type_ = XFA_FFWidgetType::kNone;
503 };
504 
505 #endif  // XFA_FXFA_PARSER_CXFA_NODE_H_
506