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 static const FX_DOUBLE fraction_scales[] = {0.1,
18                                             0.01,
19                                             0.001,
20                                             0.0001,
21                                             0.00001,
22                                             0.000001,
23                                             0.0000001,
24                                             0.00000001,
25                                             0.000000001,
26                                             0.0000000001,
27                                             0.00000000001,
28                                             0.000000000001,
29                                             0.0000000000001,
30                                             0.00000000000001,
31                                             0.000000000000001,
32                                             0.0000000000000001};
CXFA_LocaleValue()33 CXFA_LocaleValue::CXFA_LocaleValue() {
34   m_dwType = XFA_VT_NULL;
35   m_bValid = TRUE;
36   m_pLocaleMgr = NULL;
37 }
CXFA_LocaleValue(const CXFA_LocaleValue & value)38 CXFA_LocaleValue::CXFA_LocaleValue(const CXFA_LocaleValue& value) {
39   m_dwType = XFA_VT_NULL;
40   m_bValid = TRUE;
41   m_pLocaleMgr = NULL;
42   *this = value;
43 }
CXFA_LocaleValue(FX_DWORD dwType,CXFA_LocaleMgr * pLocaleMgr)44 CXFA_LocaleValue::CXFA_LocaleValue(FX_DWORD dwType,
45                                    CXFA_LocaleMgr* pLocaleMgr) {
46   m_dwType = dwType;
47   m_bValid = (m_dwType != XFA_VT_NULL);
48   m_pLocaleMgr = pLocaleMgr;
49 }
CXFA_LocaleValue(FX_DWORD dwType,const CFX_WideString & wsValue,CXFA_LocaleMgr * pLocaleMgr)50 CXFA_LocaleValue::CXFA_LocaleValue(FX_DWORD dwType,
51                                    const CFX_WideString& wsValue,
52                                    CXFA_LocaleMgr* pLocaleMgr) {
53   m_wsValue = wsValue;
54   m_dwType = dwType;
55   m_pLocaleMgr = pLocaleMgr;
56   m_bValid = ValidateCanonicalValue(wsValue, dwType);
57 }
CXFA_LocaleValue(FX_DWORD dwType,const CFX_WideString & wsValue,const CFX_WideString & wsFormat,IFX_Locale * pLocale,CXFA_LocaleMgr * pLocaleMgr)58 CXFA_LocaleValue::CXFA_LocaleValue(FX_DWORD dwType,
59                                    const CFX_WideString& wsValue,
60                                    const CFX_WideString& wsFormat,
61                                    IFX_Locale* pLocale,
62                                    CXFA_LocaleMgr* pLocaleMgr) {
63   m_pLocaleMgr = pLocaleMgr;
64   m_bValid = TRUE;
65   m_dwType = dwType;
66   m_bValid = ParsePatternValue(wsValue, wsFormat, pLocale);
67 }
operator =(const CXFA_LocaleValue & value)68 CXFA_LocaleValue& CXFA_LocaleValue::operator=(const CXFA_LocaleValue& value) {
69   m_wsValue = value.m_wsValue;
70   m_dwType = value.m_dwType;
71   m_bValid = value.m_bValid;
72   m_pLocaleMgr = value.m_pLocaleMgr;
73   return *this;
74 }
~CXFA_LocaleValue()75 CXFA_LocaleValue::~CXFA_LocaleValue() {}
XFA_ValugeCategory(FX_LOCALECATEGORY eCategory,FX_DWORD dwValueType)76 static FX_LOCALECATEGORY XFA_ValugeCategory(FX_LOCALECATEGORY eCategory,
77                                             FX_DWORD dwValueType) {
78   if (eCategory == FX_LOCALECATEGORY_Unknown) {
79     switch (dwValueType) {
80       case XFA_VT_BOOLEAN:
81       case XFA_VT_INTEGER:
82       case XFA_VT_DECIMAL:
83       case XFA_VT_FLOAT:
84         return FX_LOCALECATEGORY_Num;
85       case XFA_VT_TEXT:
86         return FX_LOCALECATEGORY_Text;
87       case XFA_VT_DATE:
88         return FX_LOCALECATEGORY_Date;
89       case XFA_VT_TIME:
90         return FX_LOCALECATEGORY_Time;
91       case XFA_VT_DATETIME:
92         return FX_LOCALECATEGORY_DateTime;
93     }
94   }
95   return eCategory;
96 }
ValidateValue(const CFX_WideString & wsValue,const CFX_WideString & wsPattern,IFX_Locale * pLocale,CFX_WideString * pMatchFormat)97 FX_BOOL CXFA_LocaleValue::ValidateValue(const CFX_WideString& wsValue,
98                                         const CFX_WideString& wsPattern,
99                                         IFX_Locale* pLocale,
100                                         CFX_WideString* pMatchFormat) {
101   CFX_WideString wsOutput;
102   IFX_Locale* locale = m_pLocaleMgr->GetDefLocale();
103   if (pLocale) {
104     m_pLocaleMgr->SetDefLocale(pLocale);
105   }
106   IFX_FormatString* pFormat = IFX_FormatString::Create(m_pLocaleMgr, FALSE);
107   CFX_WideStringArray wsPatterns;
108   pFormat->SplitFormatString(wsPattern, wsPatterns);
109   FX_BOOL bRet = FALSE;
110   int32_t iCount = wsPatterns.GetSize();
111   int32_t i = 0;
112   for (; i < iCount && !bRet; i++) {
113     CFX_WideString wsFormat = wsPatterns[i];
114     FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat);
115     eCategory = XFA_ValugeCategory(eCategory, m_dwType);
116     switch (eCategory) {
117       case FX_LOCALECATEGORY_Null:
118         bRet = pFormat->ParseNull(wsValue, wsFormat);
119         if (!bRet) {
120           bRet = wsValue.IsEmpty();
121         }
122         break;
123       case FX_LOCALECATEGORY_Zero:
124         bRet = pFormat->ParseZero(wsValue, wsFormat);
125         if (!bRet) {
126           bRet = wsValue == FX_WSTRC(L"0");
127         }
128         break;
129       case FX_LOCALECATEGORY_Num: {
130         CFX_WideString fNum;
131         bRet = pFormat->ParseNum(wsValue, wsFormat, fNum);
132         if (!bRet) {
133           bRet = pFormat->FormatNum(wsValue, wsFormat, wsOutput);
134         }
135         break;
136       }
137       case FX_LOCALECATEGORY_Text:
138         bRet = pFormat->ParseText(wsValue, wsFormat, wsOutput);
139         wsOutput.Empty();
140         if (!bRet) {
141           bRet = pFormat->FormatText(wsValue, wsFormat, wsOutput);
142         }
143         break;
144       case FX_LOCALECATEGORY_Date: {
145         CFX_Unitime dt;
146         bRet = ValidateCanonicalDate(wsValue, dt);
147         if (!bRet) {
148           bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date,
149                                         dt);
150           if (!bRet) {
151             bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
152                                            FX_DATETIMETYPE_Date);
153           }
154         }
155         break;
156       }
157       case FX_LOCALECATEGORY_Time: {
158         CFX_Unitime dt;
159         bRet =
160             pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt);
161         if (!bRet) {
162           bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
163                                          FX_DATETIMETYPE_Time);
164         }
165         break;
166       }
167       case FX_LOCALECATEGORY_DateTime: {
168         CFX_Unitime dt;
169         bRet = pFormat->ParseDateTime(wsValue, wsFormat,
170                                       FX_DATETIMETYPE_DateTime, dt);
171         if (!bRet) {
172           bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
173                                          FX_DATETIMETYPE_DateTime);
174         }
175         break;
176       }
177       default:
178         bRet = FALSE;
179         break;
180     }
181   }
182   if (bRet && pMatchFormat) {
183     *pMatchFormat = wsPatterns[i - 1];
184   }
185   pFormat->Release();
186   if (pLocale) {
187     m_pLocaleMgr->SetDefLocale(locale);
188   }
189   return bRet;
190 }
GetValue() const191 CFX_WideString CXFA_LocaleValue::GetValue() const {
192   return m_wsValue;
193 }
GetType() const194 FX_DWORD CXFA_LocaleValue::GetType() const {
195   return m_dwType;
196 }
SetValue(const CFX_WideString & wsValue,FX_DWORD dwType)197 void CXFA_LocaleValue::SetValue(const CFX_WideString& wsValue,
198                                 FX_DWORD dwType) {
199   m_wsValue = wsValue;
200   m_dwType = dwType;
201 }
GetText() const202 CFX_WideString CXFA_LocaleValue::GetText() const {
203   if (m_bValid && m_dwType == XFA_VT_TEXT) {
204     return m_wsValue;
205   }
206   return CFX_WideString();
207 }
GetNum() const208 FX_FLOAT CXFA_LocaleValue::GetNum() const {
209   if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER ||
210                    m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) {
211     int64_t nIntegral = 0;
212     FX_DWORD dwFractional = 0;
213     int32_t nExponent = 0;
214     int cc = 0;
215     FX_BOOL bNegative = FALSE, bExpSign = FALSE;
216     const FX_WCHAR* str = (const FX_WCHAR*)m_wsValue;
217     int len = m_wsValue.GetLength();
218     while (XFA_IsSpace(str[cc]) && cc < len) {
219       cc++;
220     }
221     if (cc >= len) {
222       return 0;
223     }
224     if (str[0] == '+') {
225       cc++;
226     } else if (str[0] == '-') {
227       bNegative = TRUE;
228       cc++;
229     }
230     int nIntegralLen = 0;
231     while (cc < len) {
232       if (str[cc] == '.' || !XFA_IsDigit(str[cc]) || nIntegralLen > 17) {
233         break;
234       }
235       nIntegral = nIntegral * 10 + str[cc] - '0';
236       cc++;
237       nIntegralLen++;
238     }
239     nIntegral = bNegative ? -nIntegral : nIntegral;
240     int scale = 0;
241     double fraction = 0.0;
242     if (cc < len && str[cc] == '.') {
243       cc++;
244       while (cc < len) {
245         fraction += fraction_scales[scale] * (str[cc] - '0');
246         scale++;
247         cc++;
248         if (scale == sizeof fraction_scales / sizeof(double) ||
249             !XFA_IsDigit(str[cc])) {
250           break;
251         }
252       }
253       dwFractional = (FX_DWORD)(fraction * 4294967296.0);
254     }
255     if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
256       cc++;
257       if (cc < len) {
258         if (str[cc] == '+') {
259           cc++;
260         } else if (str[cc] == '-') {
261           bExpSign = TRUE;
262           cc++;
263         }
264       }
265       while (cc < len) {
266         if (str[cc] == '.' || !XFA_IsDigit(str[cc])) {
267           break;
268         }
269         nExponent = nExponent * 10 + str[cc] - '0';
270         cc++;
271       }
272       nExponent = bExpSign ? -nExponent : nExponent;
273     }
274     FX_FLOAT fValue = (FX_FLOAT)(dwFractional / 4294967296.0);
275     fValue = nIntegral + (nIntegral >= 0 ? fValue : -fValue);
276     if (nExponent != 0) {
277       fValue *= FXSYS_pow(10, (FX_FLOAT)nExponent);
278     }
279     return fValue;
280   }
281   return 0;
282 }
GetDoubleNum() const283 FX_DOUBLE CXFA_LocaleValue::GetDoubleNum() const {
284   if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER ||
285                    m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) {
286     int64_t nIntegral = 0;
287     FX_DWORD dwFractional = 0;
288     int32_t nExponent = 0;
289     int32_t cc = 0;
290     FX_BOOL bNegative = FALSE, bExpSign = FALSE;
291     const FX_WCHAR* str = (const FX_WCHAR*)m_wsValue;
292     int len = m_wsValue.GetLength();
293     while (XFA_IsSpace(str[cc]) && cc < len) {
294       cc++;
295     }
296     if (cc >= len) {
297       return 0;
298     }
299     if (str[0] == '+') {
300       cc++;
301     } else if (str[0] == '-') {
302       bNegative = TRUE;
303       cc++;
304     }
305     int32_t nIntegralLen = 0;
306     while (cc < len) {
307       if (str[cc] == '.' || !XFA_IsDigit(str[cc]) || nIntegralLen > 17) {
308         break;
309       }
310       nIntegral = nIntegral * 10 + str[cc] - '0';
311       cc++;
312       nIntegralLen++;
313     }
314     nIntegral = bNegative ? -nIntegral : nIntegral;
315     int32_t scale = 0;
316     FX_DOUBLE fraction = 0.0;
317     if (cc < len && str[cc] == '.') {
318       cc++;
319       while (cc < len) {
320         fraction += fraction_scales[scale] * (str[cc] - '0');
321         scale++;
322         cc++;
323         if (scale == sizeof fraction_scales / sizeof(FX_DOUBLE) ||
324             !XFA_IsDigit(str[cc])) {
325           break;
326         }
327       }
328       dwFractional = (FX_DWORD)(fraction * 4294967296.0);
329     }
330     if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
331       cc++;
332       if (cc < len) {
333         if (str[cc] == '+') {
334           cc++;
335         } else if (str[cc] == '-') {
336           bExpSign = TRUE;
337           cc++;
338         }
339       }
340       while (cc < len) {
341         if (str[cc] == '.' || !XFA_IsDigit(str[cc])) {
342           break;
343         }
344         nExponent = nExponent * 10 + str[cc] - '0';
345         cc++;
346       }
347       nExponent = bExpSign ? -nExponent : nExponent;
348     }
349     FX_DOUBLE dValue = (dwFractional / 4294967296.0);
350     dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue);
351     if (nExponent != 0) {
352       dValue *= FXSYS_pow(10, (FX_FLOAT)nExponent);
353     }
354     return dValue;
355   }
356   return 0;
357 }
GetDate() const358 CFX_Unitime CXFA_LocaleValue::GetDate() const {
359   if (m_bValid && m_dwType == XFA_VT_DATE) {
360     CFX_Unitime dt;
361     FX_DateFromCanonical(m_wsValue, dt);
362     return dt;
363   }
364   return CFX_Unitime();
365 }
GetTime() const366 CFX_Unitime CXFA_LocaleValue::GetTime() const {
367   if (m_bValid && m_dwType == XFA_VT_TIME) {
368     CFX_Unitime dt(0);
369     FXSYS_assert(m_pLocaleMgr);
370     FX_TimeFromCanonical(m_wsValue, dt, m_pLocaleMgr->GetDefLocale());
371     return dt;
372   }
373   return CFX_Unitime();
374 }
GetDateTime() const375 CFX_Unitime CXFA_LocaleValue::GetDateTime() const {
376   if (m_bValid && m_dwType == XFA_VT_DATETIME) {
377     int32_t index = m_wsValue.Find('T');
378     CFX_Unitime dt;
379     FX_DateFromCanonical(m_wsValue.Left(index), dt);
380     FXSYS_assert(m_pLocaleMgr);
381     FX_TimeFromCanonical(m_wsValue.Right(m_wsValue.GetLength() - index - 1), dt,
382                          m_pLocaleMgr->GetDefLocale());
383     return dt;
384   }
385   return CFX_Unitime();
386 }
SetText(const CFX_WideString & wsText)387 FX_BOOL CXFA_LocaleValue::SetText(const CFX_WideString& wsText) {
388   m_dwType = XFA_VT_TEXT;
389   m_wsValue = wsText;
390   return TRUE;
391 }
SetText(const CFX_WideString & wsText,const CFX_WideString & wsFormat,IFX_Locale * pLocale)392 FX_BOOL CXFA_LocaleValue::SetText(const CFX_WideString& wsText,
393                                   const CFX_WideString& wsFormat,
394                                   IFX_Locale* pLocale) {
395   m_dwType = XFA_VT_TEXT;
396   return m_bValid = ParsePatternValue(wsText, wsFormat, pLocale);
397 }
SetNum(FX_FLOAT fNum)398 FX_BOOL CXFA_LocaleValue::SetNum(FX_FLOAT fNum) {
399   m_dwType = XFA_VT_FLOAT;
400   m_wsValue.Format(L"%.8g", (FX_DOUBLE)fNum);
401   return TRUE;
402 }
SetNum(const CFX_WideString & wsNum,const CFX_WideString & wsFormat,IFX_Locale * pLocale)403 FX_BOOL CXFA_LocaleValue::SetNum(const CFX_WideString& wsNum,
404                                  const CFX_WideString& wsFormat,
405                                  IFX_Locale* pLocale) {
406   m_dwType = XFA_VT_FLOAT;
407   return m_bValid = ParsePatternValue(wsNum, wsFormat, pLocale);
408 }
SetDate(const CFX_Unitime & d)409 FX_BOOL CXFA_LocaleValue::SetDate(const CFX_Unitime& d) {
410   m_dwType = XFA_VT_DATE;
411   m_wsValue.Format(L"%04d-%02d-%02d", d.GetYear(), d.GetMonth(), d.GetDay());
412   return TRUE;
413 }
SetDate(const CFX_WideString & wsDate,const CFX_WideString & wsFormat,IFX_Locale * pLocale)414 FX_BOOL CXFA_LocaleValue::SetDate(const CFX_WideString& wsDate,
415                                   const CFX_WideString& wsFormat,
416                                   IFX_Locale* pLocale) {
417   m_dwType = XFA_VT_DATE;
418   return m_bValid = ParsePatternValue(wsDate, wsFormat, pLocale);
419 }
SetTime(const CFX_Unitime & t)420 FX_BOOL CXFA_LocaleValue::SetTime(const CFX_Unitime& t) {
421   m_dwType = XFA_VT_TIME;
422   m_wsValue.Format(L"%02d:%02d:%02d", t.GetHour(), t.GetMinute(),
423                    t.GetSecond());
424   if (t.GetMillisecond() > 0) {
425     CFX_WideString wsTemp;
426     wsTemp.Format(L"%:03d", t.GetMillisecond());
427     m_wsValue += wsTemp;
428   }
429   return TRUE;
430 }
SetTime(const CFX_WideString & wsTime,const CFX_WideString & wsFormat,IFX_Locale * pLocale)431 FX_BOOL CXFA_LocaleValue::SetTime(const CFX_WideString& wsTime,
432                                   const CFX_WideString& wsFormat,
433                                   IFX_Locale* pLocale) {
434   m_dwType = XFA_VT_TIME;
435   return m_bValid = ParsePatternValue(wsTime, wsFormat, pLocale);
436 }
SetDateTime(const CFX_Unitime & dt)437 FX_BOOL CXFA_LocaleValue::SetDateTime(const CFX_Unitime& dt) {
438   m_dwType = XFA_VT_DATETIME;
439   m_wsValue.Format(L"%04d-%02d-%02dT%02d:%02d:%02d", dt.GetYear(),
440                    dt.GetMonth(), dt.GetDay(), dt.GetHour(), dt.GetMinute(),
441                    dt.GetSecond());
442   if (dt.GetMillisecond() > 0) {
443     CFX_WideString wsTemp;
444     wsTemp.Format(L"%:03d", dt.GetMillisecond());
445     m_wsValue += wsTemp;
446   }
447   return TRUE;
448 }
SetDateTime(const CFX_WideString & wsDateTime,const CFX_WideString & wsFormat,IFX_Locale * pLocale)449 FX_BOOL CXFA_LocaleValue::SetDateTime(const CFX_WideString& wsDateTime,
450                                       const CFX_WideString& wsFormat,
451                                       IFX_Locale* pLocale) {
452   m_dwType = XFA_VT_DATETIME;
453   return m_bValid = ParsePatternValue(wsDateTime, wsFormat, pLocale);
454 }
FormatPatterns(CFX_WideString & wsResult,const CFX_WideString & wsFormat,IFX_Locale * pLocale,XFA_VALUEPICTURE eValueType) const455 FX_BOOL CXFA_LocaleValue::FormatPatterns(CFX_WideString& wsResult,
456                                          const CFX_WideString& wsFormat,
457                                          IFX_Locale* pLocale,
458                                          XFA_VALUEPICTURE eValueType) const {
459   wsResult.Empty();
460   FX_BOOL bRet = FALSE;
461   IFX_FormatString* pFormat = IFX_FormatString::Create(m_pLocaleMgr, FALSE);
462   CFX_WideStringArray wsPatterns;
463   pFormat->SplitFormatString(wsFormat, wsPatterns);
464   int32_t iCount = wsPatterns.GetSize();
465   for (int32_t i = 0; i < iCount; i++) {
466     bRet = FormatSinglePattern(wsResult, wsPatterns[i], pLocale, eValueType);
467     if (bRet) {
468       break;
469     }
470   }
471   pFormat->Release();
472   return bRet;
473 }
FormatSinglePattern(CFX_WideString & wsResult,const CFX_WideString & wsFormat,IFX_Locale * pLocale,XFA_VALUEPICTURE eValueType) const474 FX_BOOL CXFA_LocaleValue::FormatSinglePattern(
475     CFX_WideString& wsResult,
476     const CFX_WideString& wsFormat,
477     IFX_Locale* pLocale,
478     XFA_VALUEPICTURE eValueType) const {
479   IFX_Locale* locale = m_pLocaleMgr->GetDefLocale();
480   if (pLocale) {
481     m_pLocaleMgr->SetDefLocale(pLocale);
482   }
483   wsResult.Empty();
484   FX_BOOL bRet = FALSE;
485   IFX_FormatString* pFormat = IFX_FormatString::Create(m_pLocaleMgr, FALSE);
486   FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat);
487   eCategory = XFA_ValugeCategory(eCategory, m_dwType);
488   switch (eCategory) {
489     case FX_LOCALECATEGORY_Null:
490       if (m_wsValue.IsEmpty()) {
491         bRet = pFormat->FormatNull(wsFormat, wsResult);
492       }
493       break;
494     case FX_LOCALECATEGORY_Zero:
495       if (m_wsValue == FX_WSTRC(L"0")) {
496         bRet = pFormat->FormatZero(wsFormat, wsResult);
497       }
498       break;
499     case FX_LOCALECATEGORY_Num:
500       bRet = pFormat->FormatNum(m_wsValue, wsFormat, wsResult);
501       break;
502     case FX_LOCALECATEGORY_Text:
503       bRet = pFormat->FormatText(m_wsValue, wsFormat, wsResult);
504       break;
505     case FX_LOCALECATEGORY_Date:
506       bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult,
507                                      FX_DATETIMETYPE_Date);
508       break;
509     case FX_LOCALECATEGORY_Time:
510       bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult,
511                                      FX_DATETIMETYPE_Time);
512       break;
513     case FX_LOCALECATEGORY_DateTime:
514       bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult,
515                                      FX_DATETIMETYPE_DateTime);
516       break;
517     default:
518       wsResult = m_wsValue;
519       bRet = TRUE;
520   }
521   pFormat->Release();
522   if (!bRet && (eCategory != FX_LOCALECATEGORY_Num ||
523                 eValueType != XFA_VALUEPICTURE_Display)) {
524     wsResult = m_wsValue;
525   }
526   if (pLocale) {
527     m_pLocaleMgr->SetDefLocale(locale);
528   }
529   return bRet;
530 }
XFA_ValueSplitDateTime(const CFX_WideString & wsDateTime,CFX_WideString & wsDate,CFX_WideString & wsTime)531 static FX_BOOL XFA_ValueSplitDateTime(const CFX_WideString& wsDateTime,
532                                       CFX_WideString& wsDate,
533                                       CFX_WideString& wsTime) {
534   wsDate = L"";
535   wsTime = L"";
536   if (wsDateTime.IsEmpty()) {
537     return FALSE;
538   }
539   int nSplitIndex = -1;
540   nSplitIndex = wsDateTime.Find('T');
541   if (nSplitIndex < 0) {
542     nSplitIndex = wsDateTime.Find(' ');
543   }
544   if (nSplitIndex < 0) {
545     return FALSE;
546   }
547   wsDate = wsDateTime.Left(nSplitIndex);
548   wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1);
549   return TRUE;
550 }
ValidateCanonicalValue(const CFX_WideString & wsValue,FX_DWORD dwVType)551 FX_BOOL CXFA_LocaleValue::ValidateCanonicalValue(const CFX_WideString& wsValue,
552                                                  FX_DWORD dwVType) {
553   if (wsValue.IsEmpty()) {
554     return TRUE;
555   }
556   CFX_Unitime dt;
557   switch (dwVType) {
558     case XFA_VT_DATE: {
559       if (ValidateCanonicalDate(wsValue, dt)) {
560         return TRUE;
561       }
562       CFX_WideString wsDate, wsTime;
563       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
564           ValidateCanonicalDate(wsDate, dt)) {
565         return TRUE;
566       }
567       return FALSE;
568     }
569     case XFA_VT_TIME: {
570       if (ValidateCanonicalTime(wsValue)) {
571         return TRUE;
572       }
573       CFX_WideString wsDate, wsTime;
574       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
575           ValidateCanonicalTime(wsTime)) {
576         return TRUE;
577       }
578       return FALSE;
579     }
580     case XFA_VT_DATETIME: {
581       CFX_WideString wsDate, wsTime;
582       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
583           ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime)) {
584         return TRUE;
585       }
586     } break;
587   }
588   return TRUE;
589 }
ValidateCanonicalDate(const CFX_WideString & wsDate,CFX_Unitime & unDate)590 FX_BOOL CXFA_LocaleValue::ValidateCanonicalDate(const CFX_WideString& wsDate,
591                                                 CFX_Unitime& unDate) {
592   const FX_WORD LastDay[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
593   const FX_WORD wCountY = 4, wCountM = 2, wCountD = 2;
594   int nLen = wsDate.GetLength();
595   if (nLen < wCountY || nLen > wCountY + wCountM + wCountD + 2) {
596     return FALSE;
597   }
598   FX_BOOL bSymbol = (wsDate.Find(0x2D) == -1) ? FALSE : TRUE;
599   FX_WORD wYear = 0, wMonth = 0, wDay = 0;
600   const FX_WCHAR* pDate = (const FX_WCHAR*)wsDate;
601   int nIndex = 0, nStart = 0;
602   while (pDate[nIndex] != '\0' && nIndex < wCountY) {
603     if (!XFA_IsDigit(pDate[nIndex])) {
604       return FALSE;
605     }
606     wYear = (pDate[nIndex] - '0') + wYear * 10;
607     nIndex++;
608   }
609   if (bSymbol) {
610     if (pDate[nIndex] != 0x2D) {
611       return FALSE;
612     }
613     nIndex++;
614   }
615   nStart = nIndex;
616   while (pDate[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) {
617     if (!XFA_IsDigit(pDate[nIndex])) {
618       return FALSE;
619     }
620     wMonth = (pDate[nIndex] - '0') + wMonth * 10;
621     nIndex++;
622   }
623   if (bSymbol) {
624     if (pDate[nIndex] != 0x2D) {
625       return FALSE;
626     }
627     nIndex++;
628   }
629   nStart = nIndex;
630   while (pDate[nIndex] != '\0' && nIndex - nStart < wCountD && nIndex < nLen) {
631     if (!XFA_IsDigit(pDate[nIndex])) {
632       return FALSE;
633     }
634     wDay = (pDate[nIndex] - '0') + wDay * 10;
635     nIndex++;
636   }
637   if (nIndex != nLen) {
638     return FALSE;
639   }
640   if (wYear < 1900 || wYear > 2029) {
641     return FALSE;
642   }
643   if (wMonth < 1 || wMonth > 12) {
644     if (wMonth == 0 && nLen == wCountY) {
645       return TRUE;
646     }
647     return FALSE;
648   }
649   if (wDay < 1) {
650     if (wDay == 0 && (nLen == wCountY + wCountM)) {
651       return TRUE;
652     }
653     return FALSE;
654   }
655   if (wMonth == 2) {
656     if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) {
657       if (wDay > 29) {
658         return FALSE;
659       }
660     } else {
661       if (wDay > 28) {
662         return FALSE;
663       }
664     }
665   } else if (wDay > LastDay[wMonth - 1]) {
666     return FALSE;
667   }
668   CFX_Unitime ut;
669   ut.Set(wYear, static_cast<uint8_t>(wMonth), static_cast<uint8_t>(wDay));
670   unDate = unDate + ut;
671   return TRUE;
672 }
ValidateCanonicalTime(const CFX_WideString & wsTime)673 FX_BOOL CXFA_LocaleValue::ValidateCanonicalTime(const CFX_WideString& wsTime) {
674   int nLen = wsTime.GetLength();
675   if (nLen < 2) {
676     return FALSE;
677   }
678   const FX_WORD wCountH = 2, wCountM = 2, wCountS = 2, wCountF = 3;
679   FX_BOOL bSymbol = (wsTime.Find(':') == -1) ? FALSE : TRUE;
680   FX_WORD wHour = 0, wMinute = 0, wSecond = 0, wFraction = 0;
681   const FX_WCHAR* pTime = (const FX_WCHAR*)wsTime;
682   int nIndex = 0, nStart = 0;
683   while (pTime[nIndex] != '\0' && nIndex - nStart < wCountH) {
684     if (!XFA_IsDigit(pTime[nIndex])) {
685       return FALSE;
686     }
687     wHour = (pTime[nIndex] - '0') + wHour * 10;
688     nIndex++;
689   }
690   if (bSymbol) {
691     if (nIndex < nLen && pTime[nIndex] != ':') {
692       return FALSE;
693     }
694     nIndex++;
695   }
696   nStart = nIndex;
697   while (pTime[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) {
698     if (!XFA_IsDigit(pTime[nIndex])) {
699       return FALSE;
700     }
701     wMinute = (pTime[nIndex] - '0') + wMinute * 10;
702     nIndex++;
703   }
704   if (bSymbol) {
705     if (nIndex < nLen && pTime[nIndex] != ':') {
706       return FALSE;
707     }
708     nIndex++;
709   }
710   nStart = nIndex;
711   while (pTime[nIndex] != '\0' && nIndex - nStart < wCountS && nIndex < nLen) {
712     if (!XFA_IsDigit(pTime[nIndex])) {
713       return FALSE;
714     }
715     wSecond = (pTime[nIndex] - '0') + wSecond * 10;
716     nIndex++;
717   }
718   if (wsTime.Find('.') > 0) {
719     if (pTime[nIndex] != '.') {
720       return FALSE;
721     }
722     nIndex++;
723     nStart = nIndex;
724     while (pTime[nIndex] != '\0' && nIndex - nStart < wCountF &&
725            nIndex < nLen) {
726       if (!XFA_IsDigit(pTime[nIndex])) {
727         return FALSE;
728       }
729       wFraction = (pTime[nIndex] - '0') + wFraction * 10;
730       nIndex++;
731     }
732   }
733   if (nIndex < nLen) {
734     if (pTime[nIndex] == 'Z') {
735       nIndex++;
736     } else if (pTime[nIndex] == '-' || pTime[nIndex] == '+') {
737       int16_t nOffsetH = 0, nOffsetM = 0;
738       nIndex++;
739       nStart = nIndex;
740       while (pTime[nIndex] != '\0' && nIndex - nStart < wCountH &&
741              nIndex < nLen) {
742         if (!XFA_IsDigit(pTime[nIndex])) {
743           return FALSE;
744         }
745         nOffsetH = (pTime[nIndex] - '0') + nOffsetH * 10;
746         nIndex++;
747       }
748       if (bSymbol) {
749         if (nIndex < nLen && pTime[nIndex] != ':') {
750           return FALSE;
751         }
752         nIndex++;
753       }
754       nStart = nIndex;
755       while (pTime[nIndex] != '\0' && nIndex - nStart < wCountM &&
756              nIndex < nLen) {
757         if (!XFA_IsDigit(pTime[nIndex])) {
758           return FALSE;
759         }
760         nOffsetM = (pTime[nIndex] - '0') + nOffsetM * 10;
761         nIndex++;
762       }
763       if (nOffsetH > 12) {
764         return FALSE;
765       }
766       if (nOffsetM >= 60) {
767         return FALSE;
768       }
769     }
770   }
771   if (nIndex != nLen) {
772     return FALSE;
773   }
774   if (wHour >= 24) {
775     return FALSE;
776   }
777   if (wMinute >= 60) {
778     return FALSE;
779   }
780   if (wSecond >= 60) {
781     return FALSE;
782   }
783   if (wFraction > 999) {
784     return FALSE;
785   }
786   return TRUE;
787 }
ValidateCanonicalDateTime(const CFX_WideString & wsDateTime)788 FX_BOOL CXFA_LocaleValue::ValidateCanonicalDateTime(
789     const CFX_WideString& wsDateTime) {
790   CFX_WideString wsDate, wsTime;
791   if (wsDateTime.IsEmpty()) {
792     return FALSE;
793   }
794   int nSplitIndex = -1;
795   nSplitIndex = wsDateTime.Find('T');
796   if (nSplitIndex < 0) {
797     nSplitIndex = wsDateTime.Find(' ');
798   }
799   if (nSplitIndex < 0) {
800     return FALSE;
801   }
802   wsDate = wsDateTime.Left(nSplitIndex);
803   wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1);
804   CFX_Unitime dt;
805   return ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime);
806 }
ParsePatternValue(const CFX_WideString & wsValue,const CFX_WideString & wsPattern,IFX_Locale * pLocale)807 FX_BOOL CXFA_LocaleValue::ParsePatternValue(const CFX_WideString& wsValue,
808                                             const CFX_WideString& wsPattern,
809                                             IFX_Locale* pLocale) {
810   IFX_Locale* locale = m_pLocaleMgr->GetDefLocale();
811   if (pLocale) {
812     m_pLocaleMgr->SetDefLocale(pLocale);
813   }
814   IFX_FormatString* pFormat = IFX_FormatString::Create(m_pLocaleMgr, FALSE);
815   CFX_WideStringArray wsPatterns;
816   pFormat->SplitFormatString(wsPattern, wsPatterns);
817   FX_BOOL bRet = FALSE;
818   int32_t iCount = wsPatterns.GetSize();
819   for (int32_t i = 0; i < iCount && !bRet; i++) {
820     CFX_WideString wsFormat = wsPatterns[i];
821     FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat);
822     eCategory = XFA_ValugeCategory(eCategory, m_dwType);
823     switch (eCategory) {
824       case FX_LOCALECATEGORY_Null:
825         bRet = pFormat->ParseNull(wsValue, wsFormat);
826         if (bRet) {
827           m_wsValue.Empty();
828         }
829         break;
830       case FX_LOCALECATEGORY_Zero:
831         bRet = pFormat->ParseZero(wsValue, wsFormat);
832         if (bRet) {
833           m_wsValue = FX_WSTRC(L"0");
834         }
835         break;
836       case FX_LOCALECATEGORY_Num: {
837         CFX_WideString fNum;
838         bRet = pFormat->ParseNum(wsValue, wsFormat, fNum);
839         if (bRet) {
840           m_wsValue = fNum;
841         }
842         break;
843       }
844       case FX_LOCALECATEGORY_Text:
845         bRet = pFormat->ParseText(wsValue, wsFormat, m_wsValue);
846         break;
847       case FX_LOCALECATEGORY_Date: {
848         CFX_Unitime dt;
849         bRet = ValidateCanonicalDate(wsValue, dt);
850         if (!bRet) {
851           bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date,
852                                         dt);
853         }
854         if (bRet) {
855           SetDate(dt);
856         }
857         break;
858       }
859       case FX_LOCALECATEGORY_Time: {
860         CFX_Unitime dt;
861         bRet =
862             pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt);
863         if (bRet) {
864           SetTime(dt);
865         }
866         break;
867       }
868       case FX_LOCALECATEGORY_DateTime: {
869         CFX_Unitime dt;
870         bRet = pFormat->ParseDateTime(wsValue, wsFormat,
871                                       FX_DATETIMETYPE_DateTime, dt);
872         if (bRet) {
873           SetDateTime(dt);
874         }
875         break;
876       }
877       default:
878         m_wsValue = wsValue;
879         bRet = TRUE;
880         break;
881     }
882   }
883   if (!bRet) {
884     m_wsValue = wsValue;
885   }
886   pFormat->Release();
887   if (pLocale) {
888     m_pLocaleMgr->SetDefLocale(locale);
889   }
890   return bRet;
891 }
GetNumbericFormat(CFX_WideString & wsFormat,int32_t nIntLen,int32_t nDecLen,FX_BOOL bSign)892 void CXFA_LocaleValue::GetNumbericFormat(CFX_WideString& wsFormat,
893                                          int32_t nIntLen,
894                                          int32_t nDecLen,
895                                          FX_BOOL bSign) {
896   FXSYS_assert(wsFormat.IsEmpty());
897   FXSYS_assert(nIntLen >= -1 && nDecLen >= -1);
898   int32_t nTotalLen = (nIntLen >= 0 ? nIntLen : 2) + (bSign ? 1 : 0) +
899                       (nDecLen >= 0 ? nDecLen : 2) + (nDecLen == 0 ? 0 : 1);
900   FX_WCHAR* lpBuf = wsFormat.GetBuffer(nTotalLen);
901   int32_t nPos = 0;
902   if (bSign) {
903     lpBuf[nPos++] = L's';
904   }
905   if (nIntLen == -1) {
906     lpBuf[nPos++] = L'z';
907     lpBuf[nPos++] = L'*';
908   } else {
909     while (nIntLen) {
910       lpBuf[nPos++] = L'z';
911       nIntLen--;
912     }
913   }
914   if (nDecLen != 0) {
915     lpBuf[nPos++] = L'.';
916   }
917   if (nDecLen == -1) {
918     lpBuf[nPos++] = L'z';
919     lpBuf[nPos++] = L'*';
920   } else {
921     while (nDecLen) {
922       lpBuf[nPos++] = L'z';
923       nDecLen--;
924     }
925   }
926   wsFormat.ReleaseBuffer(nTotalLen);
927 }
ValidateNumericTemp(CFX_WideString & wsNumeric,CFX_WideString & wsFormat,IFX_Locale * pLocale,int32_t * pos)928 FX_BOOL CXFA_LocaleValue::ValidateNumericTemp(CFX_WideString& wsNumeric,
929                                               CFX_WideString& wsFormat,
930                                               IFX_Locale* pLocale,
931                                               int32_t* pos) {
932   if (wsFormat.IsEmpty() || wsNumeric.IsEmpty()) {
933     return TRUE;
934   }
935   const FX_WCHAR* pNum = wsNumeric.c_str();
936   const FX_WCHAR* pFmt = wsFormat.c_str();
937   int32_t n = 0, nf = 0;
938   FX_WCHAR c = pNum[n];
939   FX_WCHAR cf = pFmt[nf];
940   if (cf == L's') {
941     if (c == L'-' || c == L'+') {
942       ++n;
943     }
944     ++nf;
945   }
946   FX_BOOL bLimit = TRUE;
947   int32_t nCount = wsNumeric.GetLength();
948   int32_t nCountFmt = wsFormat.GetLength();
949   while (n < nCount && (bLimit ? nf < nCountFmt : TRUE) &&
950          XFA_IsDigit(c = pNum[n])) {
951     if (bLimit == TRUE) {
952       if ((cf = pFmt[nf]) == L'*') {
953         bLimit = FALSE;
954       } else if (cf == L'z') {
955         nf++;
956       } else {
957         return FALSE;
958       }
959     }
960     n++;
961   }
962   if (n == nCount) {
963     return TRUE;
964   }
965   if (nf == nCountFmt) {
966     return FALSE;
967   }
968   while (nf < nCountFmt && (cf = pFmt[nf]) != L'.') {
969     FXSYS_assert(cf == L'z' || cf == L'*');
970     ++nf;
971   }
972   CFX_WideString wsDecimalSymbol;
973   if (pLocale) {
974     pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDecimalSymbol);
975   } else {
976     wsDecimalSymbol = CFX_WideString(L'.');
977   }
978   if (pFmt[nf] != L'.') {
979     return FALSE;
980   }
981   if (wsDecimalSymbol != CFX_WideStringC(c) && c != L'.') {
982     return FALSE;
983   }
984   ++nf;
985   ++n;
986   bLimit = TRUE;
987   while (n < nCount && (bLimit ? nf < nCountFmt : TRUE) &&
988          XFA_IsDigit(c = pNum[n])) {
989     if (bLimit == TRUE) {
990       if ((cf = pFmt[nf]) == L'*') {
991         bLimit = FALSE;
992       } else if (cf == L'z') {
993         nf++;
994       } else {
995         return FALSE;
996       }
997     }
998     n++;
999   }
1000   return n == nCount;
1001 }
1002