+/* Все глобальные функции экспортированы в request scope */
+function plain2htm(s) {
+ return replace(replace(s, chr(13),'',"ALL"),chr(10),'
', "ALL");
+}
+request.plain2htm = plain2htm;
+
+function htm2plain(s) {
+ return replaceNoCase(s, '
', '#chr(13)##chr(10)#', "ALL");
+}
+request.htm2plain = htm2plain;
+
+function cleanHtm(s) {
+ return replaceList(s, '<,>,"', '<,>,"');
+}
+request.cleanHtm = cleanHtm;
+
+function clean4CDATA(s) {
+ LF = chr(10);
+ return replaceNoCase(replaceList(s, '[,]', '&91;,&93;'),"
",LF,"ALL");
+}
+request.clean4CDATA = clean4CDATA;
+
+function numFmt(num, decimalPlaces = 0){
+ var sFormat = ",";
+ if (decimalPlaces GT 0) {sFormat = sFormat & "." & repeatString("0", decimalPlaces);}
+ return replace(NumberFormat(num, sFormat), ",", " ", "ALL");
+}
+request.numFmt = numFmt;
+
+function nFmt(num, decimalPlaces = 2){
+ if (num EQ 0) return "";
+ return numFmt(num, decimalPlaces);
+}
+request.nFmt = nFmt;
+
+function dateFmt(date, sFormat = 'YYYY-MM-DD'){
+ return dateFormat(date, sFormat);
+}
+request.dateFmt = dateFmt;
+
+function dateTimeFmt(date, sDateFormat = 'YYYY-MM-DD', sTimeFormat='HH:MM'){
+ return dateFormat(date, sDateFormat) & ' ' & timeFormat(date, sTimeFormat);
+}
+request.dateTimeFmt = dateTimeFmt;
+
+function timeFmt(date, sFormat = 'HH:MM'){
+ return timeFormat(date, sFormat);
+}
+request.timeFmt = timeFmt;
+
+//////////////////////////////////////////////////////
+function usrAuthenticated() {
+ return structKeyExists(request, "auth");
+}
+request.usrAuthenticated = usrAuthenticated;
+/////////////////////////////////////////////////////
+
+function filterOn(filter) {
+ return (isStruct(filter) AND NOT structIsEmpty(filter));
+}
+request.filterOn = filterOn;
+
+function stripWhiteSpace(sNumber) {
+ return reReplace(sNumber, "[[:space:]]", "", "ALL");
+}
+request.stripWhiteSpace = stripWhiteSpace;
+/*
+// never used
+function cleanNumber(sNumber) {
+ var s = reReplace(sNumber, "[[:space:]]", "", "ALL");
+ if ( find(",", s) ) { //watch argument order!!!
+ // assume Russian format with decimal comma and spaces for thousand separator
+ return replace(s, ",", ".");
+ } else {
+ // assume English format with decimal point and commas for thousand separator
+ return replace(s, ",", "", "ALL");
+ }
+}
+request.cleanNumber = cleanNumber;
+*/
+
+/*https://cflib.org/udf/queryColumnToArray*/
+/**
+ * Takes a selected column of data from a query and converts it into an array.
+ *
+ * @param query The query to scan. (Required)
+ * @param column The name of the column to return data from. (Required)
+ * @return Returns an array.
+ * @author Peter J. Farrell (pjf@maestropublishing.com)
+ * @version 1, July 22, 2005
+ */
+function queryColumnToArray(qry, column) {
+ var arr = arrayNew(1);
+ var ii = "";
+ var loop_len = arguments.qry.recordcount;
+ for (ii=1; ii lte loop_len; ii=ii+1) {
+ arrayAppend(arr, arguments.qry[arguments.column][ii]);
+ }
+ return arr;
+}
+request.queryColumnToArray = queryColumnToArray;
+
+/* ************************************* */
+
+function loginPasswordPolicyCheck(usr_id, login, passwd, passwd2) {
+ msg = "";
+ // для старого логина длина не проверяется, все равно ничего не поделаешь
+ if (NOT(usr_id GT 0) AND len(login) LE 3) {
+ msg="Слишком короткий логин (минимальная длина логина 3 символа)";
+ } else {
+ if (passwd NEQ passwd2) {
+ msg="Пароль и подтверждение не совпадают";
+ } else {
+ if (len(passwd) LT "8") msg="Слишком короткий пароль (минимальная длина пароля 8 символов)";
+ }
+ }
+ return msg;
+}
+request.loginPasswordPolicyCheck = loginPasswordPolicyCheck;
+
+function i18(label,label_en=label) {
+ //примитивная 2-язычная версия
+ if (request.language EQ 'en') {
+ return label_en;
+ } else {
+ return label;
+ };
+}
+request.i18 = i18;
+
+function passwordHashCreate(password) {
+ return GenerateArgon2Hash('#ARGUMENTS.password#', 'argon2id', 1, 16000, 2);
+}
+request.passwordHashCreate = passwordHashCreate;
+
+function passwordHashCheck(password, passwordHash) {
+ return Argon2CheckHash('#ARGUMENTS.password#', ARGUMENTS.passwordHash, 'argon2id');
+}
+request.passwordHashCheck = passwordHashCheck;
+/*
+function skuCode(area_code="", abstract_service_code="") {
+ var s="#arguments[1]#.#arguments[2]#";
+ if (arrayLen(arguments) GE 3) {
+ if (len(arguments[3]) GT 0) {
+ s="#s#.#arguments[3]#";
+ } else {
+ s="#s#.0";
+ };
+ };
+ if (arrayLen(arguments) GE 4) {
+ if (len(arguments[4]) GT 0) {
+ s="#s#.#arguments[4]#"
+ }
+ };
+ if (arrayLen(arguments) GE 5) {
+ var pricingModelSuffix=arguments[5];
+ s="#s#-#pricingModelSuffix#";
+ }
+ return s;
+}
+request.skuCode = skuCode;
+*/
+function roundSafe(a, precision) {
+ return (isNumeric(a) AND isNumeric(precision)) ? round(a,precision) : a;
+}
+request.roundSafe = roundSafe;
+
+function timeUnitLabel(n, value=0, locale="ru") {
+ var labels = ["сек.","мин.","ч.","д.","мес."];
+ if (n LE 5 AND n GE 1) {return labels[n];}
+ else if (n EQ 6) { // в зависимости от числа - "год" г. или "лет" л.
+ var m = value MOD 100;
+ if (m GE 11 AND m LE 20) {
+ return "л.";
+ }
+ m = m MOD 10;
+ if (m GE 1 AND m LE 4) {
+ return "г.";
+ }
+ return "л.";
+ }
+ throw (message="timeUnitLabelRu: index out of bounds", detail="Index must be from 1 to 6");
+}
+request.timeUnitLabel = timeUnitLabel;
+
+function dateDiffVerbose(dateFrom, dateTo, maxParts=6, maxPrecision=1, locale="ru") {
+// returns formatted datetime interval duration, e.g. 1 hour 5 minutes or 3 years 0 months 12 days
+//(currently, only Russian supported)
+//
+//maxParts specifies, how many parts to display
+//maxPrecision starts froms seconds: 1=seconds, 2=minutes, 3=hours, 4=days, 5=months, 6=years
+//if maxPrecision specified is greater than given time interval, output is nothing
+//locale=ru just for interface, not used
+//attention: truncates the tail, not rounds
+//example: request.dateDiffVerbose(Now(),Now()+373.1234567, 3, 1) produces 1 г. 0 мес. 8 д.
+//example: request.dateDiffVerbose(Now(),Now()+373.1234567, 6, 1) produces 1 г. 0 мес. 8 д. 2 ч. 57 мин. 46 сек.
+//intended common usage: request.dateDiffVerbose(dateFrom, dateTo, 2, 1) - prints 2 senior parts of the interval,
+//with presision not better than second
+//
+// this is not the same task as converting number of seconds to days-hours-minutes-seconds,
+// because months contain different number of days, and days number of february depends on year
+ try {
+ if (NOT (isDate(dateFrom) AND isDate(dateTo))) return "";
+ var UNIT_CODES = ["s","n","h","d","m","yyyy"];
+ var start = dateFrom;
+ var finish = dateTo;
+
+ var sOut = "";
+ var nUnits = 0;
+ var nPrintedPositions = 0;
+ var printStart = false;
+
+ for (i=ArrayLen(UNIT_CODES); i GT 0; i=i-1) {
+ nUnits = dateDiff(UNIT_CODES[i], start, finish);
+ start = dateAdd(UNIT_CODES[i], nUnits, start);
+ if (nPrintedPositions GT 0) {nPrintedPositions=nPrintedPositions+1;} //print started, so increment position
+ if (nPrintedPositions GT maxParts) {break;}
+ if (i LT maxPrecision) {break;}
+ if (nUnits NEQ 0 AND nPrintedPositions EQ 0) {nPrintedPositions=1;}
+ if (nPrintedPositions GT 0) {
+ if (len(sOut)) {sOut=sOut & " ";}
+ sOut=sOut & nUnits & " " & request.timeUnitLabel(i, nUnits, "ru");
+ }
+ }
+ return sOut;
+ } catch(e) {
+ return "";
+ }
+}
+request.dateDiffVerbose = dateDiffVerbose;
+
+/*
+function secondsToDHMS(nSeconds,partsToKeep) {
+//format seconds to days-hours-minutes-seconds and truncate to specified precision
+ {
+ days = n / (24 * 3600);
+
+ n = n % (24 * 3600);
+ hours = n / 3600;
+
+ n %= 3600;
+ minutes = n / 60 ;
+
+ n %= 60;
+ seconds = n;
+
+ return days & " " & "days "
+ & hours & " " & "hours "
+ & minutes & " " & "minutes "
+ & seconds & " " & "seconds ");
+ }
+}
+*/
+/**
+ * Formats a JSON string with indents and new lines.
+ * v1.0 by Ben Koshy (modified)
+ *
+ * @param str JSON string (Required)
+ * @return Returns a string of indent-formated JSON
+ * @author Ben Koshy (cf@animex.com)
+ * @version 0, September 16, 2012
+ */
+// formatJson() :: formats and indents JSON string
+// based on blog post @ http://ketanjetty.com/coldfusion/javascript/format-json/
+// modified for CFScript By Ben Koshy @animexcom
+// usage: result = formatJson('STRING TO BE FORMATTED') OR result = formatJson(StringVariableToFormat);
+
+// генерирует html разметку, чтобы не использовать и выровнять пробелы
+// содержит ошибку: делает перевод строки после запятой в строке в кавычках
+public string function formatJsonString(str) {
+ var fjson = '';
+ var pos = 0;
+ var strLen = len(arguments.str);
+ var indentStr = ' '; // Adjust Indent Token If you Like (замыкающий пробел - для выравнивания при пробелах после запятой)
+ var newLine = '
'; // Adjust New Line Token If you Like
+
+ for (var i=1; i<=strLen; i++) { //fix: <=
+ var char = mid(arguments.str,i,1);
+
+ if (char == '}' || char == ']') {
+ fjson &= newLine;
+ pos = pos - 1;
+
+ for (var j=1; j <= pos; j++) {
+ fjson &= indentStr;
+ }
+ }
+
+ fjson &= char;
+
+ if (char == '{' || char == '[' || char == ',') {
+ fjson &= newLine;
+
+ if (char == '{' || char == '[') {
+ pos = pos + 1;
+ }
+
+ for (var k=1; k <= pos; k++) {
+ fjson &= indentStr;
+ }
+ }
+ }
+
+ return fjson;
+}
+request.formatJsonString = formatJsonString;
+//нужна еще функция, которая сериализует структуру как pretty printed json. См. https://github.com/bennadel/JsonSerializer.cfc (все не совсем просто, например, не заранее не определен формат даты)
+
+
+