• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "../../include/javascript/JavaScript.h"
8 #include "../../include/javascript/IJavaScript.h"
9 #include "../../include/javascript/JS_Define.h"
10 #include "../../include/javascript/JS_Object.h"
11 #include "../../include/javascript/JS_Value.h"
12 #include "../../include/javascript/util.h"
13 #include "../../include/javascript/PublicMethods.h"
14 #include "../../include/javascript/resource.h"
15 #include "../../include/javascript/JS_Context.h"
16 #include "../../include/javascript/JS_EventHandler.h"
17 #include "../../include/javascript/JS_Runtime.h"
18 
19 #if _FX_OS_  == _FX_ANDROID_
20 #include <ctype.h>
21 #endif
22 
GetIsolate(IFXJS_Context * cc)23 static v8::Isolate* GetIsolate(IFXJS_Context* cc)
24 {
25 	CJS_Context* pContext = (CJS_Context *)cc;
26 	ASSERT(pContext != NULL);
27 
28 	CJS_Runtime* pRuntime = pContext->GetJSRuntime();
29 	ASSERT(pRuntime != NULL);
30 
31 	return pRuntime->GetIsolate();
32 }
33 
34 BEGIN_JS_STATIC_CONST(CJS_Util)
END_JS_STATIC_CONST()35 END_JS_STATIC_CONST()
36 
37 BEGIN_JS_STATIC_PROP(CJS_Util)
38 END_JS_STATIC_PROP()
39 
40 BEGIN_JS_STATIC_METHOD(CJS_Util)
41 	JS_STATIC_METHOD_ENTRY(printd)
42 	JS_STATIC_METHOD_ENTRY(printf)
43 	JS_STATIC_METHOD_ENTRY(printx)
44 	JS_STATIC_METHOD_ENTRY(scand)
45 	JS_STATIC_METHOD_ENTRY(byteToChar)
46 END_JS_STATIC_METHOD()
47 
48 IMPLEMENT_JS_CLASS(CJS_Util,util)
49 
50 util::util(CJS_Object *pJSObject) : CJS_EmbedObj(pJSObject)
51 {
52 }
53 
~util(void)54 util::~util(void)
55 {
56 }
57 
58 
59 struct stru_TbConvert
60 {
61 	FX_LPCWSTR lpszJSMark;
62 	FX_LPCWSTR lpszCppMark;
63 };
64 
65 const stru_TbConvert fcTable[] = {
66 	{ L"mmmm", L"%B" },
67 	{ L"mmm", L"%b" },
68 	{ L"mm",  L"%m" },
69 	//"m"
70 	{ L"dddd", L"%A" },
71 	{ L"ddd", L"%a" },
72 	{ L"dd",  L"%d" },
73 	//"d",   "%w",
74 	{ L"yyyy", L"%Y" },
75 	{ L"yy",  L"%y" },
76 	{ L"HH",  L"%H" },
77 	//"H"
78 	{ L"hh",  L"%I" },
79 	//"h"
80 	{ L"MM",  L"%M" },
81 	//"M"
82 	{ L"ss",  L"%S" },
83 	//"s
84 	{ L"TT",  L"%p" },
85 	//"t"
86 #if defined(_WIN32)
87 	{ L"tt",  L"%p" },
88 	{ L"h",  L"%#I" },
89 #else
90 	{ L"tt",  L"%P" },
91 	{ L"h",  L"%l" },
92 #endif
93 };
94 
95 #define UTIL_INT			0
96 #define UTIL_DOUBLE			1
97 #define UTIL_STRING			2
98 
ParstDataType(std::wstring * sFormat)99 int util::ParstDataType(std::wstring* sFormat)
100 {
101         size_t i = 0;
102 	bool bPercent = FALSE;
103 	for (i=0; i<sFormat->length(); ++i)
104 	{
105 		wchar_t c = (*sFormat)[i];
106 		if (c == L'%')
107 		{
108 			bPercent = true;
109 			continue;
110 		}
111 
112 		if (bPercent)
113 		{
114 			if (c == L'c' || c == L'C' || c == L'd' || c == L'i' || c == L'o' || c == L'u' || c == L'x' || c == L'X')
115 			{
116 				return UTIL_INT;
117 			}
118 			else if (c == L'e' || c == L'E' || c == L'f' || c == L'g' || c == L'G')
119 			{
120 				return UTIL_DOUBLE;
121 			}
122 			else if (c == L's' || c == L'S')
123 			{
124 				// Map s to S since we always deal internally
125 				// with wchar_t strings.
126 				(*sFormat)[i] = L'S';
127 				return UTIL_STRING;
128 			}
129 			else if (c == L'.' || c == L'+' || c == L'-' || c == L'#' || c == L' ' || CJS_PublicMethods::IsDigit(c))
130 			{
131 				continue;
132 			}
133 			else break;
134 		}
135 	}
136 
137 	return -1;
138 }
139 
printf(IFXJS_Context * cc,const CJS_Parameters & params,CJS_Value & vRet,CFX_WideString & sError)140 FX_BOOL util::printf(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
141 {
142 	int iSize = params.size();
143 	if (iSize < 1)
144 		return FALSE;
145 	std::wstring c_ConvChar(params[0].ToCFXWideString().c_str());
146 	std::vector<std::wstring> c_strConvers;
147 	int iOffset = 0;
148 	int iOffend = 0;
149 	c_ConvChar.insert(c_ConvChar.begin(),L'S');
150 	while(iOffset != -1)
151 	{
152 		iOffend = c_ConvChar.find(L"%",iOffset+1);
153 		std::wstring strSub;
154 		if (iOffend == -1)
155 			strSub = c_ConvChar.substr(iOffset);
156 		else
157 			strSub = c_ConvChar.substr(iOffset ,iOffend - iOffset);
158 		c_strConvers.push_back(strSub);
159 		iOffset = iOffend ;
160 	}
161 
162 	std::wstring c_strResult;
163 
164 	//for(int iIndex = 1;iIndex < params.size();iIndex++)
165 	std::wstring c_strFormat;
166 	for(int iIndex = 0;iIndex < (int)c_strConvers.size();iIndex++)
167 	{
168 		c_strFormat = c_strConvers[iIndex];
169 		if (iIndex == 0)
170 		{
171 			c_strResult = c_strFormat;
172 			continue;
173 		}
174 
175 
176 		CFX_WideString strSegment;
177 		if (iIndex >= iSize) {
178 			c_strResult += c_strFormat;
179 			continue;
180 		}
181 
182 		switch (ParstDataType(&c_strFormat))
183 		{
184 			case UTIL_INT:
185 				strSegment.Format(c_strFormat.c_str(), params[iIndex].ToInt());
186 				break;
187 			case UTIL_DOUBLE:
188 				strSegment.Format(c_strFormat.c_str(), params[iIndex].ToDouble());
189 				break;
190 			case UTIL_STRING:
191 				strSegment.Format(c_strFormat.c_str(), params[iIndex].ToCFXWideString().c_str());
192 				break;
193 			default:
194 				strSegment.Format(L"%S", c_strFormat.c_str());
195 				break;
196 		}
197 		c_strResult += strSegment.GetBuffer(strSegment.GetLength()+1);
198 	}
199 
200 	c_strResult.erase(c_strResult.begin());
201 	vRet = c_strResult.c_str();
202 	return TRUE;
203 }
204 
printd(IFXJS_Context * cc,const CJS_Parameters & params,CJS_Value & vRet,CFX_WideString & sError)205 FX_BOOL util::printd(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
206 {
207 	v8::Isolate* isolate = GetIsolate(cc);
208 
209 	int iSize = params.size();
210 	if (iSize < 2)
211 		return FALSE;
212 
213 	CJS_Value p1(isolate);
214 	p1 = params[0];
215 
216 	CJS_Value p2 = params[1];
217 	CJS_Date jsDate(isolate);
218 	if (!p2.ConvertToDate(jsDate))
219 	{
220 		sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPRINT1);
221 		return FALSE;
222 	}
223 
224 	if (!jsDate.IsValidDate())
225 	{
226 		sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPRINT2);
227 		return FALSE;
228 	}
229 
230 	if (p1.GetType() == VT_number)
231 	{
232 		int nFormat = p1.ToInt();
233 		CFX_WideString swResult;
234 
235 		switch (nFormat)
236 		{
237 		case 0:
238 			swResult.Format(L"D:%04d%02d%02d%02d%02d%02d",
239 				jsDate.GetYear(),
240 				jsDate.GetMonth() + 1,
241 				jsDate.GetDay(),
242 				jsDate.GetHours(),
243 				jsDate.GetMinutes(),
244 				jsDate.GetSeconds());
245 			break;
246 		case 1:
247 			swResult.Format(L"%04d.%02d.%02d %02d:%02d:%02d",
248 				jsDate.GetYear(),
249 				jsDate.GetMonth() + 1,
250 				jsDate.GetDay(),
251 				jsDate.GetHours(),
252 				jsDate.GetMinutes(),
253 				jsDate.GetSeconds());
254 			break;
255 		case 2:
256 			swResult.Format(L"%04d/%02d/%02d %02d:%02d:%02d",
257 				jsDate.GetYear(),
258 				jsDate.GetMonth() + 1,
259 				jsDate.GetDay(),
260 				jsDate.GetHours(),
261 				jsDate.GetMinutes(),
262 				jsDate.GetSeconds());
263 			break;
264 		default:
265 			return FALSE;
266 		}
267 
268 		vRet = swResult.c_str();
269 		return TRUE;
270 	}
271 	else if (p1.GetType() == VT_string)
272 	{
273 		std::basic_string<wchar_t> cFormat = p1.ToCFXWideString().c_str();
274 
275 		bool bXFAPicture = false;
276 		if (iSize > 2)
277 		{
278 			bXFAPicture = params[2].ToBool();
279 		}
280 
281 		if (bXFAPicture)
282 		{
283 			return FALSE; //currently, it doesn't support XFAPicture.
284 		}
285 
286         int iIndex;
287 		for(iIndex = 0;iIndex<sizeof(fcTable)/sizeof(stru_TbConvert);iIndex++)
288 		{
289 			int iStart = 0;
290 			int iEnd;
291 			while((iEnd = cFormat.find(fcTable[iIndex].lpszJSMark, iStart)) != -1)
292 			{
293 				cFormat.replace(iEnd, FXSYS_wcslen(fcTable[iIndex].lpszJSMark), fcTable[iIndex].lpszCppMark);
294 				iStart = iEnd;
295 			}
296 		}
297 
298 		int iYear,iMonth,iDay,iHour,iMin,iSec;
299 		iYear = jsDate.GetYear();
300 		iMonth = jsDate.GetMonth();
301 		iDay = jsDate.GetDay();
302 		iHour = jsDate.GetHours();
303 		iMin = jsDate.GetMinutes();
304 		iSec = jsDate.GetSeconds();
305 
306 		struct tm time = {0};
307 		time.tm_year = iYear-1900;
308 		time.tm_mon = iMonth;
309 		time.tm_mday = iDay;
310 		time.tm_hour = iHour;
311 		time.tm_min = iMin;
312 		time.tm_sec = iSec;
313 		//COleDateTime cppTm(iYear,iMonth+1,iDay,iHour,iMin,iSec);
314 		//CString strFormat = cppTm.Format(cFormat.c_str());
315 
316 		struct stru_TbConvertAd
317 		{
318 			FX_LPCWSTR lpszJSMark;
319 			int     iValue;
320 		};
321 
322 		stru_TbConvertAd cTableAd[] ={
323 			{ L"m", iMonth+1 },
324 			{ L"d", iDay },
325 			{ L"H", iHour },
326 			{ L"h", iHour>12?iHour-12:iHour },
327 			{ L"M", iMin },
328 			{ L"s", iSec },
329 		};
330 
331 		//cFormat = strFormat.GetBuffer(strFormat.GetLength()+1);
332 		for(iIndex = 0;iIndex<sizeof(cTableAd)/sizeof(stru_TbConvertAd);iIndex++)
333 		{
334 			wchar_t tszValue[10];
335 			//_itot(cTableAd[iIndex].iValue,tszValue,10);
336 			CFX_WideString sValue;
337 			sValue.Format(L"%d",cTableAd[iIndex].iValue);
338 			memcpy(tszValue, (wchar_t *)sValue.GetBuffer(sValue.GetLength()+1),
339                                (sValue.GetLength()+1)*sizeof(wchar_t));
340 
341 			//strFormat.Replace(cTableAd[iIndex].lpszJSMark,"%d");
342 			//strFormat.Format(strFormat,cTableAd[iIndex].iValue);
343 			int iStart = 0;
344 			int iEnd;
345 			while((iEnd = cFormat.find(cTableAd[iIndex].lpszJSMark, iStart)) != -1)
346 			{
347 				if (iEnd > 0)
348 				{
349 					if (cFormat[iEnd-1] == L'%')
350 					{
351 						iStart = iEnd+1;
352 						continue;
353 					}
354 				}
355 				cFormat.replace(iEnd, FXSYS_wcslen(cTableAd[iIndex].lpszJSMark), tszValue);
356 				iStart = iEnd;
357 			}
358 		}
359 
360 		CFX_WideString strFormat;
361 //		strFormat.Format(L"%d,%d,%d,%d,%d,%d",iYear, iMonth, iDay, iHour, iMin, iSec);
362 //		CString strFormat = cppTm.Format(cFormat.c_str());
363 		wchar_t buf[64] = {0};
364 		strFormat = wcsftime(buf, 64, cFormat.c_str(), &time);
365 		cFormat = buf;
366 		vRet = cFormat.c_str();
367 		//rtRet = strFormat.GetBuffer(strFormat.GetLength()+1);
368 		return TRUE;
369 	}
370 	return FALSE;
371 }
372 
printd(const std::wstring & cFormat2,CJS_Date jsDate,bool bXFAPicture,std::wstring & cPurpose)373 void util::printd(const std::wstring &cFormat2, CJS_Date jsDate, bool bXFAPicture, std::wstring &cPurpose)
374 {
375 	std::wstring cFormat = cFormat2;
376 
377 	if (bXFAPicture)
378 	{
379 		return ; //currently, it doesn't support XFAPicture.
380 	}
381 
382     int iIndex;
383 	for(iIndex = 0;iIndex<sizeof(fcTable)/sizeof(stru_TbConvert);iIndex++)
384 	{
385 		int iStart = 0;
386 		int iEnd;
387 		while((iEnd = cFormat.find(fcTable[iIndex].lpszJSMark, iStart)) != -1)
388 		{
389 			cFormat.replace(iEnd,FXSYS_wcslen(fcTable[iIndex].lpszJSMark), fcTable[iIndex].lpszCppMark);
390 			iStart = iEnd;
391 		}
392 	}
393 
394 	int iYear,iMonth,iDay,iHour,iMin,iSec;
395 	iYear = jsDate.GetYear();
396 	iMonth = jsDate.GetMonth();
397 	iDay = jsDate.GetDay();
398 	iHour = jsDate.GetHours();
399 	iMin = jsDate.GetMinutes();
400 	iSec = jsDate.GetSeconds();
401 
402 	struct tm time = {0};
403 	time.tm_year = iYear-1900;
404 	time.tm_mon = iMonth;
405 	time.tm_mday = iDay;
406 	time.tm_hour = iHour;
407 	time.tm_min = iMin;
408 	time.tm_sec = iSec;
409 //	COleDateTime cppTm(iYear,iMonth+1,iDay,iHour,iMin,iSec);
410 	//CString strFormat = cppTm.Format(cFormat.c_str());
411 
412 	struct stru_TbConvertAd
413 	{
414 		FX_LPCWSTR lpszJSMark;
415 		int     iValue;
416 	};
417 
418 	stru_TbConvertAd cTableAd[] ={
419 		{ L"m", iMonth+1 },
420 		{ L"d", iDay },
421 		{ L"H", iHour },
422 		{ L"h", iHour>12?iHour-12:iHour },
423 		{ L"M", iMin },
424 		{ L"s", iSec },
425 	};
426 
427 	//cFormat = strFormat.GetBuffer(strFormat.GetLength()+1);
428 	for(iIndex = 0;iIndex<sizeof(cTableAd)/sizeof(stru_TbConvertAd);iIndex++)
429 	{
430 		wchar_t tszValue[10];
431 		//_itot(cTableAd[iIndex].iValue,tszValue,10);
432 		CFX_WideString sValue;
433 		sValue.Format(L"%d",cTableAd[iIndex].iValue);
434 		memcpy(tszValue, (wchar_t *)sValue.GetBuffer(sValue.GetLength()+1),sValue.GetLength()*sizeof(wchar_t));
435 
436 
437 		//strFormat.Replace(cTableAd[iIndex].lpszJSMark,"%d");
438 		//strFormat.Format(strFormat,cTableAd[iIndex].iValue);
439 		int iStart = 0;
440 		int iEnd;
441 		while((iEnd = cFormat.find(cTableAd[iIndex].lpszJSMark, iStart)) != -1)
442 		{
443 			if (iEnd > 0)
444 			{
445 				if (cFormat[iEnd-1] == L'%')
446 				{
447 					iStart = iEnd+1;
448 					continue;
449 				}
450 			}
451 			cFormat.replace(iEnd,FXSYS_wcslen(cTableAd[iIndex].lpszJSMark),tszValue);
452 			iStart = iEnd;
453 		}
454 	}
455 
456 	CFX_WideString strFormat;
457 	wchar_t buf[64] = {0};
458 	strFormat = wcsftime(buf, 64, cFormat.c_str(), &time);
459 	cFormat = buf;
460 	cPurpose = cFormat;
461 }
462 
printx(IFXJS_Context * cc,const CJS_Parameters & params,CJS_Value & vRet,CFX_WideString & sError)463 FX_BOOL util::printx(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
464 {
465 	int iSize = params.size();
466 	if (iSize<2)
467 		return FALSE;
468 	CFX_WideString sFormat = params[0].ToCFXWideString();
469 	CFX_WideString sSource = params[1].ToCFXWideString();
470 	std::string cFormat = CFX_ByteString::FromUnicode(sFormat).c_str();
471 	std::string cSource = CFX_ByteString::FromUnicode(sSource).c_str();
472 	std::string cDest;
473 	printx(cFormat,cSource,cDest);
474 	vRet = cDest.c_str();
475 	return TRUE;
476 }
477 
printx(const std::string & cFormat,const std::string & cSource2,std::string & cPurpose)478 void util::printx(const std::string &cFormat,const std::string &cSource2,std::string &cPurpose)
479 {
480 	std::string cSource(cSource2);
481 	if (!cPurpose.empty())
482 		//cPurpose.clear();
483 		cPurpose.erase();
484 	int itSource = 0;
485 	int iSize = cSource.size();
486 	for(int iIndex = 0; iIndex < (int)cFormat.size() && itSource<iSize; iIndex++)
487 	{
488 		char letter = cFormat[iIndex];
489 		switch(letter)
490 		{
491 		case '?':
492 			//cPurpose.push_back(cSource[itSource]);
493 			cPurpose += cSource[itSource];
494 			itSource++;
495 			break;
496 		case 'X':
497 			{
498 				while(itSource < iSize)
499 				{
500 					if ((cSource[itSource]>='0'&&cSource[itSource]<='9') || (cSource[itSource]>='a' && cSource[itSource]<='z') || (cSource[itSource]>='A' && cSource[itSource]<='Z'))
501 					{
502 						//cPurpose.push_back(cSource[itSource]);
503 						cPurpose += cSource[itSource];
504 						itSource++;
505 						break;
506 					}
507 					itSource++;
508 				}
509 				break;
510 			}
511 			break;
512 		case 'A':
513 			{
514 				while(itSource < iSize)
515 				{
516 					if ((cSource[itSource]>='a' && cSource[itSource]<='z') || (cSource[itSource]>='A' && cSource[itSource]<='Z'))
517 					{
518 						//cPurpose.push_back(cSource[itSource]);
519 						cPurpose += cSource[itSource];
520 						itSource++;
521 						break;
522 					}
523 					itSource++;
524 				}
525 				break;
526 			}
527 			break;
528 		case '9':
529 			{
530 				while(itSource < iSize)
531 				{
532 					if (cSource[itSource]>='0'&&cSource[itSource]<='9')
533 					{
534 						//cPurpose.push_back(cSource[itSource]);
535 						cPurpose += cSource[itSource];
536 						itSource++;
537 						break;
538 					}
539 					itSource++;
540 				}
541 				break;
542 			}
543 		case '*':
544 			{
545 				cPurpose.append(cSource,itSource,iSize-itSource);
546 				itSource = iSize-1;
547 				break;
548 			}
549 		case '\\':
550 			break;
551 		case '>':
552 			{
553 				for(std::string::iterator it = cSource.begin();it != cSource.end(); it++)
554 				{
555 					*it = toupper(*it);
556 				}
557 				break;
558 			}
559 		case '<':
560 			{
561 				for(std::string::iterator it = cSource.begin();it != cSource.end(); it++)
562 				{
563 					*it = tolower(*it);
564 				}
565 				break;
566 			}
567 		case '=':
568 			break;
569 		default:
570 			//cPurpose.push_back(letter);
571 			cPurpose += letter;
572 			break;
573 		}
574 	}
575 }
576 
scand(IFXJS_Context * cc,const CJS_Parameters & params,CJS_Value & vRet,CFX_WideString & sError)577 FX_BOOL util::scand(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
578 {
579 	v8::Isolate* isolate = GetIsolate(cc);
580 	int iSize = params.size();
581 	if (iSize < 2)
582 		return FALSE;
583 
584 	CFX_WideString sFormat = params[0].ToCFXWideString();
585 	CFX_WideString sDate = params[1].ToCFXWideString();
586 	double dDate = JS_GetDateTime();
587 	if (sDate.GetLength() > 0)
588 	{
589 		FX_BOOL bWrongFormat = FALSE;
590 		dDate = CJS_PublicMethods::MakeRegularDate(sDate,sFormat,bWrongFormat);
591 	}
592 
593 	if (!JS_PortIsNan(dDate))
594 	{
595 		CJS_Date date(isolate,dDate);
596 		vRet = date;
597 	}
598 	else
599 	{
600 		vRet.SetNull();
601 	}
602 
603 	return TRUE;
604 }
605 
FX_atoi64(const char * nptr)606 FX_INT64 FX_atoi64(const char *nptr)
607 {
608         int c;              /* current char */
609         FX_INT64 total;      /* current total */
610         int sign;           /* if '-', then negative, otherwise positive */
611 
612         /* skip whitespace */
613         while ( isspace((int)(unsigned char)*nptr) )
614             ++nptr;
615 
616         c = (int)(unsigned char)*nptr++;
617         sign = c;           /* save sign indication */
618         if (c == '-' || c == '+')
619             c = (int)(unsigned char)*nptr++;    /* skip sign */
620 
621         total = 0;
622 
623         while (isdigit(c)) {
624             total = 10 * total + (c - '0');     /* accumulate digit */
625             c = (int)(unsigned char)*nptr++;    /* get next char */
626         }
627 
628         if (sign == '-')
629             return -total;
630         else
631             return total;   /* return result, negated if necessary */
632 }
633 
byteToChar(IFXJS_Context * cc,const CJS_Parameters & params,CJS_Value & vRet,CFX_WideString & sError)634 FX_BOOL util::byteToChar(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
635 {
636 	int iSize = params.size();
637 	if (iSize == 0)
638 		return FALSE;
639 	int nByte = params[0].ToInt();
640 	unsigned char cByte = (unsigned char)nByte;
641 	CFX_WideString csValue;
642 	csValue.Format(L"%c", cByte);
643 	vRet = csValue.c_str();
644 	return TRUE;
645 }
646