blob: 3338a3a1260f9955fc6de3d4537b6ac2f313a5bd [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>
Lei Zhange247ec42017-04-20 21:41:36 -070012#include <cwctype>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050013#include <string>
14#include <vector>
15
Dan Sinclaircfb19442017-04-20 13:13:04 -040016#include "core/fxcrt/fx_extension.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040017#include "fpdfsdk/javascript/JS_Define.h"
18#include "fpdfsdk/javascript/JS_EventHandler.h"
19#include "fpdfsdk/javascript/JS_Object.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040020#include "fpdfsdk/javascript/JS_Value.h"
21#include "fpdfsdk/javascript/PublicMethods.h"
Tom Sepezd6ae2af2017-02-16 11:49:55 -080022#include "fpdfsdk/javascript/cjs_event_context.h"
dsinclair64376be2016-03-31 20:03:24 -070023#include "fpdfsdk/javascript/cjs_runtime.h"
Dan Sinclairf766ad22016-03-14 13:51:24 -040024#include "fpdfsdk/javascript/resource.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070025
Nico Weber9d8ec5a2015-08-04 13:00:21 -070026#if _FX_OS_ == _FX_ANDROID_
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070027#include <ctype.h>
28#endif
29
Tom Sepez04557b82017-02-16 09:43:10 -080030JSConstSpec CJS_Util::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070031
Tom Sepez04557b82017-02-16 09:43:10 -080032JSPropertySpec CJS_Util::PropertySpecs[] = {{0, 0, 0}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070033
Tom Sepez04557b82017-02-16 09:43:10 -080034JSMethodSpec CJS_Util::MethodSpecs[] = {
Tom Sepez9b99b632017-02-21 15:05:57 -080035 {"printd", printd_static}, {"printf", printf_static},
36 {"printx", printx_static}, {"scand", scand_static},
37 {"byteToChar", byteToChar_static}, {0, 0}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070038
Nico Weber9d8ec5a2015-08-04 13:00:21 -070039IMPLEMENT_JS_CLASS(CJS_Util, util)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070040
Nico Weber9d8ec5a2015-08-04 13:00:21 -070041#define UTIL_INT 0
42#define UTIL_DOUBLE 1
43#define UTIL_STRING 2
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070044
tsepez86a61dc2016-03-25 10:00:11 -070045namespace {
46
47// Map PDF-style directives to equivalent wcsftime directives. Not
48// all have direct equivalents, though.
49struct TbConvert {
Dan Sinclair812e96c2017-03-13 16:43:37 -040050 const wchar_t* lpszJSMark;
51 const wchar_t* lpszCppMark;
tsepez86a61dc2016-03-25 10:00:11 -070052};
53
54// Map PDF-style directives lacking direct wcsftime directives to
55// the value with which they will be replaced.
56struct TbConvertAdditional {
Dan Sinclair812e96c2017-03-13 16:43:37 -040057 const wchar_t* lpszJSMark;
tsepez86a61dc2016-03-25 10:00:11 -070058 int iValue;
59};
60
61const TbConvert TbConvertTable[] = {
62 {L"mmmm", L"%B"}, {L"mmm", L"%b"}, {L"mm", L"%m"}, {L"dddd", L"%A"},
63 {L"ddd", L"%a"}, {L"dd", L"%d"}, {L"yyyy", L"%Y"}, {L"yy", L"%y"},
64 {L"HH", L"%H"}, {L"hh", L"%I"}, {L"MM", L"%M"}, {L"ss", L"%S"},
65 {L"TT", L"%p"},
66#if defined(_WIN32)
67 {L"tt", L"%p"}, {L"h", L"%#I"},
68#else
69 {L"tt", L"%P"}, {L"h", L"%l"},
70#endif
71};
72
73int ParseDataType(std::wstring* sFormat) {
tsepez4cf55152016-11-02 14:37:54 -070074 bool bPercent = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070075 for (size_t i = 0; i < sFormat->length(); ++i) {
76 wchar_t c = (*sFormat)[i];
77 if (c == L'%') {
78 bPercent = true;
79 continue;
Tom Sepez2f2ffec2015-07-23 14:42:09 -070080 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070081
Nico Weber9d8ec5a2015-08-04 13:00:21 -070082 if (bPercent) {
83 if (c == L'c' || c == L'C' || c == L'd' || c == L'i' || c == L'o' ||
84 c == L'u' || c == L'x' || c == L'X') {
85 return UTIL_INT;
86 }
87 if (c == L'e' || c == L'E' || c == L'f' || c == L'g' || c == L'G') {
88 return UTIL_DOUBLE;
89 }
90 if (c == L's' || c == L'S') {
91 // Map s to S since we always deal internally
92 // with wchar_t strings.
93 (*sFormat)[i] = L'S';
94 return UTIL_STRING;
95 }
96 if (c == L'.' || c == L'+' || c == L'-' || c == L'#' || c == L' ' ||
Lei Zhange247ec42017-04-20 21:41:36 -070097 std::iswdigit(c)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070098 continue;
99 }
100 break;
101 }
102 }
103
104 return -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700105}
106
tsepez86a61dc2016-03-25 10:00:11 -0700107} // namespace
108
109util::util(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {}
110
111util::~util() {}
112
Tom Sepezb1670b52017-02-16 17:01:00 -0800113bool util::printf(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700114 const std::vector<CJS_Value>& params,
115 CJS_Value& vRet,
116 CFX_WideString& sError) {
Lei Zhang574b5742017-03-30 12:41:55 -0700117 const size_t iSize = params.size();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700118 if (iSize < 1)
tsepez4cf55152016-11-02 14:37:54 -0700119 return false;
Lei Zhang574b5742017-03-30 12:41:55 -0700120
tsepezb4694242016-08-15 16:44:55 -0700121 std::wstring c_ConvChar(params[0].ToCFXWideString(pRuntime).c_str());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700122 std::vector<std::wstring> c_strConvers;
123 int iOffset = 0;
124 int iOffend = 0;
125 c_ConvChar.insert(c_ConvChar.begin(), L'S');
126 while (iOffset != -1) {
127 iOffend = c_ConvChar.find(L"%", iOffset + 1);
128 std::wstring strSub;
129 if (iOffend == -1)
130 strSub = c_ConvChar.substr(iOffset);
131 else
132 strSub = c_ConvChar.substr(iOffset, iOffend - iOffset);
133 c_strConvers.push_back(strSub);
134 iOffset = iOffend;
135 }
136
137 std::wstring c_strResult;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700138 std::wstring c_strFormat;
Lei Zhang574b5742017-03-30 12:41:55 -0700139 for (size_t iIndex = 0; iIndex < c_strConvers.size(); ++iIndex) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700140 c_strFormat = c_strConvers[iIndex];
141 if (iIndex == 0) {
142 c_strResult = c_strFormat;
143 continue;
144 }
145
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700146 if (iIndex >= iSize) {
147 c_strResult += c_strFormat;
148 continue;
149 }
150
Lei Zhang574b5742017-03-30 12:41:55 -0700151 CFX_WideString strSegment;
tsepez86a61dc2016-03-25 10:00:11 -0700152 switch (ParseDataType(&c_strFormat)) {
Dan Sinclair0c998292017-07-13 09:58:52 -0400153 case UTIL_INT: {
154 int dot = c_strFormat.find(L".", 0);
155 if (dot != -1) {
156 size_t len = 0;
157 for (size_t i = dot + 1; i < c_strFormat.length(); ++i) {
158 wchar_t c = c_strFormat[i];
159 if (std::iswdigit(c)) {
160 ++len;
161 continue;
162 }
163 break;
164 }
165
166 // Windows has a max of ~261 characters in the format string of
167 // the form %0.261x. We're just going to bail out if the format
168 // would be over 3 or more characters long.
169 if (len > 2)
170 return false;
171 }
tsepezb4694242016-08-15 16:44:55 -0700172 strSegment.Format(c_strFormat.c_str(), params[iIndex].ToInt(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700173 break;
Dan Sinclair0c998292017-07-13 09:58:52 -0400174 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700175 case UTIL_DOUBLE:
tsepezf3dc8c62016-08-10 06:29:29 -0700176 strSegment.Format(c_strFormat.c_str(),
tsepezb4694242016-08-15 16:44:55 -0700177 params[iIndex].ToDouble(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700178 break;
179 case UTIL_STRING:
tsepezb4694242016-08-15 16:44:55 -0700180 strSegment.Format(c_strFormat.c_str(),
181 params[iIndex].ToCFXWideString(pRuntime).c_str());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700182 break;
183 default:
184 strSegment.Format(L"%S", c_strFormat.c_str());
185 break;
186 }
Lei Zhang1e25e122017-06-16 02:14:40 -0700187 c_strResult += strSegment.c_str();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700188 }
189
190 c_strResult.erase(c_strResult.begin());
tsepezf3dc8c62016-08-10 06:29:29 -0700191 vRet = CJS_Value(pRuntime, c_strResult.c_str());
tsepez4cf55152016-11-02 14:37:54 -0700192 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700193}
194
Tom Sepezb1670b52017-02-16 17:01:00 -0800195bool util::printd(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700196 const std::vector<CJS_Value>& params,
197 CJS_Value& vRet,
198 CFX_WideString& sError) {
Lei Zhang574b5742017-03-30 12:41:55 -0700199 const size_t iSize = params.size();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700200 if (iSize < 2)
tsepez4cf55152016-11-02 14:37:54 -0700201 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700202
Lei Zhang574b5742017-03-30 12:41:55 -0700203 const CJS_Value& p1 = params[0];
204 const CJS_Value& p2 = params[1];
tsepezf3c88322016-08-09 07:30:38 -0700205 CJS_Date jsDate;
tsepezb4694242016-08-15 16:44:55 -0700206 if (!p2.ConvertToDate(pRuntime, jsDate)) {
tsepezcd5dc852016-09-08 11:23:24 -0700207 sError = JSGetStringFromID(IDS_STRING_JSPRINT1);
tsepez4cf55152016-11-02 14:37:54 -0700208 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209 }
210
tsepezb4694242016-08-15 16:44:55 -0700211 if (!jsDate.IsValidDate(pRuntime)) {
tsepezcd5dc852016-09-08 11:23:24 -0700212 sError = JSGetStringFromID(IDS_STRING_JSPRINT2);
tsepez4cf55152016-11-02 14:37:54 -0700213 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700214 }
215
Tom Sepez39bfe122015-09-17 15:25:23 -0700216 if (p1.GetType() == CJS_Value::VT_number) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217 CFX_WideString swResult;
tsepezb4694242016-08-15 16:44:55 -0700218 switch (p1.ToInt(pRuntime)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700219 case 0:
tsepezb4694242016-08-15 16:44:55 -0700220 swResult.Format(L"D:%04d%02d%02d%02d%02d%02d", jsDate.GetYear(pRuntime),
221 jsDate.GetMonth(pRuntime) + 1, jsDate.GetDay(pRuntime),
222 jsDate.GetHours(pRuntime), jsDate.GetMinutes(pRuntime),
223 jsDate.GetSeconds(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224 break;
225 case 1:
tsepezf3c88322016-08-09 07:30:38 -0700226 swResult.Format(L"%04d.%02d.%02d %02d:%02d:%02d",
tsepezb4694242016-08-15 16:44:55 -0700227 jsDate.GetYear(pRuntime), jsDate.GetMonth(pRuntime) + 1,
228 jsDate.GetDay(pRuntime), jsDate.GetHours(pRuntime),
229 jsDate.GetMinutes(pRuntime),
230 jsDate.GetSeconds(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700231 break;
232 case 2:
tsepezf3c88322016-08-09 07:30:38 -0700233 swResult.Format(L"%04d/%02d/%02d %02d:%02d:%02d",
tsepezb4694242016-08-15 16:44:55 -0700234 jsDate.GetYear(pRuntime), jsDate.GetMonth(pRuntime) + 1,
235 jsDate.GetDay(pRuntime), jsDate.GetHours(pRuntime),
236 jsDate.GetMinutes(pRuntime),
237 jsDate.GetSeconds(pRuntime));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238 break;
239 default:
tsepezcd5dc852016-09-08 11:23:24 -0700240 sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
tsepez4cf55152016-11-02 14:37:54 -0700241 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700242 }
243
tsepezf3dc8c62016-08-10 06:29:29 -0700244 vRet = CJS_Value(pRuntime, swResult.c_str());
tsepez4cf55152016-11-02 14:37:54 -0700245 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700246 }
tsepez86a61dc2016-03-25 10:00:11 -0700247
Tom Sepez39bfe122015-09-17 15:25:23 -0700248 if (p1.GetType() == CJS_Value::VT_string) {
tsepezb4694242016-08-15 16:44:55 -0700249 if (iSize > 2 && params[2].ToBool(pRuntime)) {
tsepezcd5dc852016-09-08 11:23:24 -0700250 sError = JSGetStringFromID(IDS_STRING_JSNOTSUPPORT);
tsepez4cf55152016-11-02 14:37:54 -0700251 return false; // currently, it doesn't support XFAPicture.
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700252 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700253
tsepez86a61dc2016-03-25 10:00:11 -0700254 // Convert PDF-style format specifiers to wcsftime specifiers. Remove any
255 // pre-existing %-directives before inserting our own.
tsepezb4694242016-08-15 16:44:55 -0700256 std::basic_string<wchar_t> cFormat = p1.ToCFXWideString(pRuntime).c_str();
tsepez86a61dc2016-03-25 10:00:11 -0700257 cFormat.erase(std::remove(cFormat.begin(), cFormat.end(), '%'),
258 cFormat.end());
259
260 for (size_t i = 0; i < FX_ArraySize(TbConvertTable); ++i) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261 int iStart = 0;
262 int iEnd;
tsepez86a61dc2016-03-25 10:00:11 -0700263 while ((iEnd = cFormat.find(TbConvertTable[i].lpszJSMark, iStart)) !=
264 -1) {
265 cFormat.replace(iEnd, FXSYS_wcslen(TbConvertTable[i].lpszJSMark),
266 TbConvertTable[i].lpszCppMark);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700267 iStart = iEnd;
268 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700269 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700270
tsepezb4694242016-08-15 16:44:55 -0700271 int iYear = jsDate.GetYear(pRuntime);
Lei Zhang2bf942d2017-06-16 13:48:19 -0700272 if (iYear < 0) {
273 sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
274 return false;
275 }
276
tsepezb4694242016-08-15 16:44:55 -0700277 int iMonth = jsDate.GetMonth(pRuntime);
278 int iDay = jsDate.GetDay(pRuntime);
279 int iHour = jsDate.GetHours(pRuntime);
280 int iMin = jsDate.GetMinutes(pRuntime);
281 int iSec = jsDate.GetSeconds(pRuntime);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700282
Lei Zhang1e25e122017-06-16 02:14:40 -0700283 static const TbConvertAdditional cTableAd[] = {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700284 {L"m", iMonth + 1}, {L"d", iDay},
285 {L"H", iHour}, {L"h", iHour > 12 ? iHour - 12 : iHour},
286 {L"M", iMin}, {L"s", iSec},
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700287 };
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700288
tsepez86a61dc2016-03-25 10:00:11 -0700289 for (size_t i = 0; i < FX_ArraySize(cTableAd); ++i) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700290 CFX_WideString sValue;
Lei Zhangb9c31972015-08-11 14:09:35 -0700291 sValue.Format(L"%d", cTableAd[i].iValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700292
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700293 int iStart = 0;
294 int iEnd;
Lei Zhangb9c31972015-08-11 14:09:35 -0700295 while ((iEnd = cFormat.find(cTableAd[i].lpszJSMark, iStart)) != -1) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700296 if (iEnd > 0) {
297 if (cFormat[iEnd - 1] == L'%') {
298 iStart = iEnd + 1;
299 continue;
300 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700301 }
Lei Zhang1e25e122017-06-16 02:14:40 -0700302 cFormat.replace(iEnd, FXSYS_wcslen(cTableAd[i].lpszJSMark),
303 sValue.c_str());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304 iStart = iEnd;
305 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700306 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700307
tsepez86a61dc2016-03-25 10:00:11 -0700308 struct tm time = {};
309 time.tm_year = iYear - 1900;
310 time.tm_mon = iMonth;
311 time.tm_mday = iDay;
312 time.tm_hour = iHour;
313 time.tm_min = iMin;
314 time.tm_sec = iSec;
315
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700316 wchar_t buf[64] = {};
Lei Zhang2bf942d2017-06-16 13:48:19 -0700317 FXSYS_wcsftime(buf, 64, cFormat.c_str(), &time);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700318 cFormat = buf;
tsepezf3dc8c62016-08-10 06:29:29 -0700319 vRet = CJS_Value(pRuntime, cFormat.c_str());
tsepez4cf55152016-11-02 14:37:54 -0700320 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700321 }
tsepez86a61dc2016-03-25 10:00:11 -0700322
tsepezcd5dc852016-09-08 11:23:24 -0700323 sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR);
tsepez4cf55152016-11-02 14:37:54 -0700324 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700325}
326
Tom Sepezb1670b52017-02-16 17:01:00 -0800327bool util::printx(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700328 const std::vector<CJS_Value>& params,
329 CJS_Value& vRet,
330 CFX_WideString& sError) {
tsepez4f1f41f2016-03-28 14:13:16 -0700331 if (params.size() < 2) {
tsepezcd5dc852016-09-08 11:23:24 -0700332 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
tsepez4cf55152016-11-02 14:37:54 -0700333 return false;
tsepez4f1f41f2016-03-28 14:13:16 -0700334 }
tsepezf3dc8c62016-08-10 06:29:29 -0700335
tsepezb4694242016-08-15 16:44:55 -0700336 vRet = CJS_Value(pRuntime, printx(params[0].ToCFXWideString(pRuntime),
337 params[1].ToCFXWideString(pRuntime))
338 .c_str());
tsepezf3dc8c62016-08-10 06:29:29 -0700339
tsepez4cf55152016-11-02 14:37:54 -0700340 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700341}
342
tsepez4f1f41f2016-03-28 14:13:16 -0700343enum CaseMode { kPreserveCase, kUpperCase, kLowerCase };
344
Dan Sinclair812e96c2017-03-13 16:43:37 -0400345static wchar_t TranslateCase(wchar_t input, CaseMode eMode) {
Lei Zhangef002c82017-04-24 16:28:07 -0700346 if (eMode == kLowerCase && FXSYS_isupper(input))
tsepez4f1f41f2016-03-28 14:13:16 -0700347 return input | 0x20;
Lei Zhangef002c82017-04-24 16:28:07 -0700348 if (eMode == kUpperCase && FXSYS_islower(input))
tsepez4f1f41f2016-03-28 14:13:16 -0700349 return input & ~0x20;
350 return input;
351}
352
353CFX_WideString util::printx(const CFX_WideString& wsFormat,
354 const CFX_WideString& wsSource) {
355 CFX_WideString wsResult;
356 FX_STRSIZE iSourceIdx = 0;
357 FX_STRSIZE iFormatIdx = 0;
358 CaseMode eCaseMode = kPreserveCase;
359 bool bEscaped = false;
360 while (iFormatIdx < wsFormat.GetLength()) {
361 if (bEscaped) {
362 bEscaped = false;
363 wsResult += wsFormat[iFormatIdx];
364 ++iFormatIdx;
365 continue;
366 }
367 switch (wsFormat[iFormatIdx]) {
368 case '\\': {
369 bEscaped = true;
370 ++iFormatIdx;
371 } break;
372 case '<': {
373 eCaseMode = kLowerCase;
374 ++iFormatIdx;
375 } break;
376 case '>': {
377 eCaseMode = kUpperCase;
378 ++iFormatIdx;
379 } break;
380 case '=': {
381 eCaseMode = kPreserveCase;
382 ++iFormatIdx;
383 } break;
384 case '?': {
385 if (iSourceIdx < wsSource.GetLength()) {
386 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
387 ++iSourceIdx;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700388 }
tsepez4f1f41f2016-03-28 14:13:16 -0700389 ++iFormatIdx;
390 } break;
391 case 'X': {
392 if (iSourceIdx < wsSource.GetLength()) {
Lei Zhangef002c82017-04-24 16:28:07 -0700393 if (FXSYS_iswalnum(wsSource[iSourceIdx])) {
tsepez4f1f41f2016-03-28 14:13:16 -0700394 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
395 ++iFormatIdx;
396 }
397 ++iSourceIdx;
398 } else {
399 ++iFormatIdx;
400 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700401 } break;
402 case 'A': {
tsepez4f1f41f2016-03-28 14:13:16 -0700403 if (iSourceIdx < wsSource.GetLength()) {
Lei Zhangef002c82017-04-24 16:28:07 -0700404 if (FXSYS_iswalpha(wsSource[iSourceIdx])) {
tsepez4f1f41f2016-03-28 14:13:16 -0700405 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
406 ++iFormatIdx;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700407 }
tsepez4f1f41f2016-03-28 14:13:16 -0700408 ++iSourceIdx;
409 } else {
410 ++iFormatIdx;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700411 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700412 } break;
413 case '9': {
tsepez4f1f41f2016-03-28 14:13:16 -0700414 if (iSourceIdx < wsSource.GetLength()) {
Lei Zhangef002c82017-04-24 16:28:07 -0700415 if (std::iswdigit(wsSource[iSourceIdx])) {
tsepez4f1f41f2016-03-28 14:13:16 -0700416 wsResult += wsSource[iSourceIdx];
417 ++iFormatIdx;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700418 }
tsepez4f1f41f2016-03-28 14:13:16 -0700419 ++iSourceIdx;
420 } else {
421 ++iFormatIdx;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700422 }
tsepez4f1f41f2016-03-28 14:13:16 -0700423 } break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700424 case '*': {
tsepez4f1f41f2016-03-28 14:13:16 -0700425 if (iSourceIdx < wsSource.GetLength()) {
426 wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
427 ++iSourceIdx;
428 } else {
429 ++iFormatIdx;
430 }
431 } break;
432 default: {
433 wsResult += wsFormat[iFormatIdx];
434 ++iFormatIdx;
435 } break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436 }
437 }
tsepez4f1f41f2016-03-28 14:13:16 -0700438 return wsResult;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700439}
440
Tom Sepezb1670b52017-02-16 17:01:00 -0800441bool util::scand(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700442 const std::vector<CJS_Value>& params,
443 CJS_Value& vRet,
444 CFX_WideString& sError) {
Lei Zhang574b5742017-03-30 12:41:55 -0700445 if (params.size() < 2)
tsepez4cf55152016-11-02 14:37:54 -0700446 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700447
tsepezb4694242016-08-15 16:44:55 -0700448 CFX_WideString sFormat = params[0].ToCFXWideString(pRuntime);
449 CFX_WideString sDate = params[1].ToCFXWideString(pRuntime);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700450 double dDate = JS_GetDateTime();
451 if (sDate.GetLength() > 0) {
Lei Zhang9559b7a2015-12-21 11:12:20 -0800452 dDate = CJS_PublicMethods::MakeRegularDate(sDate, sFormat, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700453 }
454
455 if (!JS_PortIsNan(dDate)) {
tsepezb4694242016-08-15 16:44:55 -0700456 vRet = CJS_Value(pRuntime, CJS_Date(pRuntime, dDate));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700457 } else {
tsepezf3dc8c62016-08-10 06:29:29 -0700458 vRet.SetNull(pRuntime);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700459 }
460
tsepez4cf55152016-11-02 14:37:54 -0700461 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700462}
463
Tom Sepezb1670b52017-02-16 17:01:00 -0800464bool util::byteToChar(CJS_Runtime* pRuntime,
tsepez4cf55152016-11-02 14:37:54 -0700465 const std::vector<CJS_Value>& params,
466 CJS_Value& vRet,
467 CFX_WideString& sError) {
tsepez90d87792016-03-29 09:21:54 -0700468 if (params.size() < 1) {
tsepezcd5dc852016-09-08 11:23:24 -0700469 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
tsepez4cf55152016-11-02 14:37:54 -0700470 return false;
tsepez90d87792016-03-29 09:21:54 -0700471 }
tsepezf3dc8c62016-08-10 06:29:29 -0700472
tsepezb4694242016-08-15 16:44:55 -0700473 int arg = params[0].ToInt(pRuntime);
tsepez90d87792016-03-29 09:21:54 -0700474 if (arg < 0 || arg > 255) {
tsepezcd5dc852016-09-08 11:23:24 -0700475 sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
tsepez4cf55152016-11-02 14:37:54 -0700476 return false;
tsepez90d87792016-03-29 09:21:54 -0700477 }
tsepezf3dc8c62016-08-10 06:29:29 -0700478
Dan Sinclair812e96c2017-03-13 16:43:37 -0400479 CFX_WideString wStr(static_cast<wchar_t>(arg));
tsepezf3dc8c62016-08-10 06:29:29 -0700480 vRet = CJS_Value(pRuntime, wStr.c_str());
tsepez4cf55152016-11-02 14:37:54 -0700481 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700482}