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