1 var DEBUG_ENABLED = require('../Config').DEBUG_ENABLED,
  2   DATA_TYPES = require('../constants/DataTypes'),
  3   ErrorMessages = require('../constants/ErrorMessages'),
  4   CAS = require('../constants/CASConstants');
  5 
  6 /**
  7  * Emit event only if there are registered listeners for the event
  8  * @param obj
  9  * @param successEvent
 10  * @param arg1
 11  * @param arg2
 12  * @private
 13  */
 14 function _emitSafeEvent(obj, successEvent, arg1, arg2) {
 15   if (obj.listeners(successEvent).length > 0) {
 16     if (typeof arg1 !== 'undefined' && typeof arg2 !== 'undefined') {
 17       obj.emit(successEvent, arg1, arg2);
 18     } else {
 19       if (typeof arg1 != 'undefined') {
 20         obj.emit(successEvent, arg1);
 21       } else {
 22         obj.emit(successEvent);
 23       }
 24     }
 25   }
 26 }
 27 
 28 /**
 29  * Emit ERROR event or success event
 30  * @param obj
 31  * @param err
 32  * @param errorEvent
 33  * @param successEvent
 34  * @private
 35  */
 36 exports._emitEvent = function (obj, err, errorEvent, successEvent, arg1, arg2) {
 37   if (typeof err != 'undefined' && err != null) {
 38     if (obj.listeners(errorEvent).length > 0) {
 39       obj.emit(errorEvent, err);
 40     }
 41   } else {
 42     _emitSafeEvent(obj, successEvent, arg1, arg2);
 43   }
 44 };
 45 
 46 /**
 47  * Validate if the value is an accepted "boolean"-compatible input
 48  * @param val
 49  * @return {Boolean}
 50  */
 51 exports._validateInputBoolean = function (val) {
 52   if (typeof val === 'boolean') {
 53     return true;
 54   } else {
 55     if (typeof val === 'number' && val % 1 === 0 && (val === 0 || val === 1)) {
 56       return true;
 57     }
 58   }
 59 
 60   return false;
 61 };
 62 
 63 /**
 64  * Validate if the value is an accepted "timeout" input
 65  * @param val
 66  * @return {Boolean}
 67  */
 68 exports._validateInputTimeout = function (val) {
 69   if (typeof val === 'undefined' || val === null || !(typeof val === 'number' && val % 1 === 0 && val >= 0)) {
 70     return false;
 71   }
 72 
 73   return true;
 74 };
 75 
 76 /**
 77  * Validate if the value is an accepted strict-positive "number" input
 78  * @param val
 79  * @return {Boolean}
 80  */
 81 exports._validateInputPositive = function (val) {
 82   if (typeof val === 'undefined' || val === null || !(typeof val === 'number' && val > 0)) {
 83     return false;
 84   }
 85 
 86   return true;
 87 };
 88 
 89 /**
 90  * Validate if the value is an accepted function input string
 91  * @param str
 92  * @return {Boolean}
 93  */
 94 exports._validateInputString = function (str) {
 95   if (typeof str === 'undefined' || str === null || typeof str != 'string' || str.length === 0) {
 96     return false;
 97   }
 98 
 99   return true;
100 };
101 
102 /**
103  * Validate if the value is accepted as a SQL statement string
104  * @param sql
105  * @return {Boolean}
106  */
107 exports._validateInputSQLString = function (sql) {
108   if (typeof sql === 'undefined' || sql === null || typeof sql != 'string' || sql.length <= 5) {
109     return false;
110   }
111 
112   return true;
113 };
114 
115 /**
116  * Format number values as 'money'
117  * http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript/149099#149099
118  * @param decimals
119  * @param decimal_sep
120  * @param thousands_sep
121  * @return {String}
122  */
123 Number.prototype.formatAsMoney = function (decimals, decimal_sep, thousands_sep) {
124   var n = this,
125     c = isNaN(decimals) ? 2 : Math.abs(decimals), //if decimal is zero we must take it, it means user does not want to show any decimal
126     d = decimal_sep || '.', //if no decimal separator is passed we use the dot as default decimal separator (we MUST use a decimal separator)
127     t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, //if you don't want to use a thousands separator you can pass empty string as thousands_sep value
128     sign = (n < 0) ? '-' : '',
129     i = parseInt(n = Math.abs(n).toFixed(c)) + '',
130     j;
131 
132   j = ((j = i.length) > 3) ? j % 3 : 0;
133 
134   return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : '');
135 };
136 
137 /**
138  * Escapes a string
139  * @param val
140  * @return {*}
141  * @private
142  */
143 var _escapeString = function (val) {
144   val = val.replace(/[\0\n\r\b\t\\'"\x1a]/g, function (s) {
145     switch (s) {
146       case "\0":
147         return "\\0";
148       case "\n":
149         return "\\n";
150       case "\r":
151         return "\\r";
152       case "\b":
153         return "\\b";
154       case "\t":
155         return "\\t";
156       case "\x1a":
157         return "\\Z";
158       case "\'":
159         return "''";
160       case "\"":
161         return '""';
162       default:
163         return "\\" + s;
164     }
165   });
166 
167   return val;
168 };
169 
170 exports._escapeString = _escapeString;
171 
172 /**
173  * Replaces '?' with values from an array; also, it performs string escaping.
174  * @param sql
175  * @param arrValues
176  * @param arrDelimiters
177  * @return {*}
178  * @private
179  */
180 exports._sqlFormat = function (sql, arrValues, arrDelimiters) {
181   arrValues = [].concat(arrValues);
182   if (arrDelimiters.length !== 0) {
183     arrDelimiters = [].concat(arrDelimiters);
184   } else {
185     arrDelimiters = ["'"];
186   }
187 
188   return sql.replace(/\?/g, function (match) {
189     if (!arrValues.length) {
190       return match;
191     }
192 
193     var val = arrValues.shift();
194     var delimiter = arrDelimiters.shift();
195 
196     if (val === undefined || val === null) {
197       return 'NULL';
198     }
199 
200     if (typeof val === 'number') {
201       return val + '';
202     }
203 
204     return delimiter + _escapeString(val) + delimiter;
205   });
206 };
207 
208 /**
209  * Verifies if a string starts with the specified value
210  */
211 if (typeof String.prototype.startsWith != 'function') {
212   String.prototype.startsWith = function (str) {
213     return this.indexOf(str) == 0;
214   };
215 }
216 
217 /**
218  * Appends two buffers data into a new buffer
219  * @param buffer
220  * @param value
221  * @return {Buffer}
222  * @private
223  */
224 exports._combineData = function (buffer, value) {
225   var newBuffer = new Buffer(buffer.length + value.length);
226 
227   buffer.copy(newBuffer, 0);
228   if (Array.isArray(value)) {
229     for (var i = 0; i < value.length; i++) {
230       if (typeof  value[i] == 'string') {
231         newBuffer[buffer.length + i] = value[i].charCodeAt(0);
232       } else {
233         newBuffer[buffer.length + i] = value[i];
234       }
235     }
236   } else {
237     if (typeof value == 'Buffer') {
238       value.copy(newBuffer, buffer.length);
239     } else {
240       new Buffer(value).copy(newBuffer, buffer.length);
241     }
242   }
243 
244   return newBuffer;
245 };
246 
247 /**
248  * Overrides the console output
249  * Logs data to the standard console output
250  * @param data
251  */
252 exports.logInfo = function logInfo(data) {
253   if (DEBUG_ENABLED) {
254     if (typeof window != 'undefined') {
255       if (!("console" in window) || !("firebug" in console)) {
256         var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
257         window.console = {};
258         for (var i = 0, len = names.length; i < len; ++i) {
259           window.console[names[i]] = function () {
260           };
261         }
262       }
263     }
264 
265     console.warn(data);
266   }
267 };
268 
269 /**
270  * Overrides the console output
271  * Logs data to the standard console output
272  * @param data
273  */
274 exports.logError = function logError(data) {
275   if (DEBUG_ENABLED) {
276     if (typeof window != 'undefined') {
277       if (!("console" in window) || !("firebug" in console)) {
278         var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
279         window.console = {};
280         for (var i = 0, len = names.length; i < len; ++i) {
281           window.console[names[i]] = function () {
282           };
283         }
284       }
285     }
286 
287     console.error(data);
288   }
289 };
290 
291 /**
292  * Get expected response length from the server
293  * @param buffer
294  * @return {Number}
295  */
296 exports._getExpectedResponseLength = function (buffer) {
297   var value = 0;
298 
299   for (var i = 0; i < DATA_TYPES.INT_SIZEOF; i++) {
300     value += buffer[i] * Math.pow(256, DATA_TYPES.INT_SIZEOF - i - 1);
301   }
302 
303   return value + DATA_TYPES.DATA_LENGTH_SIZEOF + DATA_TYPES.CAS_INFO_SIZE;
304 };
305 
306 /**
307  * Try to resolve the error code to a CUBRID error message
308  * @param errorCode
309  * @return {*}
310  */
311 exports._resolveErrorCode = function (errorCode) {
312   for (var i = 0; i < ErrorMessages.CASErrorMsgId.length; i++) {
313     if (errorCode == ErrorMessages.CASErrorMsgId[i][1]) {
314       return ErrorMessages.CASErrorMsgId[i][0];
315     }
316   }
317 };
318 
319 /**
320  * Returns the appropiate subfolder path for the packets definition that correspods
321  * to the current database engine version.
322  * Please note that you need to update this function any time the communication protocol changes.
323  * @param DBEngineVersion
324  * @return {String}
325  * @private
326  */
327 exports._translateDBEngineVersionToPacketsFolder = function (DBEngineVersion) {
328   if (DBEngineVersion.startsWith('8.4.1')) {
329     return '8.4.1';
330   } else {
331     if (DBEngineVersion.startsWith('9.0')) {
332       return '9.0';
333     } else {
334       //default value
335       return '8.4.1';
336     }
337   }
338 };
339 
340 
341