From 86a61dc374e8abe351df03a1aa6665013cc39345 Mon Sep 17 00:00:00 2001 From: tsepez Date: Fri, 25 Mar 2016 10:00:11 -0700 Subject: util.printd() replaces specified date with current date. Added test case. Several bugs going on here: JS_LocalTime() ignoring argument and returning current time and not factoring in the time zone adjustment. Use of FXSYS_floor() silently casts result to float, losing precision required to extract minutes and seconds. Pre-existing wcsftime escapes not stripped. BUG=pdfium:413 Review URL: https://codereview.chromium.org/1833053002 --- fpdfsdk/javascript/JS_Value.cpp | 10 +- fpdfsdk/javascript/util.cpp | 221 ++++++++++++---------------------------- fpdfsdk/javascript/util.h | 7 -- 3 files changed, 71 insertions(+), 167 deletions(-) (limited to 'fpdfsdk') diff --git a/fpdfsdk/javascript/JS_Value.cpp b/fpdfsdk/javascript/JS_Value.cpp index 1da1525d09..5e403a524b 100644 --- a/fpdfsdk/javascript/JS_Value.cpp +++ b/fpdfsdk/javascript/JS_Value.cpp @@ -778,15 +778,15 @@ int JS_GetDayFromTime(double dt) { } int JS_GetHourFromTime(double dt) { - return (int)_Mod(FXSYS_floor((double)(dt / (60 * 60 * 1000))), 24); + return (int)_Mod(floor(dt / (60 * 60 * 1000)), 24); } int JS_GetMinFromTime(double dt) { - return (int)_Mod(FXSYS_floor((double)(dt / (60 * 1000))), 60); + return (int)_Mod(floor(dt / (60 * 1000)), 60); } int JS_GetSecFromTime(double dt) { - return (int)_Mod(FXSYS_floor((double)(dt / 1000)), 60); + return (int)_Mod(floor(dt / 1000), 60); } double JS_DateParse(const wchar_t* str) { @@ -820,7 +820,7 @@ double JS_DateParse(const wchar_t* str) { double date = v->ToNumber(context).ToLocalChecked()->Value(); if (!_isfinite(date)) return date; - return date + _getLocalTZA() + _getDaylightSavingTA(date); + return JS_LocalTime(date); } } } @@ -869,7 +869,7 @@ bool JS_PortIsNan(double d) { } double JS_LocalTime(double d) { - return JS_GetDateTime() + _getDaylightSavingTA(d); + return d + _getLocalTZA() + _getDaylightSavingTA(d); } std::vector JS_ExpandKeywordParams( diff --git a/fpdfsdk/javascript/util.cpp b/fpdfsdk/javascript/util.cpp index 5a7a895dac..30656cd766 100644 --- a/fpdfsdk/javascript/util.cpp +++ b/fpdfsdk/javascript/util.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -42,50 +43,39 @@ END_JS_STATIC_METHOD() IMPLEMENT_JS_CLASS(CJS_Util, util) -util::util(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} +#define UTIL_INT 0 +#define UTIL_DOUBLE 1 +#define UTIL_STRING 2 -util::~util() {} +namespace { -struct stru_TbConvert { +// Map PDF-style directives to equivalent wcsftime directives. Not +// all have direct equivalents, though. +struct TbConvert { const FX_WCHAR* lpszJSMark; const FX_WCHAR* lpszCppMark; }; -const stru_TbConvert fcTable[] = { - {L"mmmm", L"%B"}, - {L"mmm", L"%b"}, - {L"mm", L"%m"}, - // "m" - {L"dddd", L"%A"}, - {L"ddd", L"%a"}, - {L"dd", L"%d"}, - // "d", "%w", - {L"yyyy", L"%Y"}, - {L"yy", L"%y"}, - {L"HH", L"%H"}, - // "H" - {L"hh", L"%I"}, - // "h" - {L"MM", L"%M"}, - // "M" - {L"ss", L"%S"}, - // "s +// Map PDF-style directives lacking direct wcsftime directives to +// the value with which they will be replaced. +struct TbConvertAdditional { + const FX_WCHAR* lpszJSMark; + int iValue; +}; + +const TbConvert TbConvertTable[] = { + {L"mmmm", L"%B"}, {L"mmm", L"%b"}, {L"mm", L"%m"}, {L"dddd", L"%A"}, + {L"ddd", L"%a"}, {L"dd", L"%d"}, {L"yyyy", L"%Y"}, {L"yy", L"%y"}, + {L"HH", L"%H"}, {L"hh", L"%I"}, {L"MM", L"%M"}, {L"ss", L"%S"}, {L"TT", L"%p"}, -// "t" #if defined(_WIN32) - {L"tt", L"%p"}, - {L"h", L"%#I"}, + {L"tt", L"%p"}, {L"h", L"%#I"}, #else - {L"tt", L"%P"}, - {L"h", L"%l"}, + {L"tt", L"%P"}, {L"h", L"%l"}, #endif }; -#define UTIL_INT 0 -#define UTIL_DOUBLE 1 -#define UTIL_STRING 2 - -int util::ParstDataType(std::wstring* sFormat) { +int ParseDataType(std::wstring* sFormat) { bool bPercent = FALSE; for (size_t i = 0; i < sFormat->length(); ++i) { wchar_t c = (*sFormat)[i]; @@ -119,6 +109,12 @@ int util::ParstDataType(std::wstring* sFormat) { return -1; } +} // namespace + +util::util(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} + +util::~util() {} + FX_BOOL util::printf(IJS_Context* cc, const std::vector& params, CJS_Value& vRet, @@ -143,8 +139,6 @@ FX_BOOL util::printf(IJS_Context* cc, } std::wstring c_strResult; - - // for(int iIndex = 1;iIndex < params.size();iIndex++) std::wstring c_strFormat; for (int iIndex = 0; iIndex < (int)c_strConvers.size(); iIndex++) { c_strFormat = c_strConvers[iIndex]; @@ -159,7 +153,7 @@ FX_BOOL util::printf(IJS_Context* cc, continue; } - switch (ParstDataType(&c_strFormat)) { + switch (ParseDataType(&c_strFormat)) { case UTIL_INT: strSegment.Format(c_strFormat.c_str(), params[iIndex].ToInt()); break; @@ -191,9 +185,7 @@ FX_BOOL util::printd(IJS_Context* cc, return FALSE; CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc); - CJS_Value p1(pRuntime); - p1 = params[0]; - + CJS_Value p1 = params[0]; CJS_Value p2 = params[1]; CJS_Date jsDate(pRuntime); if (!p2.ConvertToDate(jsDate)) { @@ -207,10 +199,8 @@ FX_BOOL util::printd(IJS_Context* cc, } if (p1.GetType() == CJS_Value::VT_number) { - int nFormat = p1.ToInt(); CFX_WideString swResult; - - switch (nFormat) { + switch (p1.ToInt()) { case 0: swResult.Format(L"D:%04d%02d%02d%02d%02d%02d", jsDate.GetYear(), jsDate.GetMonth() + 1, jsDate.GetDay(), @@ -230,63 +220,52 @@ FX_BOOL util::printd(IJS_Context* cc, jsDate.GetSeconds()); break; default: + sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSVALUEERROR); return FALSE; } vRet = swResult.c_str(); return TRUE; } - if (p1.GetType() == CJS_Value::VT_string) { - std::basic_string cFormat = p1.ToCFXWideString().c_str(); - bool bXFAPicture = false; - if (iSize > 2) { - bXFAPicture = params[2].ToBool(); - } - - if (bXFAPicture) { + if (p1.GetType() == CJS_Value::VT_string) { + if (iSize > 2 && params[2].ToBool()) { + sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_NOTSUPPORT); return FALSE; // currently, it doesn't support XFAPicture. } - for (size_t i = 0; i < sizeof(fcTable) / sizeof(stru_TbConvert); ++i) { + // Convert PDF-style format specifiers to wcsftime specifiers. Remove any + // pre-existing %-directives before inserting our own. + std::basic_string cFormat = p1.ToCFXWideString().c_str(); + cFormat.erase(std::remove(cFormat.begin(), cFormat.end(), '%'), + cFormat.end()); + + for (size_t i = 0; i < FX_ArraySize(TbConvertTable); ++i) { int iStart = 0; int iEnd; - while ((iEnd = cFormat.find(fcTable[i].lpszJSMark, iStart)) != -1) { - cFormat.replace(iEnd, FXSYS_wcslen(fcTable[i].lpszJSMark), - fcTable[i].lpszCppMark); + while ((iEnd = cFormat.find(TbConvertTable[i].lpszJSMark, iStart)) != + -1) { + cFormat.replace(iEnd, FXSYS_wcslen(TbConvertTable[i].lpszJSMark), + TbConvertTable[i].lpszCppMark); iStart = iEnd; } } - int iYear, iMonth, iDay, iHour, iMin, iSec; - iYear = jsDate.GetYear(); - iMonth = jsDate.GetMonth(); - iDay = jsDate.GetDay(); - iHour = jsDate.GetHours(); - iMin = jsDate.GetMinutes(); - iSec = jsDate.GetSeconds(); - - struct tm time = {}; - time.tm_year = iYear - 1900; - time.tm_mon = iMonth; - time.tm_mday = iDay; - time.tm_hour = iHour; - time.tm_min = iMin; - time.tm_sec = iSec; - - struct stru_TbConvertAd { - const FX_WCHAR* lpszJSMark; - int iValue; - }; + int iYear = jsDate.GetYear(); + int iMonth = jsDate.GetMonth(); + int iDay = jsDate.GetDay(); + int iHour = jsDate.GetHours(); + int iMin = jsDate.GetMinutes(); + int iSec = jsDate.GetSeconds(); - stru_TbConvertAd cTableAd[] = { + TbConvertAdditional cTableAd[] = { {L"m", iMonth + 1}, {L"d", iDay}, {L"H", iHour}, {L"h", iHour > 12 ? iHour - 12 : iHour}, {L"M", iMin}, {L"s", iSec}, }; - for (size_t i = 0; i < sizeof(cTableAd) / sizeof(stru_TbConvertAd); ++i) { - wchar_t tszValue[10]; + for (size_t i = 0; i < FX_ArraySize(cTableAd); ++i) { + wchar_t tszValue[16]; CFX_WideString sValue; sValue.Format(L"%d", cTableAd[i].iValue); memcpy(tszValue, (wchar_t*)sValue.GetBuffer(sValue.GetLength() + 1), @@ -306,93 +285,25 @@ FX_BOOL util::printd(IJS_Context* cc, } } - CFX_WideString strFormat; + struct tm time = {}; + time.tm_year = iYear - 1900; + time.tm_mon = iMonth; + time.tm_mday = iDay; + time.tm_hour = iHour; + time.tm_min = iMin; + time.tm_sec = iSec; + wchar_t buf[64] = {}; - strFormat = wcsftime(buf, 64, cFormat.c_str(), &time); + wcsftime(buf, 64, cFormat.c_str(), &time); cFormat = buf; vRet = cFormat.c_str(); return TRUE; } + + sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSTYPEERROR); return FALSE; } -void util::printd(const std::wstring& cFormat2, - CJS_Date jsDate, - bool bXFAPicture, - std::wstring& cPurpose) { - std::wstring cFormat = cFormat2; - - if (bXFAPicture) { - return; // currently, it doesn't support XFAPicture. - } - - for (size_t i = 0; i < sizeof(fcTable) / sizeof(stru_TbConvert); ++i) { - int iStart = 0; - int iEnd; - while ((iEnd = cFormat.find(fcTable[i].lpszJSMark, iStart)) != -1) { - cFormat.replace(iEnd, FXSYS_wcslen(fcTable[i].lpszJSMark), - fcTable[i].lpszCppMark); - iStart = iEnd; - } - } - - int iYear, iMonth, iDay, iHour, iMin, iSec; - iYear = jsDate.GetYear(); - iMonth = jsDate.GetMonth(); - iDay = jsDate.GetDay(); - iHour = jsDate.GetHours(); - iMin = jsDate.GetMinutes(); - iSec = jsDate.GetSeconds(); - - struct tm time = {}; - time.tm_year = iYear - 1900; - time.tm_mon = iMonth; - time.tm_mday = iDay; - time.tm_hour = iHour; - time.tm_min = iMin; - time.tm_sec = iSec; - // COleDateTime cppTm(iYear,iMonth+1,iDay,iHour,iMin,iSec); - // CString strFormat = cppTm.Format(cFormat.c_str()); - - struct stru_TbConvertAd { - const FX_WCHAR* lpszJSMark; - int iValue; - }; - - stru_TbConvertAd cTableAd[] = { - {L"m", iMonth + 1}, {L"d", iDay}, - {L"H", iHour}, {L"h", iHour > 12 ? iHour - 12 : iHour}, - {L"M", iMin}, {L"s", iSec}, - }; - - // cFormat = strFormat.GetBuffer(strFormat.GetLength()+1); - for (size_t i = 0; i < sizeof(cTableAd) / sizeof(stru_TbConvertAd); ++i) { - wchar_t tszValue[10]; - CFX_WideString sValue; - sValue.Format(L"%d", cTableAd[i].iValue); - memcpy(tszValue, (wchar_t*)sValue.GetBuffer(sValue.GetLength() + 1), - sValue.GetLength() * sizeof(wchar_t)); - - int iStart = 0; - int iEnd; - while ((iEnd = cFormat.find(cTableAd[i].lpszJSMark, iStart)) != -1) { - if (iEnd > 0) { - if (cFormat[iEnd - 1] == L'%') { - iStart = iEnd + 1; - continue; - } - } - cFormat.replace(iEnd, FXSYS_wcslen(cTableAd[i].lpszJSMark), tszValue); - iStart = iEnd; - } - } - - CFX_WideString strFormat; - wchar_t buf[64] = {}; - strFormat = wcsftime(buf, 64, cFormat.c_str(), &time); - cFormat = buf; - cPurpose = cFormat; -} FX_BOOL util::printx(IJS_Context* cc, const std::vector& params, diff --git a/fpdfsdk/javascript/util.h b/fpdfsdk/javascript/util.h index 50fa31ad27..17f252d6dc 100644 --- a/fpdfsdk/javascript/util.h +++ b/fpdfsdk/javascript/util.h @@ -17,7 +17,6 @@ class util : public CJS_EmbedObj { util(CJS_Object* pJSObject); ~util() override; - public: FX_BOOL printd(IJS_Context* cc, const std::vector& params, CJS_Value& vRet, @@ -39,15 +38,9 @@ class util : public CJS_EmbedObj { CJS_Value& vRet, CFX_WideString& sError); - public: - static void printd(const std::wstring& cFormat, - CJS_Date Date, - bool bXFAPicture, - std::wstring& cPurpose); static void printx(const std::string& cFormat, const std::string& cSource, std::string& cPurpose); - static int ParstDataType(std::wstring* sFormat); }; class CJS_Util : public CJS_Object { -- cgit v1.2.3