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}; 36 CXFA_LocaleValue::CXFA_LocaleValue() { 37 m_dwType = XFA_VT_NULL; 38 m_bValid = true; 39 m_pLocaleMgr = nullptr; 40 } 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 } 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 } 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 } 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 } 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 } 78 CXFA_LocaleValue::~CXFA_LocaleValue() {} 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 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 196 CFX_WideString CXFA_LocaleValue::GetValue() const { 197 return m_wsValue; 198 } 199 uint32_t CXFA_LocaleValue::GetType() const { 200 return m_dwType; 201 } 202 void CXFA_LocaleValue::SetValue(const CFX_WideString& wsValue, 203 uint32_t dwType) { 204 m_wsValue = wsValue; 205 m_dwType = dwType; 206 } 207 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 } 213 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 } 289 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 } 365 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 } 373 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 } 383 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 } 396 bool CXFA_LocaleValue::SetText(const CFX_WideString& wsText) { 397 m_dwType = XFA_VT_TEXT; 398 m_wsValue = wsText; 399 return true; 400 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 465 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 481 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 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 } 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 } 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 } 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 } 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 } 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 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 } 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