blob: 4303342064e062289bd7814df7a862c70740657d [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclairf766ad22016-03-14 13:51:24 -04007#include "fpdfsdk/javascript/util.h"
Tom Sepez37458412015-10-06 11:33:46 -07008
Lei Zhang6b37a5f2015-12-25 00:20:59 -08009#include <time.h>
10
tsepez86a61dc2016-03-25 10:00:11 -070011#include <algorithm>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050012#include <string>
13#include <vector>
14
Dan Sinclaircfb19442017-04-20 13:13:04 -040015#include "core/fxcrt/fx_extension.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040016#include "fpdfsdk/javascript/JS_Define.h"
17#include "fpdfsdk/javascript/JS_EventHandler.h"
18#include "fpdfsdk/javascript/JS_Object.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040019#include "fpdfsdk/javascript/JS_Value.h"
20#include "fpdfsdk/javascript/PublicMethods.h"
Tom Sepezd6ae2af2017-02-16 11:49:55 -080021#include "fpdfsdk/javascript/cjs_event_context.h"
dsinclair64376be2016-03-31 20:03:24 -070022#include "fpdfsdk/javascript/cjs_runtime.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040023#include "fpdfsdk/javascript/resource.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070024
Nico Weber9d8ec5a2015-08-04 13:00:21 -070025#if _FX_OS_ == _FX_ANDROID_
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070026#include <ctype.h>
27#endif
28
Tom Sepez04557b82017-02-16 09:43:10 -080029JSConstSpec CJS_Util::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070030
Tom Sepez04557b82017-02-16 09:43:10 -080031JSPropertySpec CJS_Util::PropertySpecs[] = {{0, 0, 0}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070032
Tom Sepez04557b82017-02-16 09:43:10 -080033JSMethodSpec CJS_Util::MethodSpecs[] = {
Tom Sepez9b99b632017-02-21 15:05:57 -080034 {"printd", printd_static}, {"printf", printf_static},
35 {"printx", printx_static}, {"scand", scand_static},
36 {"byteToChar", byteToChar_static}, {0, 0}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070037
Nico Weber9d8ec5a2015-08-04 13:00:21 -070038IMPLEMENT_JS_CLASS(CJS_Util, util)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070039
Nico Weber9d8ec5a2015-08-04 13:00:21 -070040#define UTIL_INT 0
41#define UTIL_DOUBLE 1
42#define UTIL_STRING 2
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070043
tsepez86a61dc2016-03-25 10:00:11 -070044namespace {
45
46// Map PDF-style directives to equivalent wcsftime directives. Not
47// all have direct equivalents, though.
48struct TbConvert {
Dan Sinclair812e96c2017-03-13 16:43:37 -040049 const wchar_t* lpszJSMark;
50 const wchar_t* lpszCppMark;
tsepez86a61dc2016-03-25 10:00:11 -070051};
52
53// Map PDF-style directives lacking direct wcsftime directives to
54// the value with which they will be replaced.
55struct TbConvertAdditional {
Dan Sinclair812e96c2017-03-13 16:43:37 -040056 const wchar_t* lpszJSMark;
tsepez86a61dc2016-03-25 10:00:11 -070057 int iValue;
58};
59
60const TbConvert TbConvertTable[] = {
61 {L"mmmm", L"%B"}, {L"mmm", L"%b"}, {L"mm", L"%m"}, {L"dddd", L"%A"},
62 {L"ddd", L"%a"}, {L"dd", L"%d"}, {L"yyyy", L"%Y"}, {L"yy", L"%y"},
63 {L"HH", L"%H"}, {L"hh", L"%I"}, {L"MM", L"%M"}, {L"ss", L"%S"},
64 {L"TT", L"%p"},
65#if defined(_WIN32)
66 {L"tt", L"%p"}, {L"h", L"%#I"},
67#else
68 {L"tt", L"%P"}, {L"h", L"%l"},
69#endif
70};
71
72int ParseDataType(std::wstring* sFormat) {
tsepez4cf55152016-11-02 14:37:54 -070073 bool bPercent = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070074 for (size_t i = 0; i < sFormat->length(); ++i) {
75 wchar_t c = (*sFormat)[i];
76 if (c == L'%') {
77 bPercent = true;
78 continue;
Tom Sepez2f2ffec2015-07-23 14:42:09 -070079 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070080
Nico Weber9d8ec5a2015-08-04 13:00:21 -070081 if (bPercent) {
82 if (c == L'c' || c == L'C' || c == L'd' || c == L'i' || c == L'o' ||
83 c == L'u' || c == L'x' || c == L'X') {
84 return UTIL_INT;
85 }
86 if (c == L'e' || c == L'E' || c == L'f' || c == L'g' || c == L'G') {
87 return UTIL_DOUBLE;
88 }
89 if (c == L's' || c == L'S') {
90 // Map s to S since we always deal internally
91 // with wchar_t strings.
92 (*sFormat)[i] = L'S';
93 return UTIL_STRING;
94 }
95 if (c == L'.' || c == L'+' || c == L'-' || c == L'#' || c == L' ' ||
Lei Zhang9559b7a2015-12-21 11:12:20 -080096 FXSYS_iswdigit(c)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070097 continue;
98 }
99 break;
100 }
101 }
102
103 return -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700104}
105
tsepez86a61dc2016-03-25 10:00:11 -0700106} // namespace
107
108util::util(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {}
109
110util::~util() {}
111
Tom Sepezb1670b52017-02-16 17:01:00 -0800112bool util::printf(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700113 const std::vector<CJS_Value>& params,
114 CJS_Value& vRet,
115 CFX_WideString& sError) {
Lei Zhang574b5742017-03-30 12:41:55 -0700116 const size_t iSize = params.size();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700117 if (iSize < 1)
tsepez4cf55152016-11-02 14:37:54 -0700118 return false;
Lei Zhang574b5742017-03-30 12:41:55 -0700119
tsepezb4694242016-08-15 16:44:55 -0700120 std::wstring c_ConvChar(params[0].ToCFXWideString(pRuntime).c_str());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700121 std::vector<std::wstring> c_strConvers;
122 int iOffset = 0;
123 int iOffend = 0;
124 c_ConvChar.insert(c_ConvChar.begin(), L'S');
125 while (iOffset != -1) {
126 iOffend = c_ConvChar.find(L"%", iOffset + 1);
127 std::wstring strSub;
128 if (iOffend == -1)
129 strSub = c_ConvChar.substr(iOffset);
130 else
131 strSub = c_ConvChar.substr(iOffset, iOffend - iOffset);
132 c_strConvers.push_back(strSub);
133 iOffset = iOffend;
134 }
135
136 std::wstring c_strResult;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 std::wstring c_strFormat;
Lei Zhang574b5742017-03-30 12:41:55 -0700138 for (size_t iIndex = 0; iIndex < c_strConvers.size(); ++iIndex) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139 c_strFormat = c_strConvers[iIndex];
140 if (iIndex == 0) {
141 c_strResult = c_strFormat;
142 continue;
143 }
144
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700145 if (iIndex >= iSize) {
146 c_strResult += c_strFormat;
147 continue;
148 }
149
Lei Zhang574b5742017-03-30 12:41:55 -0700150 CFX_WideString strSegment;
tsepez86a61dc2016-03-25 10:00:11 -0700151 switch (ParseDataType(&c_strFormat)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700152 case UTIL_INT:
tsepezb4694242016-08-15 16:44:55 -0700153 strSegment.Format(c_strFormat.c_str(), params[iIndex].ToInt(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700154 break;
155 case UTIL_DOUBLE:
tsepezf3dc8c62016-08-10 06:29:29 -0700156 strSegment.Format(c_strFormat.c_str(),
tsepezb4694242016-08-15 16:44:55 -0700157 params[iIndex].ToDouble(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700158 break;
159 case UTIL_STRING:
tsepezb4694242016-08-15 16:44:55 -0700160 strSegment.Format(c_strFormat.c_str(),
161 params[iIndex].ToCFXWideString(pRuntime).c_str());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162 break;
163 default:
164 strSegment.Format(L"%S", c_strFormat.c_str());
165 break;
166 }
167 c_strResult += strSegment.GetBuffer(strSegment.GetLength() + 1);
168 }
169
170 c_strResult.erase(c_strResult.begin());
tsepezf3dc8c62016-08-10 06:29:29 -0700171 vRet = CJS_Value(pRuntime, c_strResult.c_str());
tsepez4cf55152016-11-02 14:37:54 -0700172 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700173}
174
Tom Sepezb1670b52017-02-16 17:01:00 -0800175bool util::printd(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700176 const std::vector<CJS_Value>& params,
177 CJS_Value& vRet,
178 CFX_WideString& sError) {
Lei Zhang574b5742017-03-30 12:41:55 -0700179 const size_t iSize = params.size();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700180 if (iSize < 2)
tsepez4cf55152016-11-02 14:37:54 -0700181 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700182
Lei Zhang574b5742017-03-30 12:41:55 -0700183 const CJS_Value& p1 = params[0];
184 const CJS_Value& p2 = params[1];
tsepezf3c88322016-08-09 07:30:38 -0700185 CJS_Date jsDate;
tsepezb4694242016-08-15 16:44:55 -0700186 if (!p2.ConvertToDate(pRuntime, jsDate)) {
tsepezcd5dc852016-09-08 11:23:24 -0700187 sError = JSGetStringFromID(IDS_STRING_JSPRINT1);
tsepez4cf55152016-11-02 14:37:54 -0700188 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700189 }
190
tsepezb4694242016-08-15 16:44:55 -0700191 if (!jsDate.IsValidDate(pRuntime)) {
tsepezcd5dc852016-09-08 11:23:24 -0700192 sError = JSGetStringFromID(IDS_STRING_JSPRINT2);
tsepez4cf55152016-11-02 14:37:54 -0700193 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700194 }
195
Tom Sepez39bfe122015-09-17 15:25:23 -0700196 if (p1.GetType() == CJS_Value::VT_number) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700197 CFX_WideString swResult;
tsepezb4694242016-08-15 16:44:55 -0700198 switch (p1.ToInt(pRuntime)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199 case 0:
tsepezb4694242016-08-15 16:44:55 -0700200 swResult.Format(L"D:%04d%02d%02d%02d%02d%02d", jsDate.GetYear(pRuntime),
201 jsDate.GetMonth(pRuntime) + 1, jsDate.GetDay(pRuntime),
202 jsDate.GetHours(pRuntime), jsDate.GetMinutes(pRuntime),
203 jsDate.GetSeconds(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700204 break;
205 case 1:
tsepezf3c88322016-08-09 07:30:38 -0700206 swResult.Format(L"%04d.%02d.%02d %02d:%02d:%02d",
tsepezb4694242016-08-15 16:44:55 -0700207 jsDate.GetYear(pRuntime), jsDate.GetMonth(pRuntime) + 1,
208 jsDate.GetDay(pRuntime), jsDate.GetHours(pRuntime),
209 jsDate.GetMinutes(pRuntime),
210 jsDate.GetSeconds(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700211 break;
212 case 2:
tsepezf3c88322016-08-09 07:30:38 -0700213 swResult.Format(L"%04d/%02d/%02d %02d:%02d:%02d",
tsepezb4694242016-08-15 16:44:55 -0700214 jsDate.GetYear(pRuntime), jsDate.GetMonth(pRuntime) + 1,
215 jsDate.GetDay(pRuntime), jsDate.GetHours(pRuntime),
216 jsDate.GetMinutes(pRuntime),
217 jsDate.GetSeconds(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700218 break;
219 default:
tsepezcd5dc852016-09-08 11:23:24 -0700220 sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
tsepez4cf55152016-11-02 14:37:54 -0700221 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700222 }
223
tsepezf3dc8c62016-08-10 06:29:29 -0700224 vRet = CJS_Value(pRuntime, swResult.c_str());
tsepez4cf55152016-11-02 14:37:54 -0700225 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226 }
tsepez86a61dc2016-03-25 10:00:11 -0700227
Tom Sepez39bfe122015-09-17 15:25:23 -0700228 if (p1.GetType() == CJS_Value::VT_string) {
tsepezb4694242016-08-15 16:44:55 -0700229 if (iSize > 2 && params[2].ToBool(pRuntime)) {
tsepezcd5dc852016-09-08 11:23:24 -0700230 sError = JSGetStringFromID(IDS_STRING_JSNOTSUPPORT);
tsepez4cf55152016-11-02 14:37:54 -0700231 return false; // currently, it doesn't support XFAPicture.
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700232 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700233
tsepez86a61dc2016-03-25 10:00:11 -0700234 // Convert PDF-style format specifiers to wcsftime specifiers. Remove any
235 // pre-existing %-directives before inserting our own.
tsepezb4694242016-08-15 16:44:55 -0700236 std::basic_string<wchar_t> cFormat = p1.ToCFXWideString(pRuntime).c_str();
tsepez86a61dc2016-03-25 10:00:11 -0700237 cFormat.erase(std::remove(cFormat.begin(), cFormat.end(), '%'),
238 cFormat.end());
239
240 for (size_t i = 0; i < FX_ArraySize(TbConvertTable); ++i) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700241 int iStart = 0;
242 int iEnd;
tsepez86a61dc2016-03-25 10:00:11 -0700243 while ((iEnd = cFormat.find(TbConvertTable[i].lpszJSMark, iStart)) !=
244 -1) {
245 cFormat.replace(iEnd, FXSYS_wcslen(TbConvertTable[i].lpszJSMark),
246 TbConvertTable[i].lpszCppMark);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700247 iStart = iEnd;
248 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700249 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700250
tsepezb4694242016-08-15 16:44:55 -0700251 int iYear = jsDate.GetYear(pRuntime);
252 int iMonth = jsDate.GetMonth(pRuntime);
253 int iDay = jsDate.GetDay(pRuntime);
254 int iHour = jsDate.GetHours(pRuntime);
255 int iMin = jsDate.GetMinutes(pRuntime);
256 int iSec = jsDate.GetSeconds(pRuntime);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700257
tsepez86a61dc2016-03-25 10:00:11 -0700258 TbConvertAdditional cTableAd[] = {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700259 {L"m", iMonth + 1}, {L"d", iDay},
260 {L"H", iHour}, {L"h", iHour > 12 ? iHour - 12 : iHour},
261 {L"M", iMin}, {L"s", iSec},
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700262 };
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700263
tsepez86a61dc2016-03-25 10:00:11 -0700264 for (size_t i = 0; i < FX_ArraySize(cTableAd); ++i) {
265 wchar_t tszValue[16];
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700266 CFX_WideString sValue;
Lei Zhangb9c31972015-08-11 14:09:35 -0700267 sValue.Format(L"%d", cTableAd[i].iValue);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268 memcpy(tszValue, (wchar_t*)sValue.GetBuffer(sValue.GetLength() + 1),
269 (sValue.GetLength() + 1) * sizeof(wchar_t));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700270
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 int iStart = 0;
272 int iEnd;
Lei Zhangb9c31972015-08-11 14:09:35 -0700273 while ((iEnd = cFormat.find(cTableAd[i].lpszJSMark, iStart)) != -1) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700274 if (iEnd > 0) {
275 if (cFormat[iEnd - 1] == L'%') {
276 iStart = iEnd + 1;
277 continue;
278 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700279 }
Lei Zhangb9c31972015-08-11 14:09:35 -0700280 cFormat.replace(iEnd, FXSYS_wcslen(cTableAd[i].lpszJSMark), tszValue);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700281 iStart = iEnd;
282 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700283 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700284
tsepez86a61dc2016-03-25 10:00:11 -0700285 struct tm time = {};
286 time.tm_year = iYear - 1900;
287 time.tm_mon = iMonth;
288 time.tm_mday = iDay;
289 time.tm_hour = iHour;
290 time.tm_min = iMin;
291 time.tm_sec = iSec;
292
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700293 wchar_t buf[64] = {};
tsepez86a61dc2016-03-25 10:00:11 -0700294 wcsftime(buf, 64, cFormat.c_str(), &time);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700295 cFormat = buf;
tsepezf3dc8c62016-08-10 06:29:29 -0700296 vRet = CJS_Value(pRuntime, cFormat.c_str());
tsepez4cf55152016-11-02 14:37:54 -0700297 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700298 }
tsepez86a61dc2016-03-25 10:00:11 -0700299
tsepezcd5dc852016-09-08 11:23:24 -0700300 sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR);
tsepez4cf55152016-11-02 14:37:54 -0700301 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700302}
303
Tom Sepezb1670b52017-02-16 17:01:00 -0800304bool util::printx(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700305 const std::vector<CJS_Value>& params,
306 CJS_Value& vRet,
307 CFX_WideString& sError) {
tsepez4f1f41f2016-03-28 14:13:16 -0700308 if (params.size() < 2) {
tsepezcd5dc852016-09-08 11:23:24 -0700309 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
tsepez4cf55152016-11-02 14:37:54 -0700310 return false;
tsepez4f1f41f2016-03-28 14:13:16 -0700311 }
tsepezf3dc8c62016-08-10 06:29:29 -0700312
tsepezb4694242016-08-15 16:44:55 -0700313 vRet = CJS_Value(pRuntime, printx(params[0].ToCFXWideString(pRuntime),
314 params[1].ToCFXWideString(pRuntime))
315 .c_str());
tsepezf3dc8c62016-08-10 06:29:29 -0700316
tsepez4cf55152016-11-02 14:37:54 -0700317 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700318}
319
tsepez4f1f41f2016-03-28 14:13:16 -0700320enum CaseMode { kPreserveCase, kUpperCase, kLowerCase };
321
Dan Sinclair812e96c2017-03-13 16:43:37 -0400322static wchar_t TranslateCase(wchar_t input, CaseMode eMode) {
tsepez4f1f41f2016-03-28 14:13:16 -0700323 if (eMode == kLowerCase && input >= 'A' && input <= 'Z')
324 return input | 0x20;
325 if (eMode == kUpperCase && input >= 'a' && input <= 'z')
326 return input & ~0x20;
327 return input;
328}
329
330CFX_WideString util::printx(const CFX_WideString& wsFormat,
331 const CFX_WideString& wsSource) {
332 CFX_WideString wsResult;
333 FX_STRSIZE iSourceIdx = 0;
334 FX_STRSIZE iFormatIdx = 0;
335 CaseMode eCaseMode = kPreserveCase;
336 bool bEscaped = false;
337 while (iFormatIdx < wsFormat.GetLength()) {
338 if (bEscaped) {
339 bEscaped = false;
340 wsResult += wsFormat[iFormatIdx];
341 ++iFormatIdx;
342 continue;
343 }
344 switch (wsFormat[iFormatIdx]) {
345 case '\\': {
346 bEscaped = true;
347 ++iFormatIdx;
348 } break;
349 case '<': {
350 eCaseMode = kLowerCase;
351 ++iFormatIdx;
352 } break;
353 case '>': {
354 eCaseMode = kUpperCase;
355 ++iFormatIdx;
356 } break;
357 case '=': {
358 eCaseMode = kPreserveCase;
359 ++iFormatIdx;
360 } break;
361 case '?': {
362 if (iSourceIdx < wsSource.GetLength()) {
363 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
364 ++iSourceIdx;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700365 }
tsepez4f1f41f2016-03-28 14:13:16 -0700366 ++iFormatIdx;
367 } break;
368 case 'X': {
369 if (iSourceIdx < wsSource.GetLength()) {
370 if ((wsSource[iSourceIdx] >= '0' && wsSource[iSourceIdx] <= '9') ||
371 (wsSource[iSourceIdx] >= 'a' && wsSource[iSourceIdx] <= 'z') ||
372 (wsSource[iSourceIdx] >= 'A' && wsSource[iSourceIdx] <= 'Z')) {
373 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
374 ++iFormatIdx;
375 }
376 ++iSourceIdx;
377 } else {
378 ++iFormatIdx;
379 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700380 } break;
381 case 'A': {
tsepez4f1f41f2016-03-28 14:13:16 -0700382 if (iSourceIdx < wsSource.GetLength()) {
383 if ((wsSource[iSourceIdx] >= 'a' && wsSource[iSourceIdx] <= 'z') ||
384 (wsSource[iSourceIdx] >= 'A' && wsSource[iSourceIdx] <= 'Z')) {
385 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
386 ++iFormatIdx;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700387 }
tsepez4f1f41f2016-03-28 14:13:16 -0700388 ++iSourceIdx;
389 } else {
390 ++iFormatIdx;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700391 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700392 } break;
393 case '9': {
tsepez4f1f41f2016-03-28 14:13:16 -0700394 if (iSourceIdx < wsSource.GetLength()) {
395 if (wsSource[iSourceIdx] >= '0' && wsSource[iSourceIdx] <= '9') {
396 wsResult += wsSource[iSourceIdx];
397 ++iFormatIdx;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398 }
tsepez4f1f41f2016-03-28 14:13:16 -0700399 ++iSourceIdx;
400 } else {
401 ++iFormatIdx;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 }
tsepez4f1f41f2016-03-28 14:13:16 -0700403 } break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700404 case '*': {
tsepez4f1f41f2016-03-28 14:13:16 -0700405 if (iSourceIdx < wsSource.GetLength()) {
406 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
407 ++iSourceIdx;
408 } else {
409 ++iFormatIdx;
410 }
411 } break;
412 default: {
413 wsResult += wsFormat[iFormatIdx];
414 ++iFormatIdx;
415 } break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700416 }
417 }
tsepez4f1f41f2016-03-28 14:13:16 -0700418 return wsResult;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700419}
420
Tom Sepezb1670b52017-02-16 17:01:00 -0800421bool util::scand(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700422 const std::vector<CJS_Value>& params,
423 CJS_Value& vRet,
424 CFX_WideString& sError) {
Lei Zhang574b5742017-03-30 12:41:55 -0700425 if (params.size() < 2)
tsepez4cf55152016-11-02 14:37:54 -0700426 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700427
tsepezb4694242016-08-15 16:44:55 -0700428 CFX_WideString sFormat = params[0].ToCFXWideString(pRuntime);
429 CFX_WideString sDate = params[1].ToCFXWideString(pRuntime);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700430 double dDate = JS_GetDateTime();
431 if (sDate.GetLength() > 0) {
Lei Zhang9559b7a2015-12-21 11:12:20 -0800432 dDate = CJS_PublicMethods::MakeRegularDate(sDate, sFormat, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700433 }
434
435 if (!JS_PortIsNan(dDate)) {
tsepezb4694242016-08-15 16:44:55 -0700436 vRet = CJS_Value(pRuntime, CJS_Date(pRuntime, dDate));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700437 } else {
tsepezf3dc8c62016-08-10 06:29:29 -0700438 vRet.SetNull(pRuntime);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700439 }
440
tsepez4cf55152016-11-02 14:37:54 -0700441 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700442}
443
Tom Sepezb1670b52017-02-16 17:01:00 -0800444bool util::byteToChar(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700445 const std::vector<CJS_Value>& params,
446 CJS_Value& vRet,
447 CFX_WideString& sError) {
tsepez90d87792016-03-29 09:21:54 -0700448 if (params.size() < 1) {
tsepezcd5dc852016-09-08 11:23:24 -0700449 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
tsepez4cf55152016-11-02 14:37:54 -0700450 return false;
tsepez90d87792016-03-29 09:21:54 -0700451 }
tsepezf3dc8c62016-08-10 06:29:29 -0700452
tsepezb4694242016-08-15 16:44:55 -0700453 int arg = params[0].ToInt(pRuntime);
tsepez90d87792016-03-29 09:21:54 -0700454 if (arg < 0 || arg > 255) {
tsepezcd5dc852016-09-08 11:23:24 -0700455 sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
tsepez4cf55152016-11-02 14:37:54 -0700456 return false;
tsepez90d87792016-03-29 09:21:54 -0700457 }
tsepezf3dc8c62016-08-10 06:29:29 -0700458
Dan Sinclair812e96c2017-03-13 16:43:37 -0400459 CFX_WideString wStr(static_cast<wchar_t>(arg));
tsepezf3dc8c62016-08-10 06:29:29 -0700460 vRet = CJS_Value(pRuntime, wStr.c_str());
tsepez4cf55152016-11-02 14:37:54 -0700461 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700462}