diff options
Diffstat (limited to 'fpdfsdk/javascript/cjs_util.cpp')
-rw-r--r-- | fpdfsdk/javascript/cjs_util.cpp | 468 |
1 files changed, 0 insertions, 468 deletions
diff --git a/fpdfsdk/javascript/cjs_util.cpp b/fpdfsdk/javascript/cjs_util.cpp deleted file mode 100644 index 6eb52f13fe..0000000000 --- a/fpdfsdk/javascript/cjs_util.cpp +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/cjs_util.h" - -#include <time.h> - -#include <algorithm> -#include <cmath> -#include <cwctype> -#include <string> -#include <vector> - -#include "core/fxcrt/fx_extension.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/cjs_eventhandler.h" -#include "fpdfsdk/javascript/cjs_object.h" -#include "fpdfsdk/javascript/cjs_publicmethods.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/javascript/js_resources.h" - -#if _FX_OS_ == _FX_OS_ANDROID_ -#include <ctype.h> -#endif - -namespace { - -// Map PDF-style directives to equivalent wcsftime directives. Not -// all have direct equivalents, though. -struct TbConvert { - const wchar_t* lpszJSMark; - const wchar_t* lpszCppMark; -}; - -// Map PDF-style directives lacking direct wcsftime directives to -// the value with which they will be replaced. -struct TbConvertAdditional { - const wchar_t* 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"}, -#if defined(_WIN32) - {L"tt", L"%p"}, {L"h", L"%#I"}, -#else - {L"tt", L"%P"}, {L"h", L"%l"}, -#endif -}; - -} // namespace - -const JSMethodSpec CJS_Util::MethodSpecs[] = { - {"printd", printd_static}, {"printf", printf_static}, - {"printx", printx_static}, {"scand", scand_static}, - {"byteToChar", byteToChar_static}, {0, 0}}; - -int CJS_Util::ObjDefnID = -1; - -// static -void CJS_Util::DefineJSObjects(CFXJS_Engine* pEngine) { - ObjDefnID = - pEngine->DefineObj("util", FXJSOBJTYPE_STATIC, - JSConstructor<CJS_Util, util>, JSDestructor<CJS_Util>); - DefineMethods(pEngine, ObjDefnID, MethodSpecs); -} - -util::util(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} - -util::~util() {} - -CJS_Return util::printf(CJS_Runtime* pRuntime, - const std::vector<v8::Local<v8::Value>>& params) { - const size_t iSize = params.size(); - if (iSize < 1) - return CJS_Return(false); - - std::wstring unsafe_fmt_string(pRuntime->ToWideString(params[0]).c_str()); - std::vector<std::wstring> unsafe_conversion_specifiers; - int iOffset = 0; - int iOffend = 0; - unsafe_fmt_string.insert(unsafe_fmt_string.begin(), L'S'); - while (iOffset != -1) { - iOffend = unsafe_fmt_string.find(L"%", iOffset + 1); - std::wstring strSub; - if (iOffend == -1) - strSub = unsafe_fmt_string.substr(iOffset); - else - strSub = unsafe_fmt_string.substr(iOffset, iOffend - iOffset); - unsafe_conversion_specifiers.push_back(strSub); - iOffset = iOffend; - } - - std::wstring c_strResult; - for (size_t iIndex = 0; iIndex < unsafe_conversion_specifiers.size(); - ++iIndex) { - std::wstring c_strFormat = unsafe_conversion_specifiers[iIndex]; - if (iIndex == 0) { - c_strResult = c_strFormat; - continue; - } - - if (iIndex >= iSize) { - c_strResult += c_strFormat; - continue; - } - - WideString strSegment; - switch (ParseDataType(&c_strFormat)) { - case UTIL_INT: - strSegment.Format(c_strFormat.c_str(), - pRuntime->ToInt32(params[iIndex])); - break; - case UTIL_DOUBLE: - strSegment.Format(c_strFormat.c_str(), - pRuntime->ToDouble(params[iIndex])); - break; - case UTIL_STRING: - strSegment.Format(c_strFormat.c_str(), - pRuntime->ToWideString(params[iIndex]).c_str()); - break; - default: - strSegment.Format(L"%ls", c_strFormat.c_str()); - break; - } - c_strResult += strSegment.c_str(); - } - - c_strResult.erase(c_strResult.begin()); - return CJS_Return(pRuntime->NewString(c_strResult.c_str())); -} - -CJS_Return util::printd(CJS_Runtime* pRuntime, - const std::vector<v8::Local<v8::Value>>& params) { - const size_t iSize = params.size(); - if (iSize < 2) - return CJS_Return(false); - - if (params[1].IsEmpty() || !params[1]->IsDate()) - return CJS_Return(JSGetStringFromID(IDS_STRING_JSPRINT1)); - - v8::Local<v8::Date> v8_date = params[1].As<v8::Date>(); - if (v8_date.IsEmpty() || std::isnan(pRuntime->ToDouble(v8_date))) - return CJS_Return(JSGetStringFromID(IDS_STRING_JSPRINT2)); - - double date = JS_LocalTime(pRuntime->ToDouble(v8_date)); - int year = JS_GetYearFromTime(date); - int month = JS_GetMonthFromTime(date) + 1; // One-based. - int day = JS_GetDayFromTime(date); - int hour = JS_GetHourFromTime(date); - int min = JS_GetMinFromTime(date); - int sec = JS_GetSecFromTime(date); - - if (params[0]->IsNumber()) { - WideString swResult; - switch (pRuntime->ToInt32(params[0])) { - case 0: - swResult.Format(L"D:%04d%02d%02d%02d%02d%02d", year, month, day, hour, - min, sec); - break; - case 1: - swResult.Format(L"%04d.%02d.%02d %02d:%02d:%02d", year, month, day, - hour, min, sec); - break; - case 2: - swResult.Format(L"%04d/%02d/%02d %02d:%02d:%02d", year, month, day, - hour, min, sec); - break; - default: - return CJS_Return(JSGetStringFromID(IDS_STRING_JSVALUEERROR)); - } - - return CJS_Return(pRuntime->NewString(swResult.c_str())); - } - - if (params[0]->IsString()) { - // We don't support XFAPicture at the moment. - if (iSize > 2 && pRuntime->ToBoolean(params[2])) - return CJS_Return(JSGetStringFromID(IDS_STRING_JSNOTSUPPORT)); - - // Convert PDF-style format specifiers to wcsftime specifiers. Remove any - // pre-existing %-directives before inserting our own. - std::basic_string<wchar_t> cFormat = - pRuntime->ToWideString(params[0]).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(TbConvertTable[i].lpszJSMark, iStart)) != - -1) { - cFormat.replace(iEnd, wcslen(TbConvertTable[i].lpszJSMark), - TbConvertTable[i].lpszCppMark); - iStart = iEnd; - } - } - - if (year < 0) - return CJS_Return(JSGetStringFromID(IDS_STRING_JSVALUEERROR)); - - static const TbConvertAdditional cTableAd[] = { - {L"m", month}, {L"d", day}, - {L"H", hour}, {L"h", hour > 12 ? hour - 12 : hour}, - {L"M", min}, {L"s", sec}, - }; - - for (size_t i = 0; i < FX_ArraySize(cTableAd); ++i) { - WideString sValue; - sValue.Format(L"%d", cTableAd[i].iValue); - - 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, wcslen(cTableAd[i].lpszJSMark), sValue.c_str()); - iStart = iEnd; - } - } - - struct tm time = {}; - time.tm_year = year - 1900; - time.tm_mon = month - 1; - time.tm_mday = day; - time.tm_hour = hour; - time.tm_min = min; - time.tm_sec = sec; - - wchar_t buf[64] = {}; - FXSYS_wcsftime(buf, 64, cFormat.c_str(), &time); - cFormat = buf; - return CJS_Return(pRuntime->NewString(cFormat.c_str())); - } - - return CJS_Return(JSGetStringFromID(IDS_STRING_JSTYPEERROR)); -} - -CJS_Return util::printx(CJS_Runtime* pRuntime, - const std::vector<v8::Local<v8::Value>>& params) { - if (params.size() < 2) - return CJS_Return(JSGetStringFromID(IDS_STRING_JSPARAMERROR)); - - return CJS_Return( - pRuntime->NewString(printx(pRuntime->ToWideString(params[0]), - pRuntime->ToWideString(params[1])) - .c_str())); -} - -enum CaseMode { kPreserveCase, kUpperCase, kLowerCase }; - -static wchar_t TranslateCase(wchar_t input, CaseMode eMode) { - if (eMode == kLowerCase && FXSYS_isupper(input)) - return input | 0x20; - if (eMode == kUpperCase && FXSYS_islower(input)) - return input & ~0x20; - return input; -} - -WideString util::printx(const WideString& wsFormat, - const WideString& wsSource) { - WideString wsResult; - size_t iSourceIdx = 0; - size_t iFormatIdx = 0; - CaseMode eCaseMode = kPreserveCase; - bool bEscaped = false; - while (iFormatIdx < wsFormat.GetLength()) { - if (bEscaped) { - bEscaped = false; - wsResult += wsFormat[iFormatIdx]; - ++iFormatIdx; - continue; - } - switch (wsFormat[iFormatIdx]) { - case '\\': { - bEscaped = true; - ++iFormatIdx; - } break; - case '<': { - eCaseMode = kLowerCase; - ++iFormatIdx; - } break; - case '>': { - eCaseMode = kUpperCase; - ++iFormatIdx; - } break; - case '=': { - eCaseMode = kPreserveCase; - ++iFormatIdx; - } break; - case '?': { - if (iSourceIdx < wsSource.GetLength()) { - wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); - ++iSourceIdx; - } - ++iFormatIdx; - } break; - case 'X': { - if (iSourceIdx < wsSource.GetLength()) { - if (FXSYS_iswalnum(wsSource[iSourceIdx])) { - wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); - ++iFormatIdx; - } - ++iSourceIdx; - } else { - ++iFormatIdx; - } - } break; - case 'A': { - if (iSourceIdx < wsSource.GetLength()) { - if (FXSYS_iswalpha(wsSource[iSourceIdx])) { - wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); - ++iFormatIdx; - } - ++iSourceIdx; - } else { - ++iFormatIdx; - } - } break; - case '9': { - if (iSourceIdx < wsSource.GetLength()) { - if (std::iswdigit(wsSource[iSourceIdx])) { - wsResult += wsSource[iSourceIdx]; - ++iFormatIdx; - } - ++iSourceIdx; - } else { - ++iFormatIdx; - } - } break; - case '*': { - if (iSourceIdx < wsSource.GetLength()) { - wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); - ++iSourceIdx; - } else { - ++iFormatIdx; - } - } break; - default: { - wsResult += wsFormat[iFormatIdx]; - ++iFormatIdx; - } break; - } - } - return wsResult; -} - -CJS_Return util::scand(CJS_Runtime* pRuntime, - const std::vector<v8::Local<v8::Value>>& params) { - if (params.size() < 2) - return CJS_Return(false); - - WideString sFormat = pRuntime->ToWideString(params[0]); - WideString sDate = pRuntime->ToWideString(params[1]); - double dDate = JS_GetDateTime(); - if (sDate.GetLength() > 0) - dDate = CJS_PublicMethods::MakeRegularDate(sDate, sFormat, nullptr); - - if (std::isnan(dDate)) - return CJS_Return(pRuntime->NewUndefined()); - return CJS_Return(pRuntime->NewDate(dDate)); -} - -CJS_Return util::byteToChar(CJS_Runtime* pRuntime, - const std::vector<v8::Local<v8::Value>>& params) { - if (params.size() < 1) - return CJS_Return(JSGetStringFromID(IDS_STRING_JSPARAMERROR)); - - int arg = pRuntime->ToInt32(params[0]); - if (arg < 0 || arg > 255) - return CJS_Return(JSGetStringFromID(IDS_STRING_JSVALUEERROR)); - - WideString wStr(static_cast<wchar_t>(arg)); - return CJS_Return(pRuntime->NewString(wStr.c_str())); -} - -// Ensure that sFormat contains at most one well-understood printf formatting -// directive which is safe to use with a single argument, and return the type -// of argument expected, or -1 otherwise. If -1 is returned, it is NOT safe -// to use sFormat with printf() and it must be copied byte-by-byte. -int util::ParseDataType(std::wstring* sFormat) { - enum State { BEFORE, FLAGS, WIDTH, PRECISION, SPECIFIER, AFTER }; - - int result = -1; - State state = BEFORE; - size_t precision_digits = 0; - size_t i = 0; - while (i < sFormat->length()) { - wchar_t c = (*sFormat)[i]; - switch (state) { - case BEFORE: - if (c == L'%') - state = FLAGS; - break; - case FLAGS: - if (c == L'+' || c == L'-' || c == L'#' || c == L' ') { - // Stay in same state. - } else { - state = WIDTH; - continue; // Re-process same character. - } - break; - case WIDTH: - if (c == L'*') - return -1; - if (std::iswdigit(c)) { - // Stay in same state. - } else if (c == L'.') { - state = PRECISION; - } else { - state = SPECIFIER; - continue; // Re-process same character. - } - break; - case PRECISION: - if (c == L'*') - return -1; - if (std::iswdigit(c)) { - // Stay in same state. - ++precision_digits; - } else { - state = SPECIFIER; - continue; // Re-process same character. - } - break; - case SPECIFIER: - 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') { - result = UTIL_INT; - } else if (c == L'e' || c == L'E' || c == L'f' || c == L'g' || - c == L'G') { - result = UTIL_DOUBLE; - } else if (c == L's' || c == L'S') { - // Map s to S since we always deal internally with wchar_t strings. - // TODO(tsepez): Probably 100% borked. %S is not a standard - // conversion. - (*sFormat)[i] = L'S'; - result = UTIL_STRING; - } else { - return -1; - } - state = AFTER; - break; - case AFTER: - if (c == L'%') - return -1; - // Stay in same state until string exhausted. - break; - } - ++i; - } - // See https://crbug.com/740166 - if (result == UTIL_INT && precision_digits > 2) - return -1; - - return result; -} |