ServiceConfig::State ServiceConfig::ParseNetworks(const VariantNC & oData, const STLW::string & sBranch, ServiceConfig & oServiceConfig, IPv4Map & oIPv4Map, Logger & oLogger) { const STLW::vector<STLW::string> vNetworks = oData[sBranch]; STLW::vector<STLW::string>::const_iterator itvNetworks = vNetworks.begin(); while (itvNetworks != vNetworks.end()) { // IPv4 if (itvNetworks -> find(".") != STLW::string::npos) { if (oIPv4Map.AddNet(*itvNetworks) != IPMap::OK) { oLogger.Emerg("Invalid format of parameter `Service/%s/%s`: invalid network `%s`", oServiceConfig.name.c_str(), sBranch.c_str(), itvNetworks -> c_str()); return CONFIG_ERROR; } } // IPv6, TBD else if (itvNetworks -> find(":") != STLW::string::npos) { oLogger.Emerg("Invalid format of parameter `Service/%s/%s`: IPv6 networks `%s` not supported yet", oServiceConfig.name.c_str(), sBranch.c_str(), itvNetworks -> c_str()); } ++itvNetworks; } return OK; }
// // Handler // INT_32 FnArrayElement::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // Only 2 args allowed if (iArgNum != 2) { oLogger.Emerg("Usage: ARRAY_ELEMENT(index, array)"); return -1; } // Second argument *MUST* be an ARRAY if (aArguments[0].GetType() != CDT::ARRAY_VAL) { oLogger.Error("Second argument MUST be ARRAY"); return -1; } // Element index const UINT_32 iElement = aArguments[1].GetInt(); if (aArguments[0].Size() <= iElement) { oCDTRetVal = CDT(); return 0; } // Return element oCDTRetVal = aArguments[0][iElement]; return 0; }
// // Handler // INT_32 FnTruncate::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum == 2) { const UINT_32 iMaxLen = UINT_32(aArguments[0].GetInt()); const STLW::string sData = aArguments[1].GetString(); if (sData.size() > iMaxLen) { oCDTRetVal = STLW::string(sData, 0, iMaxLen); } else { oCDTRetVal = sData; } return 0; } else if (iArgNum == 3) { const UINT_32 iMaxLen = UINT_32(aArguments[1].GetInt()); STLW::string sData = aArguments[2].GetString(); if (sData.size() > iMaxLen) { sData = STLW::string(sData, 0, iMaxLen); sData.append(aArguments[0].GetString()); } oCDTRetVal = sData; return 0; } oLogger.Emerg("Usage: TRUNCATE(x, offest[, addon])"); return -1; }
// // Handler // INT_32 FnLog::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // Natural logarithm if (iArgNum == 1) { // NaN oCDTRetVal = log(aArguments[0].GetFloat()); return 0; } // Logarithm with specified base else if (iArgNum == 2) { const W_FLOAT dBase = aArguments[0].GetFloat(); const W_FLOAT dValue = aArguments[1].GetFloat(); // NaN if (dBase <= 0) { return (INT_32)log((W_FLOAT)-1); } oCDTRetVal = log(dValue) / log(dBase); return 0; } oLogger.Emerg("Usage: LOG(x[, base])"); return -1; }
// // Handler // INT_32 FnSprintf::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum == 0) { oLogger.Emerg("Usage: SPRINTF(format, a[, b, ...])"); return -1; } CDT oArgs(CDT::ARRAY_VAL); INT_32 iPos = iArgNum - 2; while (iPos >= 0) { oArgs.PushBack(aArguments[iPos]); --iPos; } STLW::string sResult; FormatString(aArguments[iArgNum - 1].GetString(), sResult, oArgs); oCDTRetVal = sResult; return 0; }
// // Handler // INT_32 FnListElement::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum <= 1) { oLogger.Emerg("Usage: LIST_ELEMENT(data1, data2, ..., element_number); at least 2 arguments need"); return -1; } // Element index const UINT_32 iLastElement = iArgNum - 1; // Element const UINT_32 iElement = (UINT_32)aArguments[iLastElement].GetInt(); // Element does not exist? if (iElement >= iLastElement) { return -1; } // Return element oCDTRetVal = aArguments[iLastElement - iElement - 1]; return 0; }
// // Handler // INT_32 FnGetText::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum == 1) { oCDTRetVal = gettext(aArguments[0].GetString().c_str()); return 0; } else if (iArgNum == 2) { oCDTRetVal = dgettext(aArguments[1].GetString().c_str(), aArguments[0].GetString().c_str()); return 0; } else if (iArgNum == 3) { oCDTRetVal = ngettext(aArguments[2].GetString().c_str(), aArguments[1].GetString().c_str(), INT_32(aArguments[0].GetInt())); return 0; } else if (iArgNum == 4) { oCDTRetVal = dngettext(aArguments[3].GetString().c_str(), aArguments[2].GetString().c_str(), aArguments[1].GetString().c_str(), INT_32(aArguments[0].GetInt())); return 0; } oLogger.Emerg("Usage: GETTEXT(message), GETTEXT(domain, message) or GETTEXT(message, message-plural, n)"); return -1; }
// // Handler // INT_32 FnDefined::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // At least one argument need if (iArgNum == 0) { oLogger.Emerg("Usage: DEFINED(a[, b, ...])"); return -1; } oCDTRetVal = 1; INT_32 iI = iArgNum - 1; for (; iI >= 0; --iI) { if (aArguments[iI].GetType() == CDT::UNDEF) { oCDTRetVal = 0; break; } } return 0; }
// // Handler // INT_32 FnInSet::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum <= 1) { oLogger.Emerg("Usage: IN_SET(x, a[, b, ...])"); return -1; } INT_32 iI = iArgNum - 1; CDT & oCDT1 = aArguments[iI]; --iI; for (; iI >= 0; --iI) { if (oCDT1.Equal(aArguments[iI])) { oCDTRetVal = 1; return 0; } } oCDTRetVal = 0; return 0; }
// // Setup server: create sockets, load modules, etc // INT_32 MainProcess::Setup(Logger & oLogger, bool & bLoggerStarted) { // Initialize loggers, before of all other modules oLogger.Info("Starting logger subsystem"); STLW::vector<ModuleConfig>::const_iterator itvLoggers = oGlobalContext.config.loggers.begin(); while (itvLoggers != oGlobalContext.config.loggers.end()) { const INT_32 iRC = LoadModule(itvLoggers -> type, itvLoggers -> name, itvLoggers -> library, itvLoggers -> driver, itvLoggers -> params, oGlobalContext.config.libexec_dirs, oLogger); if (iRC != 0) { return iRC; } oLogger.Info("Logger `%s` started", itvLoggers -> name.c_str()); ++itvLoggers; } // Get logger from factory for main process Object * pObject = oGlobalContext.factory.GetObject("Logger/" + oGlobalContext.config.logger_type); if (pObject == NULL) { oLogger.Emerg("Can't get main process logger `%s`", oGlobalContext.config.logger_type.c_str()); return -1; } oLogger.Info("Logger subsystem started"); // Start logger subsystem oGlobalContext.error_log = static_cast<LoggerObject *>(pObject) -> GetErrorLog(NULL); oGlobalContext.error_log -> Notice("Log started"); oGlobalContext.transfer_log = static_cast<LoggerObject *>(pObject) -> GetCustomLog(NULL); oGlobalContext.transfer_log -> Notice("Log started"); bLoggerStarted = true; // Load modules oGlobalContext.error_log -> Info("Starting modules"); STLW::vector<ModuleConfig>::const_iterator itvModules = oGlobalContext.config.modules.begin(); while(itvModules != oGlobalContext.config.modules.end()) { const INT_32 iRC = LoadModule(itvModules -> type, itvModules -> name, itvModules -> library, itvModules -> driver, itvModules -> params, oGlobalContext.config.libexec_dirs, *oGlobalContext.error_log); if (iRC != 0) { return iRC; } ++itvModules; } oGlobalContext.error_log -> Info("All modules started"); return 0; }
// // Handler // INT_32 FnJSONEscape::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum < 1) { oLogger.Emerg("Usage: JSONESCAPE(a[, b, ...])"); return -1; } STLW::string sResult; for(INT_32 iPos = iArgNum - 1; iPos >=0; --iPos) { switch (aArguments[iPos].GetType()) { case CDT::UNDEF: sResult.append("null", 4); break; case CDT::INT_VAL: case CDT::REAL_VAL: case CDT::POINTER_VAL: case CDT::STRING_INT_VAL: case CDT::STRING_REAL_VAL: sResult.append(aArguments[iPos].GetString()); break; case CDT::STRING_VAL: sResult.append(EscapeJSONString(aArguments[iPos].GetString(), true, false)); break; default: oLogger.Emerg("Invalid type %s", aArguments[iPos].PrintableType()); return -1; } } oCDTRetVal = sResult; return 0; }
// // Handler // INT_32 FnContext::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum != 0) { oLogger.Emerg("Usage: CONTEXT()"); return -1; } oCDTRetVal = *pCDT; return 0; }
// // Handler // INT_32 FnBase64Decode::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // Only 1 argument if (iArgNum != 1) { oLogger.Emerg("Usage: BASE64_DECODE(x)"); return -1; } oCDTRetVal = Base64Decode(aArguments[0].GetString()); return 0; }
// // Handler // INT_32 FnHashElement::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum <= 1) { oLogger.Emerg("Usage: HASH_ELEMENT(index, hash); 2 arguments need"); return -1; } // Return element oCDTRetVal = aArguments[0].GetCDT(aArguments[1].GetString()); return 0; }
// // Handler // INT_32 FnHTMLEscape::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum < 1) { oLogger.Emerg("Usage: HTMLESCAPE(a[, b, ...])"); return -1; } STLW::string sResult; for(INT_32 iPos = iArgNum - 1; iPos >=0; --iPos) { sResult.append(aArguments[iPos].GetString()); } oCDTRetVal = HTMLEscape(sResult); return 0; }
// // Handler // INT_32 FnJSON::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum != 1) { oLogger.Emerg("Usage: JSON(data)"); return -1; } STLW::string sData; CDT2JSON(aArguments[0], sData); oCDTRetVal = sData; return 0; }
// // Handler // INT_32 FnMin::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum == 0) { oLogger.Emerg("Usage: MIN(a[, b, ...])"); return -1; } INT_32 iMinPos = 0; W_FLOAT dMinVal = aArguments[0].GetFloat(); for (UINT_32 iPos = 0; iPos < iArgNum; ++iPos) { const W_FLOAT dCurVal = aArguments[iPos].GetFloat(); if (dCurVal < dMinVal) { iMinPos = iPos; dMinVal = dCurVal; } } oCDTRetVal = aArguments[iMinPos]; return 0; }
// // Handler // INT_32 FnMax::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum == 0) { oLogger.Emerg("Usage: MAX(data1, data2, ..., dataN); at least 1 argument need"); return -1; } INT_32 iMaxPos = 0; W_FLOAT dMaxVal = aArguments[0].GetFloat(); for (UINT_32 iPos = 0; iPos < iArgNum; ++iPos) { const W_FLOAT dCurVal = aArguments[iPos].GetFloat(); if (dCurVal > dMaxVal) { iMaxPos = iPos; dMaxVal = dCurVal; } } oCDTRetVal = aArguments[iMaxPos]; return 0; }
// // Handler // INT_32 FnGetText_::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum == 1) { oCDTRetVal = gettext(aArguments[0].GetString().c_str()); return 0; } else if (iArgNum == 2) { oCDTRetVal = dgettext(aArguments[1].GetString().c_str(), aArguments[0].GetString().c_str()); return 0; } else if (iArgNum == 3) { oCDTRetVal = dcgettext(aArguments[2].GetString().c_str(), aArguments[1].GetString().c_str(), INT_32(aArguments[3].GetInt())); return 0; } oLogger.Emerg("Usage: _(message) or _(message, domain) or _(message, domain, category)"); return -1; }
// // Handler // INT_32 FnAvg::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // Need at least 2 args if (iArgNum < 2) { oLogger.Emerg("Usage: AVG(data1, data2, ..., dataN, '[aAgGhHqQ]')"); return -1; } // First Arg 1: destination type const STLW::string & sWhat = aArguments[iArgNum - 1].GetString(); if (sWhat.length() == 0) { oLogger.Error("Last argument should be 'a', 'A', 'g', 'G', 'h', 'H', 'q' or 'Q', but is `%s`", sWhat.c_str()); return -1; } // http://en.wikipedia.org/wiki/Average switch (sWhat[0]) { // Arithmetic case 'A': case 'a': { W_FLOAT dSum = 0.0; for(INT_32 iPos = iArgNum - 2; iPos >= 0 ; --iPos) { dSum += aArguments[iPos].GetFloat(); } oCDTRetVal = dSum / (iArgNum - 1); } break; // Geometric case 'G': case 'g': { W_FLOAT dSum = 1.0; for(INT_32 iPos = iArgNum - 2; iPos >= 0 ; --iPos) { dSum *= aArguments[iPos].GetFloat(); } oCDTRetVal = pow(dSum, 1.0 / (iArgNum - 1)); } break; // Harmonic case 'H': case 'h': { W_FLOAT dSum = 0.0; for(INT_32 iPos = iArgNum - 2; iPos >= 0 ; --iPos) { const W_FLOAT dTMP = aArguments[iPos].GetFloat(); if (dTMP == 0.0) { dSum = 0; break; } dSum += 1.0 / dTMP; } oCDTRetVal = 1.0 * (iArgNum - 1) / dSum; } break; // Quadratic case 'Q': case 'q': { W_FLOAT dSum = 0.0; for(INT_32 iPos = iArgNum - 1; iPos >= 0 ; --iPos) { const W_FLOAT dTMP = aArguments[iPos].GetFloat(); dSum += dTMP * dTMP; } oCDTRetVal = sqrt(dSum / (iArgNum - 1)); } break; default: oLogger.Error("Last argument should be 'a', 'A', 'g', 'G', 'h', 'H', 'q' or 'Q', but is `%s`", sWhat.c_str()); return -1; } return 0; }
// // Get configuration from variant data type // ServiceConfig::State ServiceConfig::GetConfig(const VariantNC & oData, ServiceConfig & oServiceConfig, Logger & oLogger) { // Allow connection from specified IP's or subnets if (ParseNetworks(oData, "AllowConnect", oServiceConfig, oServiceConfig.ipv4_allowed_networks, oLogger) != OK) { return CONFIG_ERROR; } // Deny connection from specified IP's or subnets if (ParseNetworks(oData, "DenyConnect", oServiceConfig, oServiceConfig.ipv4_denied_networks, oLogger) != OK) { return CONFIG_ERROR; } // Order of networks check oServiceConfig.allow_deny_order = ALLOW_DENY; const STLW::vector<STLW::string> vDenyAllow = oData["AllowDenyOrder"]; if (!vDenyAllow.empty() && vDenyAllow[0] != "") { if (vDenyAllow.size() != 2) { oLogger.Emerg("Invalid format of parameter `Service/%s/AllowDenyOrder`: need `allow deny` or `deny allow`", oServiceConfig.name.c_str()); return CONFIG_ERROR; } if (Unicode::CompareIgnoreCase(vDenyAllow[0].data(), vDenyAllow[0].size(), "deny", sizeof("deny") - 1) == 0) { oServiceConfig.allow_deny_order = DENY_ALLOW; } } // Listen to inteface STLW::vector<STLW::string> vListen; ConfigHelper::GetList(oData["Listen"], vListen); STLW::vector<STLW::string>::const_iterator itvListen = vListen.begin(); while(itvListen != vListen.end()) { ListenInterface oInterface; ConfigHelper::State oRC = ConfigHelper::ParseAddress(*itvListen, oInterface.af, oInterface.address, oInterface.port); if (oRC != ConfigHelper::OK) { oLogger.Emerg("Invalid address: `%s`", itvListen -> c_str()); return CONFIG_ERROR; } oServiceConfig.listen.push_back(oInterface); ++itvListen; } // Socket listen queue oServiceConfig.listen_queue = oData["MaxQueueLength"]; if (oServiceConfig.listen_queue == 0) { oLogger.Emerg("Invalid format of parameter `Service/%s/MaxQueueLength` not set", oServiceConfig.name.c_str()); return CONFIG_ERROR; } // Read buffer size oServiceConfig.recv_buffer_size = ConfigHelper::ParseSize(oData["RecvBufferSize"]); if (oServiceConfig.recv_buffer_size == 0 || oServiceConfig.recv_buffer_size == UINT_32(-1)) { oLogger.Emerg("Invalid format of parameter `Service/%s/RecvBufferSize` not set", oServiceConfig.name.c_str()); return CONFIG_ERROR; } // Maximum number of connections for this service oServiceConfig.max_clients = oData["MaxClients"]; if (oServiceConfig.max_clients == 0) { oLogger.Warn("Parameter `Service/%s/MaxClients`: not set", oServiceConfig.name.c_str()); } // Number of active clients oServiceConfig.active_clients = 0; // Read/Write timeout oServiceConfig.io_timeout = ConfigHelper::ParseTimeout(oData["IOTimeout"]) / 1000.0; if (oServiceConfig.io_timeout == 0) { oLogger.Emerg("Parameter `Service/%s/IOTimeout`: need to set positive value", oServiceConfig.name.c_str()); return CONFIG_ERROR; } #ifdef IRIS_TLS_SUPPORT // TLS parameters oServiceConfig.enable_ssl_tls = ConfigHelper::ParseBool(oData["EnableTLSSSL"]); if (oServiceConfig.enable_ssl_tls) { // File with the RSA certificate in PEM format. oServiceConfig.tls_cert_file = oData["TLSCertFile"]; // File with the RSA private key in PEM format oServiceConfig.tls_key_file = oData["TLSKeyFile"]; // File with the DH data oServiceConfig.dh_file.assign(oData["DHFile"]); // SSL Ciphers oServiceConfig.ciphers.assign(oData["SSLCiphers"]); if (oServiceConfig.tls_cert_file.size() != oServiceConfig.tls_key_file.size()) { oLogger.Emerg("Number of files `Service/%s/TLSCertFile` and Service/%s/TLSKeyFile` must be equal", oServiceConfig.name.c_str()); return CONFIG_ERROR; } // Use Transport Level Security at connection time oServiceConfig.use_tls = ConfigHelper::ParseBool(oData["UseTLS"]); // Allow upgrade an existing insecure connection to a secure connection using SSL/TLS oServiceConfig.start_tls = ConfigHelper::ParseBool(oData["StartTLS"]); // Prefer to user server ciphers oServiceConfig.prefer_server_ciphers = ConfigHelper::ParseBool(oData["PreferServerCiphers"], true); } #endif // IRIS_TLS_SUPPORT // Handler name oServiceConfig.handler_name.assign(oData["Handler"]); // Handler object oServiceConfig.handler = NULL; return OK; }
// // Handler // INT_32 FnRandom::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // 0 .. MAX(unsigned long) if (iArgNum == 0) { oCDTRetVal = UINT_64(random()); return 0; } // RAND(x) -> 0 .. RAND(x) else if (iArgNum == 1) { const CDT & oFirstArg = aArguments[0]; // Integer value if (oFirstArg.GetType() == CDT::INT_VAL) { oCDTRetVal = INT_64(random() % oFirstArg.GetInt()); return 0; } // Floating point value else if (oFirstArg.GetType() == CDT::REAL_VAL) { oCDTRetVal = W_FLOAT(oFirstArg.GetFloat() * (random() % UINT_64(RAND_MAX)) / UINT_64(RAND_MAX)); return 0; } // Invalid data type, just return 0 oCDTRetVal = 0; return 0; } // RAND(x, y) -> x .. y else if (iArgNum == 2) { const CDT & oFirstArg = aArguments[1]; const CDT & oSecondArg = aArguments[0]; // x and y is integer values if (oFirstArg.GetType() == CDT::INT_VAL && oSecondArg.GetType() == CDT::INT_VAL) { const UINT_64 iFirst = oFirstArg.GetInt(); const UINT_64 iInterval = oSecondArg.GetInt() - iFirst; oCDTRetVal = INT_64(random() % iInterval + iFirst); return 0; } // x or y (or both) are floating point value else if ((oFirstArg.GetType() == CDT::REAL_VAL && oSecondArg.GetType() == CDT::INT_VAL) || (oFirstArg.GetType() == CDT::INT_VAL && oSecondArg.GetType() == CDT::REAL_VAL) || (oFirstArg.GetType() == CDT::REAL_VAL && oSecondArg.GetType() == CDT::REAL_VAL)) { const W_FLOAT dFirst = oFirstArg.GetFloat(); const W_FLOAT dInterval = oSecondArg.GetFloat() - dFirst; oCDTRetVal = W_FLOAT(dInterval * (random() % UINT_64(RAND_MAX)) / UINT_64(RAND_MAX) + dFirst); return 0; } // Invalid data type, just return 0 oCDTRetVal = 0; return 0; } oLogger.Emerg("Usage: RANDOM([[min,] max])"); return -1; }
// // Handler // INT_32 FnMBTruncate::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { if (iArgNum == 2) { const UINT_32 iMaxLen = UINT_32(aArguments[0].GetInt()); const STLW::string sData = aArguments[1].GetString(); CCHAR_P szStart = sData.data(); CCHAR_P szEnd = sData.data() + sData.size(); INT_32 iPos = 0; UINT_32 iCharPos = 0; for(;;) { INT_32 iCharLen = utf_charlen(szStart + iPos, szEnd); if (iCharLen == -3) { break; } // Check character length if (iCharLen < 0) { iCharLen = 1; } // Skip errors else { ++iCharPos; } iPos += iCharLen; if (iCharPos >= iMaxLen) { break; } } if (iCharPos == iMaxLen) { oCDTRetVal = STLW::string(sData, 0, iPos); } else { oCDTRetVal = sData; } return 0; } else if (iArgNum == 3) { const UINT_32 iMaxLen = UINT_32(aArguments[1].GetInt()); STLW::string sData = aArguments[2].GetString(); CCHAR_P szStart = sData.data(); CCHAR_P szEnd = sData.data() + sData.size(); INT_32 iPos = 0; UINT_32 iCharPos = 0; for(;;) { INT_32 iCharLen = utf_charlen(szStart + iPos, szEnd); if (iCharLen == -3) { break; } // Check character length if (iCharLen < 0) { iCharLen = 1; } // Skip errors else { ++iCharPos; } iPos += iCharLen; if (iCharPos >= iMaxLen) { break; } } if (iCharPos >= iMaxLen) { sData = STLW::string(sData, 0, iPos); sData.append(aArguments[0].GetString()); } oCDTRetVal = sData; return 0; } oLogger.Emerg("Usage: MB_TRUNCATE(data, offset) or MB_TRUNCATE(data, offset, add_on)"); return -1; }
INT_32 FN_CoNaN::Usage(Logger &logger) { logger.Emerg("Usage: CoNaN(N, LIST(\"язык\", \"языка\", \"языков\"), [concat_num = true]) or CoNaN(N, \"язык\", \"языка\", \"языков\", [concat_num = true])"); return -1; }
// // Handler // INT_32 FnIconv::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { UINT_32 iMyArgNum = iArgNum; // 3 or 4 arguments need if (iMyArgNum != 3 && iMyArgNum != 4) { oLogger.Emerg("Usage: ICONV(x, src, dst[, flags])"); return -1; } // Arg 3: flags // Arg 2: destination charset // Arg 1: source charset // Arg 0: string to convert UINT_32 iFlags = 0; #ifdef ICONV_DISCARD_ILSEQ iFlags |= C_ICONV_DISCARD_ILSEQ; #endif #ifdef ICONV_TRANSLITERATE iFlags |= C_ICONV_TRANSLITERATE; #endif if (iMyArgNum == 4) { const STLW::string & sFlags = aArguments[0].GetString(); for (UINT_32 iPos = 0; iPos < sFlags.size(); ++iPos) { switch (sFlags[iPos]) { // Discard illegal sequence and continue case 'i': case 'I': iFlags |= C_ICONV_DISCARD_ILSEQ; break; // Enable transliteration case 't': case 'T': iFlags |= C_ICONV_TRANSLITERATE; break; default: oLogger.Error("Last argument should be 'i', 'I', 't' or 'T', but is `%s`", sFlags.c_str()); return -1; } } } const STLW::string & sTo = aArguments[--iMyArgNum].GetString(); const STLW::string & sFrom = aArguments[--iMyArgNum].GetString(); const STLW::string & sWhat = aArguments[--iMyArgNum].GetString(); STLW::string sFromTo(sFrom); sFromTo.append(sTo); iconv_t oIconvConverter = (iconv_t)(-1); STLW::map<STLW::string, iconv_t>::iterator itmIconvMap = mIconvMap.find(sFromTo); if (itmIconvMap != mIconvMap.end()) { oIconvConverter = itmIconvMap -> second; } // Try to open iconv converter else { oIconvConverter = iconv_open(sFrom.c_str(), sTo.c_str()); if (oIconvConverter != (iconv_t)(-1)) { mIconvMap[sFromTo] = oIconvConverter; } else { if (errno == EINVAL) { oLogger.Error("The conversion from `%s` to `%s` is not supported by the implementation", sFrom.c_str(), sTo.c_str()); } else { oLogger.Error("Error(%d) in iconv_open('%s', '%s'): %s", sFrom.c_str(), sTo.c_str(), strerror(errno)); } return -1; } } #if (_LIBICONV_VERSION >= 0x0108) int iFlag = 1; // Discard illegal characters if (iFlags & C_ICONV_DISCARD_ILSEQ) { if (iconvctl(oIconvConverter, ICONV_SET_DISCARD_ILSEQ, &iFlag) == -1) { oLogger.Error("ICONV_SET_DISCARD_ILSEQ is is not supported by the implementation"); return -1; } } // Ånable transliteration in the conver-sion if (iFlags & C_ICONV_TRANSLITERATE) { if (iconvctl(oIconvConverter, ICONV_SET_TRANSLITERATE, &iFlag) == -1) { oLogger.Error("ICONV_SET_TRANSLITERATE is is not supported by the implementation"); return -1; } } #endif // Allocate memory size_t iSrcLength = sWhat.size(); size_t iDstLength = CTPP_ESCAPE_BUFFER_LEN; char aDstData[CTPP_ESCAPE_BUFFER_LEN]; #if defined(linux) || defined(__APPLE__) char * aSrcData = (char *)sWhat.data(); #else const char * aSrcData = (const char *)sWhat.data(); #endif STLW::string sResult; for (;;) { char * aDstTMP = aDstData; size_t iDstLengthTMP = iDstLength; size_t iResult = iconv(oIconvConverter, &aSrcData, &iSrcLength, &aDstTMP, &iDstLengthTMP); if (aDstTMP - aDstData > 0) { sResult.append(aDstData, aDstTMP - aDstData); } // All data converted? if (iResult != (size_t)-1) { break; } else { if (errno != E2BIG) { ++aSrcData; --iSrcLength; } } } oCDTRetVal = sResult; return 0; }
// // Handler // INT_32 FnCast::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // 2 arguments need if (iArgNum != 2) { oLogger.Emerg("Usage: CAST(flag, x)"); return -1; } // Arg 1: destination type const STLW::string & sWhat = aArguments[1].GetString(); if (sWhat.length() == 0) { oLogger.Error("The last argument should be 's', 'S', 'o', 'O', 'd', 'D', 'i', 'I', 'h', 'H', 'f' or 'F', but is `%s`", sWhat.c_str()); return -1; } CDT & oTMP = aArguments[0]; switch(sWhat[0]) { // S[tring] case 'S': case 's': oCDTRetVal = oTMP.GetString(); return 0; // O[ct[al]] case 'o': case 'O': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetInt(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { unsigned long long iLL = 0; sscanf(oTMP.GetString().c_str(), "%llo", &iLL); oCDTRetVal = INT_64(iLL); return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // D[ec[imal]] case 'd': case 'D': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetInt(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { long long iLL = 0; sscanf(oTMP.GetString().c_str(), "%lld", &iLL); oCDTRetVal = INT_64(iLL); return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // I[nt[eger]] case 'i': case 'I': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetInt(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { long long iLL = 0; sscanf(oTMP.GetString().c_str(), "%lli", &iLL); oCDTRetVal = INT_64(iLL); return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // H[ex[adecimal]] case 'H': case 'h': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetInt(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { unsigned long long iLL = 0; sscanf(oTMP.GetString().c_str(), "%llx", &iLL); oCDTRetVal = INT_64(iLL); return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // F[loat] case 'F': case 'f': if (oTMP.GetType() <= CDT::REAL_VAL) { oCDTRetVal = oTMP.GetFloat(); return 0; } else if (oTMP.GetType() == CDT::STRING_VAL) { double dVal = 0; sscanf(oTMP.GetString().c_str(), "%lg", &dVal); oCDTRetVal = dVal; return 0; } oLogger.Error("Invalid source type of first argument. Should be INT, REAL or STRING, but is `%s`", oTMP.PrintableType()); return -1; // Error default: oLogger.Error("The last argument should be 's', 'S', 'o', 'O', 'd', 'D', 'i', 'I', 'h', 'H', 'f' or 'F', but is `%s`", sWhat.c_str()); return -1; } }
// // Handler // INT_32 FnMBSubstring::Handler(CDT * aArguments, const UINT_32 iArgNum, CDT & oCDTRetVal, Logger & oLogger) { // Check number of parameters if (iArgNum == 0) { oCDTRetVal = ""; return 0; } // substr('foobar', 2) -> 'obar' if (iArgNum == 2) { const UINT_32 iOffset = UINT_32(aArguments[0].GetInt()); const STLW::string sResult = aArguments[1].GetString(); CCHAR_P szStart = sResult.data(); CCHAR_P szEnd = sResult.data() + sResult.size(); INT_32 iPos = 0; UINT_32 iCharPos = 0; for(;;) { INT_32 iCharLen = utf_charlen(szStart + iPos, szEnd); if (iCharLen == -3) { break; } // Check character length if (iCharLen < 0) { iCharLen = 1; } // Skip errors else { ++iCharPos; } iPos += iCharLen; if (iCharPos >= iOffset) { break; } } if (iCharPos < iOffset) { oCDTRetVal = ""; } else { oCDTRetVal = sResult.substr(iPos); } return 0; } // substr('foobar', 2, 3) -> 'oba' if (iArgNum == 3) { const UINT_32 iBytes = UINT_32(aArguments[0].GetInt()); const UINT_32 iOffset = UINT_32(aArguments[1].GetInt()); const STLW::string sResult = aArguments[2].GetString(); CCHAR_P szStart = sResult.data(); CCHAR_P szEnd = sResult.data() + sResult.size(); INT_32 iPos = 0; UINT_32 iCharOffset = 0; UINT_32 iCharPos = 0; for(;;) { INT_32 iCharLen = utf_charlen(szStart + iPos, szEnd); if (iCharLen == -3) { break; } // Check character length if (iCharLen < 0) { iCharLen = 1; } // Skip errors else { ++iCharPos; } iPos += iCharLen; if (iCharPos == iOffset) { iCharOffset = iPos; } if (iCharPos == iOffset + iBytes) { break; } } if (sResult.size() < iCharOffset) { oCDTRetVal = ""; } else { oCDTRetVal = sResult.substr(iCharOffset, iPos - iCharOffset); } return 0; } // substr('foobar', 2, 3, '1234567') -> 'fo1234567r' if (iArgNum == 4) { STLW::string sReplacement = aArguments[0].GetString(); const UINT_32 iBytes = UINT_32(aArguments[1].GetInt()); const UINT_32 iOffset = UINT_32(aArguments[2].GetInt()); const STLW::string sTMP = aArguments[3].GetString(); CCHAR_P szStart = sTMP.data(); CCHAR_P szEnd = sTMP.data() + sTMP.size(); UINT_32 iPos = 0; UINT_32 iCharOffset = 0; UINT_32 iCharPos = 0; for(;;) { INT_32 iCharLen = utf_charlen(szStart + iPos, szEnd); if (iCharLen == -3) { break; } // Check character length if (iCharLen < 0) { iCharLen = 1; } // Skip errors else { ++iCharPos; } iPos += iCharLen; if (iCharPos == iOffset) { iCharOffset = iPos; } if (iCharPos == iOffset + iBytes) { break; } } if (sTMP.size() < iCharOffset) { oCDTRetVal = ""; return 0; } STLW::string sResult(sTMP, 0, iCharOffset); sResult.append(sReplacement); if (iPos == sTMP.size()) { oCDTRetVal = sResult; return 0; } sResult.append(sTMP, iPos, STLW::string::npos); oCDTRetVal = sResult; return 0; } oLogger.Emerg("Usage: MB_SUBSTR(x, offset[, bytes[, y]]])"); return -1; }
// // Load modules // INT_32 MainProcess::LoadModule(const STLW::string & sModuleType, const STLW::string & sModuleName, const STLW::string & sLibrary, const STLW::string & sDriver, const VariantNC & oModuleConfig, const STLW::vector<STLW::string> & vLibexecDirs, Logger & oLogger) { oLogger.Info("Opening `%s/%s` from library `%s`", sModuleType.c_str(), sModuleName.c_str(), sLibrary.c_str()); STLW::string sFullpath; INT_32 iRC = FindFile(vLibexecDirs, sLibrary, sFullpath); if (iRC == -1) { STLW::string sDirList; STLW::vector<STLW::string>::const_iterator itvLibexecDirs = vLibexecDirs.begin(); for (;;) { sDirList += "`" + *itvLibexecDirs + "` "; ++itvLibexecDirs; if (itvLibexecDirs == vLibexecDirs.end()) { break; } sDirList += ", "; } oLogger.Emerg("Can't find library `%s` in LibexecDirs(%s) ", sLibrary.c_str(), sDirList.c_str()); return -1; } oLogger.Info("Library `%s` found here: `%s`", sLibrary.c_str(), sFullpath.c_str()); Object * pObject = oGlobalContext.loader.GetObject(sFullpath.c_str(), sDriver.c_str()); if (pObject == NULL) { oLogger.Emerg("Can't load object `%s` from file `%s`", sDriver.c_str(), sFullpath.c_str()); return -1; } // Check type of object const STLW::string sObjectType = pObject -> GetObjectType(); if (Unicode::CompareIgnoreCase(sObjectType.data(), sObjectType.size(), sModuleType.data(), sModuleType.size()) != 0) { oLogger.Emerg("Need type `%s`, but object `%s` loaded from file `%s` has type `%s`", sModuleType.c_str(), pObject -> GetObjectName(), sFullpath.c_str(), pObject -> GetObjectType()); delete pObject; return -1; } oLogger.Info("Object `%s` with type `%s` loaded from file `%s`", pObject -> GetObjectName(), pObject -> GetObjectType(), sFullpath.c_str()); // Initialize module iRC = static_cast<Module *>(pObject) -> InitModule(oGlobalContext, oModuleConfig, oSigHandler, oLogger); if (iRC != 0) { oLogger.Emerg("Can't initialize module `%s` from file `%s`", sModuleName.c_str(), sFullpath.c_str()); delete pObject; return -1; } const STLW::string sFullName = sModuleType + '/' + sModuleName; vModules.push_back(sFullName); // Store object in factory if(oGlobalContext.factory.AddObject(sFullName, pObject) == NULL) { oLogger.Emerg("Can't add module `%s` from file `%s`", sModuleName.c_str(), sFullpath.c_str()); static_cast<Module *>(pObject) -> DestroyModule(oGlobalContext, oSigHandler, oLogger); delete pObject; return -1; } return 0; }