OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "../../../core/include/fdrm/fx_crypt.h" | 7 #include "../../../core/include/fdrm/fx_crypt.h" |
8 #include "../../include/javascript/JavaScript.h" | 8 #include "../../include/javascript/JavaScript.h" |
9 #include "../../include/javascript/IJavaScript.h" | 9 #include "../../include/javascript/IJavaScript.h" |
10 #include "../../include/javascript/JS_GlobalData.h" | 10 #include "../../include/javascript/JS_GlobalData.h" |
11 | 11 |
12 #define JS_MAXGLOBALDATA» » » (1024 * 4 - 8) | 12 #define JS_MAXGLOBALDATA (1024 * 4 - 8) |
13 | 13 |
14 /* --------------------- CJS_GlobalVariableArray --------------------- */ | 14 /* --------------------- CJS_GlobalVariableArray --------------------- */ |
15 | 15 |
16 CJS_GlobalVariableArray::CJS_GlobalVariableArray() | 16 CJS_GlobalVariableArray::CJS_GlobalVariableArray() |
17 { | 17 { |
18 } | 18 } |
19 | 19 |
20 CJS_GlobalVariableArray::~CJS_GlobalVariableArray() | 20 CJS_GlobalVariableArray::~CJS_GlobalVariableArray() |
21 { | 21 { |
22 » Empty(); | 22 Empty(); |
23 } | 23 } |
24 | 24 |
25 void CJS_GlobalVariableArray::Copy(const CJS_GlobalVariableArray& array) | 25 void CJS_GlobalVariableArray::Copy(const CJS_GlobalVariableArray& array) |
26 { | 26 { |
27 » Empty(); | 27 Empty(); |
28 » for (int i=0,sz=array.Count(); i<sz; i++) | 28 for (int i=0,sz=array.Count(); i<sz; i++) |
29 » { | 29 { |
30 » » CJS_KeyValue* pOldObjData = array.GetAt(i); | 30 CJS_KeyValue* pOldObjData = array.GetAt(i); |
31 » » ASSERT(pOldObjData != NULL); | 31 ASSERT(pOldObjData != NULL); |
32 | 32 |
33 » » switch (pOldObjData->nType) | 33 switch (pOldObjData->nType) |
34 » » { | 34 { |
35 » » case JS_GLOBALDATA_TYPE_NUMBER: | 35 case JS_GLOBALDATA_TYPE_NUMBER: |
36 » » » { | 36 { |
37 » » » » CJS_KeyValue* pNewObjData = new CJS_KeyValue; | 37 CJS_KeyValue* pNewObjData = new CJS_KeyValue; |
38 » » » » pNewObjData->sKey = pOldObjData->sKey; | 38 pNewObjData->sKey = pOldObjData->sKey; |
39 » » » » pNewObjData->nType = pOldObjData->nType; | 39 pNewObjData->nType = pOldObjData->nType; |
40 » » » » pNewObjData->dData = pOldObjData->dData; | 40 pNewObjData->dData = pOldObjData->dData; |
41 » » » » Add(pNewObjData); | 41 Add(pNewObjData); |
42 » » » } | 42 } |
43 » » » break; | 43 break; |
44 » » case JS_GLOBALDATA_TYPE_BOOLEAN: | 44 case JS_GLOBALDATA_TYPE_BOOLEAN: |
45 » » » { | 45 { |
46 » » » » CJS_KeyValue* pNewObjData = new CJS_KeyValue; | 46 CJS_KeyValue* pNewObjData = new CJS_KeyValue; |
47 » » » » pNewObjData->sKey = pOldObjData->sKey; | 47 pNewObjData->sKey = pOldObjData->sKey; |
48 » » » » pNewObjData->nType = pOldObjData->nType; | 48 pNewObjData->nType = pOldObjData->nType; |
49 » » » » pNewObjData->bData = pOldObjData->bData; | 49 pNewObjData->bData = pOldObjData->bData; |
50 » » » » Add(pNewObjData); | 50 Add(pNewObjData); |
51 » » » } | 51 } |
52 » » » break; | 52 break; |
53 » » case JS_GLOBALDATA_TYPE_STRING: | 53 case JS_GLOBALDATA_TYPE_STRING: |
54 » » » { | 54 { |
55 » » » » CJS_KeyValue* pNewObjData = new CJS_KeyValue; | 55 CJS_KeyValue* pNewObjData = new CJS_KeyValue; |
56 » » » » pNewObjData->sKey = pOldObjData->sKey; | 56 pNewObjData->sKey = pOldObjData->sKey; |
57 » » » » pNewObjData->nType = pOldObjData->nType; | 57 pNewObjData->nType = pOldObjData->nType; |
58 » » » » pNewObjData->sData = pOldObjData->sData; | 58 pNewObjData->sData = pOldObjData->sData; |
59 » » » » Add(pNewObjData); | 59 Add(pNewObjData); |
60 » » » } | 60 } |
61 » » » break; | 61 break; |
62 » » case JS_GLOBALDATA_TYPE_OBJECT: | 62 case JS_GLOBALDATA_TYPE_OBJECT: |
63 » » » { | 63 { |
64 » » » » CJS_KeyValue* pNewObjData = new CJS_KeyValue; | 64 CJS_KeyValue* pNewObjData = new CJS_KeyValue; |
65 » » » » pNewObjData->sKey = pOldObjData->sKey; | 65 pNewObjData->sKey = pOldObjData->sKey; |
66 » » » » pNewObjData->nType = pOldObjData->nType; | 66 pNewObjData->nType = pOldObjData->nType; |
67 » » » » pNewObjData->objData.Copy(pOldObjData->objData); | 67 pNewObjData->objData.Copy(pOldObjData->objData); |
68 » » » » Add(pNewObjData); | 68 Add(pNewObjData); |
69 » » » } | 69 } |
70 » » case JS_GLOBALDATA_TYPE_NULL: | 70 case JS_GLOBALDATA_TYPE_NULL: |
71 » » » { | 71 { |
72 » » » » CJS_KeyValue* pNewObjData = new CJS_KeyValue; | 72 CJS_KeyValue* pNewObjData = new CJS_KeyValue; |
73 » » » » pNewObjData->sKey = pOldObjData->sKey; | 73 pNewObjData->sKey = pOldObjData->sKey; |
74 » » » » pNewObjData->nType = pOldObjData->nType; | 74 pNewObjData->nType = pOldObjData->nType; |
75 » » » » Add(pNewObjData); | 75 Add(pNewObjData); |
76 » » » } | 76 } |
77 » » } | 77 } |
78 » } | 78 } |
79 } | 79 } |
80 | 80 |
81 void CJS_GlobalVariableArray::Add(CJS_KeyValue* p) | 81 void CJS_GlobalVariableArray::Add(CJS_KeyValue* p) |
82 { | 82 { |
83 » array.Add(p); | 83 array.Add(p); |
84 } | 84 } |
85 | 85 |
86 int CJS_GlobalVariableArray::Count() const | 86 int CJS_GlobalVariableArray::Count() const |
87 { | 87 { |
88 » return array.GetSize(); | 88 return array.GetSize(); |
89 } | 89 } |
90 | 90 |
91 CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const | 91 CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const |
92 { | 92 { |
93 » return array.GetAt(index); | 93 return array.GetAt(index); |
94 } | 94 } |
95 | 95 |
96 void CJS_GlobalVariableArray::Empty() | 96 void CJS_GlobalVariableArray::Empty() |
97 { | 97 { |
98 » for (int i=0,sz=array.GetSize(); i<sz; i++) | 98 for (int i=0,sz=array.GetSize(); i<sz; i++) |
99 » » delete array.GetAt(i); | 99 delete array.GetAt(i); |
100 » array.RemoveAll(); | 100 array.RemoveAll(); |
101 } | 101 } |
102 | 102 |
103 /* -------------------------- CJS_GlobalData -------------------------- */ | 103 /* -------------------------- CJS_GlobalData -------------------------- */ |
104 | 104 |
105 #define READER_JS_GLOBALDATA_FILENAME» » » » L"Reader_JsGloba
l.Data" | 105 #define READER_JS_GLOBALDATA_FILENAME L"Reader_JsGlobal.Data" |
106 #define PHANTOM_JS_GLOBALDATA_FILENAME» » » » L"Phantom_JsGlob
al.Data" | 106 #define PHANTOM_JS_GLOBALDATA_FILENAME L"Phantom_JsGlobal.Data" |
107 #define SDK_JS_GLOBALDATA_FILENAME» » » » » L"SDK_Js
Global.Data" | 107 #define SDK_JS_GLOBALDATA_FILENAME L"SDK_JsGlobal.Data" |
108 | 108 |
109 static const uint8_t JS_RC4KEY[] = {0x19,0xa8,0xe8,0x01,0xf6,0xa8,0xb6,0x4d,0x82
,0x04, | 109 static const uint8_t JS_RC4KEY[] = {0x19,0xa8,0xe8,0x01,0xf6,0xa8,0xb6,0x4d,0x82
,0x04, |
110 » » » » » » » 0x45,0x6d,0xb4,0xcf,0xd7
,0x77,0x67,0xf9,0x75,0x9f, | 110 0x45,0x6d,0xb4,0xcf,0xd7,0x77,0x67,0xf9,0x75,0x9f, |
111 » » » » » » » 0xf0,0xe0,0x1e,0x51,0xee
,0x46,0xfd,0x0b,0xc9,0x93, | 111 0xf0,0xe0,0x1e,0x51,0xee,0x46,0xfd,0x0b,0xc9,0x93, |
112 » » » » » » » 0x25,0x55,0x4a,0xee,0xe0
,0x16,0xd0,0xdf,0x8c,0xfa, | 112 0x25,0x55,0x4a,0xee,0xe0,0x16,0xd0,0xdf,0x8c,0xfa, |
113 » » » » » » » 0x2a,0xa9,0x49,0xfd,0x97
,0x1c,0x0e,0x22,0x13,0x28, | 113 0x2a,0xa9,0x49,0xfd,0x97,0x1c,0x0e,0x22,0x13,0x28, |
114 » » » » » » » 0x7c,0xaf,0xc4,0xfc,0x9c
,0x12,0x65,0x8c,0x4e,0x5b, | 114 0x7c,0xaf,0xc4,0xfc,0x9c,0x12,0x65,0x8c,0x4e,0x5b, |
115 » » » » » » » 0x04,0x75,0x89,0xc9,0xb1
,0xed,0x50,0xca,0x96,0x6f, | 115 0x04,0x75,0x89,0xc9,0xb1,0xed,0x50,0xca,0x96,0x6f, |
116 » » » » » » » 0x1a,0x7a,0xfe,0x58,0x5d
,0xec,0x19,0x4a,0xf6,0x35, | 116 0x1a,0x7a,0xfe,0x58,0x5d,0xec,0x19,0x4a,0xf6,0x35, |
117 » » » » » » » 0x6a,0x97,0x14,0x00,0x0e
,0xd0,0x6b,0xbb,0xd5,0x75, | 117 0x6a,0x97,0x14,0x00,0x0e,0xd0,0x6b,0xbb,0xd5,0x75, |
118 » » » » » » » 0x55,0x8b,0x6e,0x6b,0x19
,0xa0,0xf8,0x77,0xd5,0xa3 | 118 0x55,0x8b,0x6e,0x6b,0x19,0xa0,0xf8,0x77,0xd5,0xa3 |
119 » » » » » » » }; | 119 }; |
120 | 120 |
121 CJS_GlobalData::CJS_GlobalData(CPDFDoc_Environment* pApp) : m_pApp(pApp) | 121 CJS_GlobalData::CJS_GlobalData(CPDFDoc_Environment* pApp) : m_pApp(pApp) |
122 { | 122 { |
123 // » IBaseAnnot* pBaseAnnot = IBaseAnnot::GetBaseAnnot(m_pApp); | 123 // IBaseAnnot* pBaseAnnot = IBaseAnnot::GetBaseAnnot(m_pApp); |
124 // » ASSERT(pBaseAnnot != NULL); | 124 // ASSERT(pBaseAnnot != NULL); |
125 // | 125 // |
126 // » m_sFilePath = pBaseAnnot->GetUserPath(); | 126 // m_sFilePath = pBaseAnnot->GetUserPath(); |
127 » m_sFilePath += SDK_JS_GLOBALDATA_FILENAME; | 127 m_sFilePath += SDK_JS_GLOBALDATA_FILENAME; |
128 | 128 |
129 » LoadGlobalPersistentVariables(); | 129 LoadGlobalPersistentVariables(); |
130 } | 130 } |
131 | 131 |
132 CJS_GlobalData::~CJS_GlobalData() | 132 CJS_GlobalData::~CJS_GlobalData() |
133 { | 133 { |
134 » SaveGlobalPersisitentVariables(); | 134 SaveGlobalPersisitentVariables(); |
135 | 135 |
136 » for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++) | 136 for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++) |
137 » » delete m_arrayGlobalData.GetAt(i); | 137 delete m_arrayGlobalData.GetAt(i); |
138 | 138 |
139 » m_arrayGlobalData.RemoveAll(); | 139 m_arrayGlobalData.RemoveAll(); |
140 } | 140 } |
141 | 141 |
142 int» CJS_GlobalData::FindGlobalVariable(const FX_CHAR* propname) | 142 int CJS_GlobalData::FindGlobalVariable(const FX_CHAR* propname) |
143 { | 143 { |
144 » ASSERT(propname != NULL); | 144 ASSERT(propname != NULL); |
145 | 145 |
146 » int nRet = -1; | 146 int nRet = -1; |
147 | 147 |
148 » for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++) | 148 for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++) |
149 » { | 149 { |
150 » » CJS_GlobalData_Element* pTemp = m_arrayGlobalData.GetAt(i); | 150 CJS_GlobalData_Element* pTemp = m_arrayGlobalData.GetAt(i); |
151 » » if (pTemp->data.sKey[0] == *propname && pTemp->data.sKey == prop
name) | 151 if (pTemp->data.sKey[0] == *propname && pTemp->data.sKey == propname) |
152 » » { | 152 { |
153 » » » nRet = i; | 153 nRet = i; |
154 » » » break; | 154 break; |
155 » » } | 155 } |
156 » } | 156 } |
157 | 157 |
158 » return nRet; | 158 return nRet; |
159 } | 159 } |
160 | 160 |
161 CJS_GlobalData_Element* CJS_GlobalData::GetGlobalVariable(const FX_CHAR* propnam
e) | 161 CJS_GlobalData_Element* CJS_GlobalData::GetGlobalVariable(const FX_CHAR* propnam
e) |
162 { | 162 { |
163 » ASSERT(propname != NULL); | 163 ASSERT(propname != NULL); |
164 | 164 |
165 » int» nFind = FindGlobalVariable(propname); | 165 int nFind = FindGlobalVariable(propname); |
166 | 166 if (nFind >= 0) |
167 » if (nFind >= 0) | 167 return m_arrayGlobalData.GetAt(nFind); |
168 » » return m_arrayGlobalData.GetAt(nFind); | 168 |
169 » else | 169 return NULL; |
170 » » return NULL; | |
171 } | 170 } |
172 | 171 |
173 void CJS_GlobalData::SetGlobalVariableNumber(const FX_CHAR* propname, double dDa
ta) | 172 void CJS_GlobalData::SetGlobalVariableNumber(const FX_CHAR* propname, double dDa
ta) |
174 { | 173 { |
175 » ASSERT(propname != NULL); | 174 ASSERT(propname != NULL); |
176 » CFX_ByteString sPropName = propname; | 175 |
177 | 176 CFX_ByteString sPropName = propname; |
178 » sPropName.TrimLeft(); | 177 sPropName.TrimLeft(); |
179 » sPropName.TrimRight(); | 178 sPropName.TrimRight(); |
180 | 179 if (sPropName.GetLength() == 0) |
181 » if (sPropName.GetLength() == 0) return; | 180 return; |
182 | 181 |
183 » if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) | 182 if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) |
184 » { | 183 { |
185 » » pData->data.nType = JS_GLOBALDATA_TYPE_NUMBER; | 184 pData->data.nType = JS_GLOBALDATA_TYPE_NUMBER; |
186 » » pData->data.dData = dData; | 185 pData->data.dData = dData; |
187 » } | 186 } |
188 » else | 187 else |
189 » { | 188 { |
190 » » CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; | 189 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; |
191 » » pNewData->data.sKey = sPropName; | 190 pNewData->data.sKey = sPropName; |
192 » » pNewData->data.nType = JS_GLOBALDATA_TYPE_NUMBER; | 191 pNewData->data.nType = JS_GLOBALDATA_TYPE_NUMBER; |
193 » » pNewData->data.dData = dData; | 192 pNewData->data.dData = dData; |
194 | 193 m_arrayGlobalData.Add(pNewData); |
195 » » m_arrayGlobalData.Add(pNewData); | 194 } |
196 » } | |
197 } | 195 } |
198 | 196 |
199 void CJS_GlobalData::SetGlobalVariableBoolean(const FX_CHAR* propname, bool bDat
a) | 197 void CJS_GlobalData::SetGlobalVariableBoolean(const FX_CHAR* propname, bool bDat
a) |
200 { | 198 { |
201 » ASSERT(propname != NULL); | 199 ASSERT(propname != NULL); |
202 » CFX_ByteString sPropName = propname; | 200 CFX_ByteString sPropName = propname; |
203 | 201 |
204 » sPropName.TrimLeft(); | 202 sPropName.TrimLeft(); |
205 » sPropName.TrimRight(); | 203 sPropName.TrimRight(); |
206 | 204 |
207 » if (sPropName.GetLength() == 0) return; | 205 if (sPropName.GetLength() == 0) return; |
208 | 206 |
209 » if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) | 207 if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) |
210 » { | 208 { |
211 » » pData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN; | 209 pData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN; |
212 » » pData->data.bData = bData; | 210 pData->data.bData = bData; |
213 » } | 211 } |
214 » else | 212 else |
215 » { | 213 { |
216 » » CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; | 214 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; |
217 » » pNewData->data.sKey = sPropName; | 215 pNewData->data.sKey = sPropName; |
218 » » pNewData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN; | 216 pNewData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN; |
219 » » pNewData->data.bData = bData; | 217 pNewData->data.bData = bData; |
220 | 218 |
221 » » m_arrayGlobalData.Add(pNewData); | 219 m_arrayGlobalData.Add(pNewData); |
222 » } | 220 } |
223 } | 221 } |
224 | 222 |
225 void CJS_GlobalData::SetGlobalVariableString(const FX_CHAR* propname, const CFX_
ByteString& sData) | 223 void CJS_GlobalData::SetGlobalVariableString(const FX_CHAR* propname, const CFX_
ByteString& sData) |
226 { | 224 { |
227 » ASSERT(propname != NULL); | 225 ASSERT(propname != NULL); |
228 » CFX_ByteString sPropName = propname; | 226 CFX_ByteString sPropName = propname; |
229 | 227 |
230 » sPropName.TrimLeft(); | 228 sPropName.TrimLeft(); |
231 » sPropName.TrimRight(); | 229 sPropName.TrimRight(); |
232 | 230 |
233 » if (sPropName.GetLength() == 0) return; | 231 if (sPropName.GetLength() == 0) return; |
234 | 232 |
235 » if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) | 233 if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) |
236 » { | 234 { |
237 » » pData->data.nType = JS_GLOBALDATA_TYPE_STRING; | 235 pData->data.nType = JS_GLOBALDATA_TYPE_STRING; |
238 » » pData->data.sData = sData; | 236 pData->data.sData = sData; |
239 » } | 237 } |
240 » else | 238 else |
241 » { | 239 { |
242 » » CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; | 240 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; |
243 » » pNewData->data.sKey = sPropName; | 241 pNewData->data.sKey = sPropName; |
244 » » pNewData->data.nType = JS_GLOBALDATA_TYPE_STRING; | 242 pNewData->data.nType = JS_GLOBALDATA_TYPE_STRING; |
245 » » pNewData->data.sData = sData; | 243 pNewData->data.sData = sData; |
246 | 244 |
247 » » m_arrayGlobalData.Add(pNewData); | 245 m_arrayGlobalData.Add(pNewData); |
248 » } | 246 } |
249 } | 247 } |
250 | 248 |
251 void CJS_GlobalData::SetGlobalVariableObject(const FX_CHAR* propname, const CJS_
GlobalVariableArray& array) | 249 void CJS_GlobalData::SetGlobalVariableObject(const FX_CHAR* propname, const CJS_
GlobalVariableArray& array) |
252 { | 250 { |
253 » ASSERT(propname != NULL); | 251 ASSERT(propname != NULL); |
254 » CFX_ByteString sPropName = propname; | 252 CFX_ByteString sPropName = propname; |
255 | 253 |
256 » sPropName.TrimLeft(); | 254 sPropName.TrimLeft(); |
257 » sPropName.TrimRight(); | 255 sPropName.TrimRight(); |
258 | 256 |
259 » if (sPropName.GetLength() == 0) return; | 257 if (sPropName.GetLength() == 0) return; |
260 | 258 |
261 » if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) | 259 if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) |
262 » { | 260 { |
263 » » pData->data.nType = JS_GLOBALDATA_TYPE_OBJECT; | 261 pData->data.nType = JS_GLOBALDATA_TYPE_OBJECT; |
264 » » pData->data.objData.Copy(array); | 262 pData->data.objData.Copy(array); |
265 » } | 263 } |
266 » else | 264 else |
267 » { | 265 { |
268 » » CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; | 266 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; |
269 » » pNewData->data.sKey = sPropName; | 267 pNewData->data.sKey = sPropName; |
270 » » pNewData->data.nType = JS_GLOBALDATA_TYPE_OBJECT; | 268 pNewData->data.nType = JS_GLOBALDATA_TYPE_OBJECT; |
271 » » pNewData->data.objData.Copy(array); | 269 pNewData->data.objData.Copy(array); |
272 | 270 |
273 » » m_arrayGlobalData.Add(pNewData); | 271 m_arrayGlobalData.Add(pNewData); |
274 » } | 272 } |
275 } | 273 } |
276 | 274 |
277 void CJS_GlobalData::SetGlobalVariableNull(const FX_CHAR* propname) | 275 void CJS_GlobalData::SetGlobalVariableNull(const FX_CHAR* propname) |
278 { | 276 { |
279 » ASSERT(propname != NULL); | 277 ASSERT(propname != NULL); |
280 » CFX_ByteString sPropName = propname; | 278 CFX_ByteString sPropName = propname; |
281 | 279 |
282 » sPropName.TrimLeft(); | 280 sPropName.TrimLeft(); |
283 » sPropName.TrimRight(); | 281 sPropName.TrimRight(); |
284 | 282 |
285 » if (sPropName.GetLength() == 0) return; | 283 if (sPropName.GetLength() == 0) return; |
286 | 284 |
287 » if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) | 285 if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) |
288 » { | 286 { |
289 » » pData->data.nType = JS_GLOBALDATA_TYPE_NULL; | 287 pData->data.nType = JS_GLOBALDATA_TYPE_NULL; |
290 » } | 288 } |
291 » else | 289 else |
292 » { | 290 { |
293 » » CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; | 291 CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element; |
294 » » pNewData->data.sKey = sPropName; | 292 pNewData->data.sKey = sPropName; |
295 » » pNewData->data.nType = JS_GLOBALDATA_TYPE_NULL; | 293 pNewData->data.nType = JS_GLOBALDATA_TYPE_NULL; |
296 | 294 |
297 » » m_arrayGlobalData.Add(pNewData); | 295 m_arrayGlobalData.Add(pNewData); |
298 » } | 296 } |
299 } | 297 } |
300 | 298 |
301 FX_BOOL CJS_GlobalData::SetGlobalVariablePersistent(const FX_CHAR* propname, FX_
BOOL bPersistent) | 299 FX_BOOL CJS_GlobalData::SetGlobalVariablePersistent(const FX_CHAR* propname, FX_
BOOL bPersistent) |
302 { | 300 { |
303 » ASSERT(propname != NULL); | 301 ASSERT(propname != NULL); |
304 » CFX_ByteString sPropName = propname; | 302 CFX_ByteString sPropName = propname; |
305 | 303 |
306 » sPropName.TrimLeft(); | 304 sPropName.TrimLeft(); |
307 » sPropName.TrimRight(); | 305 sPropName.TrimRight(); |
308 | 306 |
309 » if (sPropName.GetLength() == 0) return FALSE; | 307 if (sPropName.GetLength() == 0) return FALSE; |
310 | 308 |
311 » if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) | 309 if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) |
312 » { | 310 { |
313 » » pData->bPersistent = bPersistent; | 311 pData->bPersistent = bPersistent; |
314 » » return TRUE; | 312 return TRUE; |
315 » } | 313 } |
316 | 314 |
317 » return FALSE; | 315 return FALSE; |
318 } | 316 } |
319 | 317 |
320 FX_BOOL CJS_GlobalData::DeleteGlobalVariable(const FX_CHAR* propname) | 318 FX_BOOL CJS_GlobalData::DeleteGlobalVariable(const FX_CHAR* propname) |
321 { | 319 { |
322 » ASSERT(propname != NULL); | 320 ASSERT(propname != NULL); |
323 » CFX_ByteString sPropName = propname; | 321 CFX_ByteString sPropName = propname; |
324 | 322 |
325 » sPropName.TrimLeft(); | 323 sPropName.TrimLeft(); |
326 » sPropName.TrimRight(); | 324 sPropName.TrimRight(); |
327 | 325 |
328 » if (sPropName.GetLength() == 0) return FALSE; | 326 if (sPropName.GetLength() == 0) return FALSE; |
329 | 327 |
330 » int» nFind = FindGlobalVariable(sPropName); | 328 int nFind = FindGlobalVariable(sPropName); |
331 | 329 |
332 » if (nFind >= 0) | 330 if (nFind >= 0) |
333 » { | 331 { |
334 » » delete m_arrayGlobalData.GetAt(nFind); | 332 delete m_arrayGlobalData.GetAt(nFind); |
335 » » m_arrayGlobalData.RemoveAt(nFind); | 333 m_arrayGlobalData.RemoveAt(nFind); |
336 » » return TRUE; | 334 return TRUE; |
337 » } | 335 } |
338 | 336 |
339 » return FALSE; | 337 return FALSE; |
340 } | 338 } |
341 | 339 |
342 int32_t CJS_GlobalData::GetSize() const | 340 int32_t CJS_GlobalData::GetSize() const |
343 { | 341 { |
344 » return m_arrayGlobalData.GetSize(); | 342 return m_arrayGlobalData.GetSize(); |
345 } | 343 } |
346 | 344 |
347 CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const | 345 CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const |
348 { | 346 { |
349 » return m_arrayGlobalData.GetAt(index); | 347 return m_arrayGlobalData.GetAt(index); |
350 } | 348 } |
351 | 349 |
352 void CJS_GlobalData::LoadGlobalPersistentVariables() | 350 void CJS_GlobalData::LoadGlobalPersistentVariables() |
353 { | 351 { |
354 » uint8_t* pBuffer = NULL; | 352 uint8_t* pBuffer = NULL; |
355 » int32_t nLength = 0; | 353 int32_t nLength = 0; |
356 | 354 |
357 » LoadFileBuffer(m_sFilePath.c_str(), pBuffer, nLength); | 355 LoadFileBuffer(m_sFilePath.c_str(), pBuffer, nLength); |
358 » CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY)); | 356 CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY)); |
359 | 357 |
360 » if (pBuffer) | 358 if (pBuffer) |
361 » { | 359 { |
362 » » uint8_t* p = pBuffer; | 360 uint8_t* p = pBuffer; |
363 » » FX_WORD wType = *((FX_WORD*)p); | 361 FX_WORD wType = *((FX_WORD*)p); |
364 » » p += sizeof(FX_WORD); | 362 p += sizeof(FX_WORD); |
365 | 363 |
366 » » //FX_WORD wTemp = (FX_WORD)(('X' << 8) | 'F'); | 364 //FX_WORD wTemp = (FX_WORD)(('X' << 8) | 'F'); |
367 | 365 |
368 » » if (wType == (FX_WORD)(('X' << 8) | 'F')) | 366 if (wType == (FX_WORD)(('X' << 8) | 'F')) |
369 » » { | 367 { |
370 » » » FX_WORD wVersion = *((FX_WORD*)p); | 368 FX_WORD wVersion = *((FX_WORD*)p); |
371 » » » p += sizeof(FX_WORD); | 369 p += sizeof(FX_WORD); |
372 | 370 |
373 » » » ASSERT(wVersion <= 2); | 371 ASSERT(wVersion <= 2); |
374 | 372 |
375 » » » FX_DWORD dwCount = *((FX_DWORD*)p); | 373 FX_DWORD dwCount = *((FX_DWORD*)p); |
376 » » » p += sizeof(FX_DWORD); | 374 p += sizeof(FX_DWORD); |
377 | 375 |
378 » » » FX_DWORD dwSize = *((FX_DWORD*)p); | 376 FX_DWORD dwSize = *((FX_DWORD*)p); |
379 » » » p += sizeof(FX_DWORD); | 377 p += sizeof(FX_DWORD); |
380 | 378 |
381 » » » if (dwSize == nLength - sizeof(FX_WORD) * 2 - sizeof(FX_
DWORD)* 2) | 379 if (dwSize == nLength - sizeof(FX_WORD) * 2 - sizeof(FX_DWORD)* 2) |
382 » » » { | 380 { |
383 » » » » for (int32_t i=0,sz=dwCount; i<sz; i++) | 381 for (int32_t i=0,sz=dwCount; i<sz; i++) |
384 » » » » { | 382 { |
385 » » » » » if (p > pBuffer + nLength) | 383 if (p > pBuffer + nLength) |
386 » » » » » » break; | 384 break; |
387 | 385 |
388 » » » » » FX_DWORD dwNameLen = *((FX_DWORD*)p); | 386 FX_DWORD dwNameLen = *((FX_DWORD*)p); |
389 » » » » » p += sizeof(FX_DWORD); | 387 p += sizeof(FX_DWORD); |
390 | 388 |
391 » » » » » if (p + dwNameLen > pBuffer + nLength) | 389 if (p + dwNameLen > pBuffer + nLength) |
392 » » » » » » break; | 390 break; |
393 | 391 |
394 » » » » » CFX_ByteString sEntry = CFX_ByteString(p
, dwNameLen); | 392 CFX_ByteString sEntry = CFX_ByteString(p, dwNameLen); |
395 » » » » » p += sizeof(char) * dwNameLen; | 393 p += sizeof(char) * dwNameLen; |
396 | 394 |
397 » » » » » FX_WORD wDataType = *((FX_WORD*)p); | 395 FX_WORD wDataType = *((FX_WORD*)p); |
398 » » » » » p += sizeof(FX_WORD); | 396 p += sizeof(FX_WORD); |
399 | 397 |
400 » » » » » switch (wDataType) | 398 switch (wDataType) |
401 » » » » » { | 399 { |
402 » » » » » case JS_GLOBALDATA_TYPE_NUMBER: | 400 case JS_GLOBALDATA_TYPE_NUMBER: |
403 » » » » » » { | 401 { |
404 » » » » » » » double dData = 0; | 402 double dData = 0; |
405 » » » » » » » switch (wVersion) | 403 switch (wVersion) |
406 » » » » » » » { | 404 { |
407 » » » » » » » case 1: | 405 case 1: |
408 » » » » » » » » { | 406 { |
409 » » » » » » » » » FX_DWORD
dwData = *((FX_DWORD*)p); | 407 FX_DWORD dwData = *((FX_DWORD*)p); |
410 » » » » » » » » » p += siz
eof(FX_DWORD); | 408 p += sizeof(FX_DWORD); |
411 » » » » » » » » » dData =
dwData; | 409 dData = dwData; |
412 » » » » » » » » } | 410 } |
413 » » » » » » » » break; | 411 break; |
414 » » » » » » » case 2: | 412 case 2: |
415 » » » » » » » » { | 413 { |
416 » » » » » » » » » dData =
*((double*)p); | 414 dData = *((double*)p); |
417 » » » » » » » » » p += siz
eof(double); | 415 p += sizeof(double); |
418 » » » » » » » » } | 416 } |
419 » » » » » » » » break; | 417 break; |
420 » » » » » » » } | 418 } |
421 » » » » » » » SetGlobalVariableNumber(
sEntry, dData); | 419 SetGlobalVariableNumber(sEntry, dData); |
422 » » » » » » » SetGlobalVariablePersist
ent(sEntry, TRUE); | 420 SetGlobalVariablePersistent(sEntry, TRUE); |
423 » » » » » » } | 421 } |
424 » » » » » » break; | 422 break; |
425 » » » » » case JS_GLOBALDATA_TYPE_BOOLEAN: | 423 case JS_GLOBALDATA_TYPE_BOOLEAN: |
426 » » » » » » { | 424 { |
427 » » » » » » » FX_WORD wData = *((FX_WO
RD*)p); | 425 FX_WORD wData = *((FX_WORD*)p); |
428 » » » » » » » p += sizeof(FX_WORD); | 426 p += sizeof(FX_WORD); |
429 » » » » » » » SetGlobalVariableBoolean
(sEntry, (bool)(wData == 1)); | 427 SetGlobalVariableBoolean(sEntry, (bool)(wData == 1))
; |
430 » » » » » » » SetGlobalVariablePersist
ent(sEntry, TRUE); | 428 SetGlobalVariablePersistent(sEntry, TRUE); |
431 » » » » » » } | 429 } |
432 » » » » » » break; | 430 break; |
433 » » » » » case JS_GLOBALDATA_TYPE_STRING: | 431 case JS_GLOBALDATA_TYPE_STRING: |
434 » » » » » » { | 432 { |
435 » » » » » » » FX_DWORD dwLength = *((F
X_DWORD*)p); | 433 FX_DWORD dwLength = *((FX_DWORD*)p); |
436 » » » » » » » p += sizeof(FX_DWORD); | 434 p += sizeof(FX_DWORD); |
437 | 435 |
438 » » » » » » » if (p + dwLength > pBuff
er + nLength) | 436 if (p + dwLength > pBuffer + nLength) |
439 » » » » » » » » break; | 437 break; |
440 | 438 |
441 » » » » » » » SetGlobalVariableString(
sEntry, CFX_ByteString(p, dwLength)); | 439 SetGlobalVariableString(sEntry, CFX_ByteString(p, dw
Length)); |
442 » » » » » » » SetGlobalVariablePersist
ent(sEntry, TRUE); | 440 SetGlobalVariablePersistent(sEntry, TRUE); |
443 » » » » » » » p += sizeof(char) * dwLe
ngth; | 441 p += sizeof(char) * dwLength; |
444 » » » » » » } | 442 } |
445 » » » » » » break; | 443 break; |
446 » » » » » case JS_GLOBALDATA_TYPE_NULL: | 444 case JS_GLOBALDATA_TYPE_NULL: |
447 » » » » » » { | 445 { |
448 » » » » » » » SetGlobalVariableNull(sE
ntry); | 446 SetGlobalVariableNull(sEntry); |
449 » » » » » » » SetGlobalVariablePersist
ent(sEntry, TRUE); | 447 SetGlobalVariablePersistent(sEntry, TRUE); |
450 » » » » » » } | 448 } |
451 » » » » » } | 449 } |
452 » » » » } | 450 } |
453 » » » } | 451 } |
454 » » } | 452 } |
455 » » FX_Free(pBuffer); | 453 FX_Free(pBuffer); |
456 » } | 454 } |
457 } | 455 } |
458 | 456 |
459 /* | 457 /* |
460 struct js_global_datafile_header | 458 struct js_global_datafile_header |
461 { | 459 { |
462 » FX_WORD type; //FX ('X' << 8) | 'F' | 460 FX_WORD type; //FX ('X' << 8) | 'F' |
463 » FX_WORD version; //1.0 | 461 FX_WORD version; //1.0 |
464 » FX_DWORD datacount; | 462 FX_DWORD datacount; |
465 }; | 463 }; |
466 struct js_global_datafile_data | 464 struct js_global_datafile_data |
467 { | 465 { |
468 » FX_WORD type; | 466 FX_WORD type; |
469 » FX_DWORD nData; | 467 FX_DWORD nData; |
470 » FX_WORD bData; | 468 FX_WORD bData; |
471 » FX_DWORD nStrLen; | 469 FX_DWORD nStrLen; |
472 » char* pStr; | 470 char* pStr; |
473 }; | 471 }; |
474 */ | 472 */ |
475 | 473 |
476 void CJS_GlobalData::SaveGlobalPersisitentVariables() | 474 void CJS_GlobalData::SaveGlobalPersisitentVariables() |
477 { | 475 { |
478 » FX_DWORD nCount = 0; | 476 FX_DWORD nCount = 0; |
479 » CFX_BinaryBuf sData; | 477 CFX_BinaryBuf sData; |
480 | 478 |
481 » for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++) | 479 for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++) |
482 » { | 480 { |
483 » » CJS_GlobalData_Element* pElement = m_arrayGlobalData.GetAt(i); | 481 CJS_GlobalData_Element* pElement = m_arrayGlobalData.GetAt(i); |
484 » » ASSERT(pElement != NULL); | 482 ASSERT(pElement != NULL); |
485 | 483 |
486 » » if (pElement->bPersistent) | 484 if (pElement->bPersistent) |
487 » » { | 485 { |
488 » » » CFX_BinaryBuf sElement; | 486 CFX_BinaryBuf sElement; |
489 » » » MakeByteString(pElement->data.sKey, &pElement->data, sEl
ement); | 487 MakeByteString(pElement->data.sKey, &pElement->data, sElement); |
490 | 488 |
491 » » » if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALD
ATA) | 489 if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALDATA) |
492 » » » » break; | 490 break; |
493 | 491 |
494 » » » sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize
()); | 492 sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize()); |
495 » » » nCount++; | 493 nCount++; |
496 » » } | 494 } |
497 » } | 495 } |
498 | 496 |
499 » CFX_BinaryBuf sFile; | 497 CFX_BinaryBuf sFile; |
500 | 498 |
501 » FX_WORD wType = (FX_WORD)(('X' << 8) | 'F'); | 499 FX_WORD wType = (FX_WORD)(('X' << 8) | 'F'); |
502 » sFile.AppendBlock(&wType, sizeof(FX_WORD)); | 500 sFile.AppendBlock(&wType, sizeof(FX_WORD)); |
503 » FX_WORD wVersion = 2; | 501 FX_WORD wVersion = 2; |
504 » sFile.AppendBlock(&wVersion, sizeof(FX_WORD)); | 502 sFile.AppendBlock(&wVersion, sizeof(FX_WORD)); |
505 » sFile.AppendBlock(&nCount, sizeof(FX_DWORD)); | 503 sFile.AppendBlock(&nCount, sizeof(FX_DWORD)); |
506 » FX_DWORD dwSize = sData.GetSize(); | 504 FX_DWORD dwSize = sData.GetSize(); |
507 » sFile.AppendBlock(&dwSize, sizeof(FX_DWORD)); | 505 sFile.AppendBlock(&dwSize, sizeof(FX_DWORD)); |
508 | 506 |
509 » sFile.AppendBlock(sData.GetBuffer(), sData.GetSize()); | 507 sFile.AppendBlock(sData.GetBuffer(), sData.GetSize()); |
510 | 508 |
511 » CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY, s
izeof(JS_RC4KEY)); | 509 CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY, sizeo
f(JS_RC4KEY)); |
512 » WriteFileBuffer(m_sFilePath.c_str(), (const FX_CHAR*)sFile.GetBuffer(),
sFile.GetSize()); | 510 WriteFileBuffer(m_sFilePath.c_str(), (const FX_CHAR*)sFile.GetBuffer(), sFil
e.GetSize()); |
513 } | 511 } |
514 | 512 |
515 void CJS_GlobalData::LoadFileBuffer(const FX_WCHAR* sFilePath, uint8_t*& pBuffer
, int32_t& nLength) | 513 void CJS_GlobalData::LoadFileBuffer(const FX_WCHAR* sFilePath, uint8_t*& pBuffer
, int32_t& nLength) |
516 { | 514 { |
517 //UnSupport. | 515 //UnSupport. |
518 } | 516 } |
519 | 517 |
520 void CJS_GlobalData::WriteFileBuffer(const FX_WCHAR* sFilePath, const FX_CHAR* p
Buffer, int32_t nLength) | 518 void CJS_GlobalData::WriteFileBuffer(const FX_WCHAR* sFilePath, const FX_CHAR* p
Buffer, int32_t nLength) |
521 { | 519 { |
522 //UnSupport. | 520 //UnSupport. |
523 } | 521 } |
524 | 522 |
525 void CJS_GlobalData::MakeByteString(const CFX_ByteString& name, CJS_KeyValue* pD
ata, CFX_BinaryBuf& sData) | 523 void CJS_GlobalData::MakeByteString(const CFX_ByteString& name, CJS_KeyValue* pD
ata, CFX_BinaryBuf& sData) |
526 { | 524 { |
527 » ASSERT(pData != NULL); | 525 FX_WORD wType = (FX_WORD)pData->nType; |
| 526 switch (wType) |
| 527 { |
| 528 case JS_GLOBALDATA_TYPE_NUMBER: |
| 529 { |
| 530 FX_DWORD dwNameLen = (FX_DWORD)name.GetLength(); |
| 531 sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD)); |
| 532 sData.AppendString(name); |
| 533 sData.AppendBlock(&wType, sizeof(FX_WORD)); |
528 | 534 |
529 » FX_WORD wType = (FX_WORD)pData->nType; | 535 double dData = pData->dData; |
| 536 sData.AppendBlock(&dData, sizeof(double)); |
| 537 } |
| 538 break; |
| 539 case JS_GLOBALDATA_TYPE_BOOLEAN: |
| 540 { |
| 541 FX_DWORD dwNameLen = (FX_DWORD)name.GetLength(); |
| 542 sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD)); |
| 543 sData.AppendString(name); |
| 544 sData.AppendBlock(&wType, sizeof(FX_WORD)); |
530 | 545 |
531 » switch (wType) | 546 FX_WORD wData = (FX_WORD)pData->bData; |
532 » { | 547 sData.AppendBlock(&wData, sizeof(FX_WORD)); |
533 » case JS_GLOBALDATA_TYPE_NUMBER: | 548 } |
534 » » { | 549 break; |
535 » » » FX_DWORD dwNameLen = (FX_DWORD)name.GetLength(); | 550 case JS_GLOBALDATA_TYPE_STRING: |
536 » » » sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD)); | 551 { |
537 » » » sData.AppendString(name); | 552 FX_DWORD dwNameLen = (FX_DWORD)name.GetLength(); |
| 553 sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD)); |
| 554 sData.AppendString(name); |
| 555 sData.AppendBlock(&wType, sizeof(FX_WORD)); |
538 | 556 |
539 » » » sData.AppendBlock(&wType, sizeof(FX_WORD)); | 557 FX_DWORD dwDataLen = (FX_DWORD)pData->sData.GetLength(); |
540 » » » double dData = pData->dData; | 558 sData.AppendBlock(&dwDataLen, sizeof(FX_DWORD)); |
541 » » » sData.AppendBlock(&dData, sizeof(double)); | 559 sData.AppendString(pData->sData); |
542 » » } | 560 } |
543 » » break; | 561 break; |
544 » case JS_GLOBALDATA_TYPE_BOOLEAN: | 562 case JS_GLOBALDATA_TYPE_NULL: |
545 » » { | 563 { |
546 » » » FX_DWORD dwNameLen = (FX_DWORD)name.GetLength(); | 564 FX_DWORD dwNameLen = (FX_DWORD)name.GetLength(); |
547 » » » sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD)); | 565 sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD)); |
548 » » » sData.AppendString(name); | 566 sData.AppendString(name); |
549 | 567 sData.AppendBlock(&wType, sizeof(FX_DWORD)); |
550 » » » sData.AppendBlock(&wType, sizeof(FX_WORD)); | 568 } |
551 » » » FX_WORD wData = (FX_WORD)pData->bData; | 569 break; |
552 » » » sData.AppendBlock(&wData, sizeof(FX_WORD)); | 570 default: |
553 » » } | 571 break; |
554 » » break; | 572 } |
555 » case JS_GLOBALDATA_TYPE_STRING: | |
556 » » { | |
557 » » » FX_DWORD dwNameLen = (FX_DWORD)name.GetLength(); | |
558 » » » sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD)); | |
559 » » » sData.AppendString(name); | |
560 | |
561 » » » sData.AppendBlock(&wType, sizeof(FX_WORD)); | |
562 | |
563 » » » FX_DWORD dwDataLen = (FX_DWORD)pData->sData.GetLength(); | |
564 » » » sData.AppendBlock(&dwDataLen, sizeof(FX_DWORD)); | |
565 » » » sData.AppendString(pData->sData); | |
566 » » } | |
567 » » break; | |
568 » case JS_GLOBALDATA_TYPE_NULL: | |
569 » » { | |
570 » » » FX_DWORD dwNameLen = (FX_DWORD)name.GetLength(); | |
571 » » » sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD)); | |
572 » » » sData.AppendString(name); | |
573 | |
574 » » » sData.AppendBlock(&wType, sizeof(FX_DWORD)); | |
575 » » } | |
576 » » break; | |
577 » default: | |
578 » » break; | |
579 » } | |
580 } | 573 } |
581 | 574 |
OLD | NEW |