Comparing version 0.0.14 to 0.0.15
853
index.js
@@ -5,3 +5,3 @@ //----------------------------------------------------- | ||
// Site: 666.io | ||
// Version: 0.00.014 | ||
// Version: 0.00.015 | ||
// | ||
@@ -15,5 +15,13 @@ //----------------------------------------------------- | ||
var C_MODE_TYPENIZE = 1, | ||
C_MODE_SANITIZE = 2, | ||
C_MODE_VALIDATE = 3; | ||
var customTypesStore = {}, | ||
customRulesStore = {}; | ||
var typenizeSchemaStore = {}, | ||
sanitizeSchemaStore = {}, | ||
validateSchemaStore = {}; | ||
var gVPhones = { | ||
@@ -32,270 +40,284 @@ "ru-RU": /^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}$/, | ||
function validation(use, input, options, data) { | ||
switch(use) { | ||
case "null": | ||
return input === null; | ||
var gExport = { | ||
"createInstance": function(isGlobal) { | ||
var r = createInstance(); | ||
case "nan": | ||
return typeof(input) === "number" && isNaN(input); | ||
r.global(isGlobal); | ||
case "finite": | ||
return typeof(input) === "number" && isFinite(input); | ||
return r; | ||
}, | ||
//-----------------------]> | ||
//--------]> | ||
case "boolean": | ||
return typeof(input) === "boolean"; | ||
"global": function(v) { | ||
if(global && typeof(global) !== "object" || typeof(v) === "undefined") | ||
return this; | ||
case "string": | ||
if(typeof(input) !== "string") | ||
return false; | ||
if(v) { | ||
var gTObj = gExport.typenize, | ||
gSObj = gExport.sanitize, | ||
gVObj = gExport.validate; | ||
return !( | ||
(typeof(options.min) !== "undefined" && input.length < options.min) || | ||
(typeof(options.max) !== "undefined" && input.length > options.max) || | ||
(typeof(options.pattern) !== "undefined" && !options.pattern.test(input)) || | ||
(typeof(options.enum) !== "undefined" && options.enum.indexOf(input) === -1) | ||
); | ||
for(var i in gExport) { | ||
if(gExport.hasOwnProperty(i)) | ||
gTObj[i] = gSObj[i] = gVObj[i] = gExport[i]; | ||
} | ||
case "integer": | ||
if(typeof(input) !== "number" || isNaN(input)) | ||
return false; | ||
if(typeof(global.$typenize) === "undefined") | ||
global.$typenize = gTObj; | ||
return !( | ||
(input !== parseInt(input, 10)) || | ||
(typeof(options.min) !== "undefined" && input < options.min) || | ||
(typeof(options.max) !== "undefined" && input > options.max) || | ||
(typeof(options.divisibleBy) !== "undefined" && (input % options.divisibleBy) !== 0) || | ||
(typeof(options.enum) !== "undefined" && options.enum.indexOf(input) === -1) | ||
); | ||
if(typeof(global.$sanitize) === "undefined") | ||
global.$sanitize = gSObj; | ||
case "float": | ||
if(typeof(input) !== "number" || isNaN(input)) | ||
return false; | ||
if(typeof(global.$validate) === "undefined") | ||
global.$validate = gVObj; | ||
} else { | ||
if(global.$typenize === gExport.typenize) | ||
delete global.$typenize; | ||
return !( | ||
(typeof(options.min) !== "undefined" && input < options.min) || | ||
(typeof(options.max) !== "undefined" && input > options.max) || | ||
(typeof(options.divisibleBy) !== "undefined" && (input % options.divisibleBy) !== 0) || | ||
(typeof(options.enum) !== "undefined" && options.enum.indexOf(input) === -1) | ||
); | ||
if(global.$sanitize === gExport.sanitize) | ||
delete global.$sanitize; | ||
case "date": | ||
if(!(input instanceof(Date)) || !input.getTime()) | ||
return false; | ||
if(global.$validate === gExport.validate) | ||
delete global.$validate; | ||
} | ||
return !( | ||
(typeof(options.min) !== "undefined" && input < options.min) || | ||
(typeof(options.max) !== "undefined" && input > options.max) | ||
); | ||
return this; | ||
}, | ||
case "hashTable": | ||
if(Array.isArray(input) || !input) | ||
return false; | ||
"type": function(name, func) { | ||
wFuncStore(name, func, customTypesStore); | ||
return this; | ||
}, | ||
return typeof(input) === "object"; | ||
"rule": function(name, func) { | ||
wFuncStore(name, func, customRulesStore); | ||
return this; | ||
}, | ||
case "array": | ||
if(!Array.isArray(input)) | ||
return false; | ||
//--------]> | ||
return !( | ||
(typeof(options.min) !== "undefined" && input.length < options.min) || | ||
(typeof(options.max) !== "undefined" && input.length > options.max) | ||
); | ||
"typenize": function(schema, data, options) { | ||
return parseSchema(C_MODE_TYPENIZE, schema, data, options, { | ||
"string": function(schema, data, options) { | ||
return $typenize(schema, data, options); | ||
}, | ||
case "json": | ||
return input === null || typeof(input) === "object"; | ||
"hashTable": function(schema, data, options) { | ||
var optScenario = options.on; | ||
//-----------------------]> | ||
var result = {}; | ||
case "required": | ||
return !( | ||
input === null || typeof(input) === "undefined" || | ||
(typeof(input) === "number" && input !== input) || | ||
(typeof(input) === "string" && !input.length) || | ||
(input instanceof(Date) && !input.getTime()) | ||
); | ||
for(var field in schema) { | ||
if(!Object.prototype.hasOwnProperty.call(schema, field)) continue; | ||
case "equal": | ||
var d; | ||
var nameFunc, | ||
schemaData = schema[field], | ||
fieldData = data[field]; | ||
if(typeof(options.value) !== "undefined") { | ||
d = options.value; | ||
if(!schemaData) { | ||
throw new Error("[!] Typenize | schemaData: " + schemaData); | ||
} | ||
if(typeof(input) !== "string") | ||
input = normalize("string", input); | ||
//-----------------)> | ||
if(typeof(d) !== "string") | ||
d = normalize("string", d); | ||
if(typeof(schemaData) === "string") { | ||
nameFunc = schemaData; | ||
schemaData = {}; | ||
} | ||
else if(typeof(schemaData) === "object") { | ||
nameFunc = schemaData.type || schemaData.use; | ||
return input === d; | ||
} | ||
if(typeof(schemaData.on) !== "undefined" && schemaData.on != optScenario) | ||
continue; | ||
} | ||
else { | ||
throw new Error("[!] Typenize | schemaData: " + schemaData); | ||
} | ||
if(typeof(options.field) !== "undefined" && data && typeof(data) === "object") { | ||
d = data[options.field]; | ||
if(nameFunc[0] === "?") { | ||
if(typeof(fieldData) === "undefined") | ||
continue; | ||
if(typeof(input) !== "string") | ||
input = normalize("string", input); | ||
nameFunc = nameFunc.substring(1); | ||
} | ||
if(typeof(d) !== "string") | ||
d = normalize("string", d); | ||
//-----------------)> | ||
return input === d; | ||
result[field] = $typenize(nameFunc, fieldData, schemaData); | ||
} | ||
return result; | ||
} | ||
}); | ||
}, | ||
return false; | ||
"sanitize": function(schema, data, options) { | ||
return parseSchema(C_MODE_SANITIZE, schema, data, options, { | ||
"string": function(schema, data, options) { | ||
return $sanitize(schema, $typenize(schema, data, options), options); | ||
}, | ||
case "notEmpty": | ||
return typeof(input) === "string" && !input.match(/^[\s\t\r\n]*$/); | ||
"hashTable": function(schema, data, options) { | ||
var optScenario = options.on; | ||
case "lowercase": | ||
return typeof(input) === "string" && input === input.toLowerCase(); | ||
var result = {}; | ||
case "uppercase": | ||
return typeof(input) === "string" && input === input.toUpperCase(); | ||
for(var field in schema) { | ||
if(!Object.prototype.hasOwnProperty.call(schema, field)) continue; | ||
//-----------------------]> | ||
var nameFunc, | ||
schemaData = schema[field], | ||
fieldData = data[field]; | ||
case "wordchar": | ||
return typeof(input) === "string" && !!input.match(/^[\w]+$/); | ||
if(!schemaData) { | ||
throw new Error("[!] Sanitize | schemaData: " + schemaData); | ||
} | ||
case "alphanumeric": | ||
return typeof(input) === "string" && !!input.match(/^[a-zA-Z0-9]+$/); | ||
//-----------------)> | ||
case "alpha": | ||
return typeof(input) === "string" && !!input.match(/^[a-zA-Z]+$/); | ||
if(typeof(schemaData) === "string") { | ||
nameFunc = schemaData; | ||
schemaData = {}; | ||
} | ||
else if(typeof(schemaData) === "object") { | ||
nameFunc = schemaData.type || schemaData.use; | ||
case "numeric": | ||
return typeof(input) === "string" && !!input.match(/^[0-9]+$/); | ||
if(typeof(schemaData.on) !== "undefined" && schemaData.on != optScenario) | ||
continue; | ||
} | ||
else { | ||
throw new Error("[!] Sanitize | schemaData: " + schemaData); | ||
} | ||
case "hexadecimal": | ||
return typeof(input) === "string" && !!input.match(/^[0-9a-fA-F]+$/); | ||
if(nameFunc[0] === "?") { | ||
if(typeof(fieldData) === "undefined") | ||
continue; | ||
case "email": | ||
return typeof(input) === "string" && !!input.match(/^(?:[\w\!\#\$\%\&\"\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\"\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/); | ||
nameFunc = nameFunc.substring(1); | ||
} | ||
case "url": | ||
return typeof(input) === "string" && !!input.match(/^(?!mailto:)(?:(?:https?|ftp|ssh|ws|gopher|news|telnet|ldap):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i); | ||
//-----------------)> | ||
case "mongoId": | ||
return typeof(input) === "string" && !!input.match(/^[0-9a-fA-F]{24}$/); | ||
result[field] = $sanitize(nameFunc, $typenize(nameFunc, fieldData, schemaData), schemaData); | ||
} | ||
//-----------------------]> | ||
case "hexColor": | ||
if(typeof(input) !== "string") | ||
return false; | ||
return !!input.match(options.strict ? /^#[0-9A-F]{6}$/i : /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i); | ||
case "creditcard": | ||
if(typeof(input) !== "string") | ||
return false; | ||
input = input.replace(/[^0-9]+/g, ""); | ||
if(!input || !input.match(/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/)) | ||
return false; | ||
var sum = 0, shouldDouble = false; | ||
var digit, tmpNum; | ||
for(var i = input.length - 1; i >= 0; i--) { | ||
digit = input.substring(i, (i + 1)); | ||
tmpNum = parseInt(digit, 10); | ||
if(shouldDouble) { | ||
tmpNum *= 2; | ||
sum += (tmpNum >= 10) ? ((tmpNum % 10) + 1) : tmpNum; | ||
} else | ||
sum += tmpNum; | ||
shouldDouble = !shouldDouble; | ||
return result; | ||
} | ||
}); | ||
}, | ||
return (sum % 10) === 0; | ||
"validate": function(schema, data, options) { | ||
return parseSchema(C_MODE_VALIDATE, schema, data, options, { | ||
"string": function(schema, data, options) { | ||
return $validate(schema, data, options, options.data); | ||
}, | ||
case "phone": | ||
if(!input || typeof(input) !== "string") | ||
return false; | ||
"hashTable": function(schema, data, options) { | ||
var optScenario = options.on, | ||
optErrors = options.errors; | ||
///---)> | ||
var result = optErrors ? null : true; | ||
var rgPhone = gVPhones[options.locale || "ru-RU"]; | ||
for(var field in schema) { | ||
if(!Object.prototype.hasOwnProperty.call(schema, field)) continue; | ||
return rgPhone && rgPhone.test(input); | ||
var nameFunc, | ||
case "uuid": | ||
if(!input || typeof(input) !== "string") | ||
return false; | ||
schemaData = schema[field], | ||
fieldData = data[field]; | ||
///---)> | ||
if(!schemaData) { | ||
throw new Error("[!] Validation | schemaData: " + schemaData); | ||
} | ||
var version = options.version, | ||
pattern; | ||
//-----------------)> | ||
if(version == 3 || version == "v3") | ||
pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i; | ||
else if(version == 4 || version == "v4") | ||
pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; | ||
else if(version == 5 || version == "v5") | ||
pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; | ||
else | ||
pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i; | ||
if(typeof(schemaData) === "string") { | ||
nameFunc = schemaData; | ||
schemaData = {}; | ||
} | ||
else if(typeof(schemaData) === "object") { | ||
nameFunc = schemaData.rule || schemaData.use; | ||
return pattern.test(input); | ||
if(typeof(schemaData.on) !== "undefined" && schemaData.on != optScenario) | ||
continue; | ||
} | ||
else { | ||
throw new Error("[!] Validation | schemaData: " + schemaData); | ||
} | ||
case "ip": | ||
if(!input || typeof(input) !== "string") | ||
return false; | ||
if(nameFunc[0] === "?") { | ||
if(typeof(fieldData) === "undefined") | ||
continue; | ||
///---)> | ||
var version = options.version, | ||
ipV4 = function() { | ||
if((/^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$/).test(input)) { | ||
var parts = input.split(".").sort(); | ||
// no need to check for < 0 as regex won't match in that case | ||
return !(parts[3] > 255); | ||
nameFunc = nameFunc.substring(1); | ||
} | ||
}; | ||
///---)> | ||
//-----------------)> | ||
if(version && version != 4 && version != 6) | ||
return false; | ||
if(!$validate(nameFunc, fieldData, schemaData, data)) { | ||
if(optErrors) { | ||
result = result || []; | ||
result.push({ | ||
"field": field, | ||
"use": nameFunc, | ||
if(!version && !ipV4() && !(/^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/).test(input)) | ||
return false; | ||
"input": fieldData | ||
}); | ||
} else { | ||
result = false; | ||
break; | ||
} | ||
} | ||
} | ||
if(version == 4 && !ipV4()) | ||
return false; | ||
return result; | ||
} | ||
}); | ||
} | ||
}; | ||
if(version == 6 && !(/^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/).test(input)) | ||
return false; | ||
//---------[Storage]----------}> | ||
return true; | ||
{ | ||
var gTObj = gExport.typenize, | ||
gSObj = gExport.sanitize, | ||
gVObj = gExport.validate; | ||
case "ascii": | ||
return typeof(input) === "string" && (/^[\x00-\x7F]+$/).test(input); | ||
["set", "get", "run"] | ||
.forEach(function(name) { | ||
function buildFunc(obj, store) { | ||
switch(name) { | ||
case "set": | ||
return function(name, data) { | ||
store[name] = data; | ||
return obj; | ||
}; | ||
case "base64": | ||
return typeof(input) === "string" && (/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/).test(input); | ||
case "get": | ||
return function(name) { | ||
return store[name]; | ||
}; | ||
//------------------------]> | ||
case "run": | ||
return function(name, data, options) { | ||
return obj(store[name], data, options); | ||
}; | ||
} | ||
} | ||
default: | ||
var func = customRulesStore[use]; | ||
gTObj[name] = buildFunc(gTObj, typenizeSchemaStore); | ||
gSObj[name] = buildFunc(gSObj, sanitizeSchemaStore); | ||
gVObj[name] = buildFunc(gVObj, validateSchemaStore); | ||
}); | ||
} | ||
if(func) | ||
return func(input, options); | ||
//------------------)> | ||
throw new Error("[!] Validation | Unknown rule.\n" + use + " : " + JSON.stringify(options)); | ||
} | ||
} | ||
return gExport; | ||
//-----------------------------]> | ||
function normalize(type, input, options) { | ||
function $typenize(type, input, options) { | ||
if(type === "custom") | ||
@@ -348,4 +370,8 @@ return input; | ||
if(!input || Array.isArray(input)) | ||
return {}; | ||
input = {}; | ||
if(typeof(options.schema) === "object") { | ||
return gExport.typenize(options.schema, input, options); | ||
} | ||
if(typeof(input) === "object") | ||
@@ -402,7 +428,7 @@ return input; | ||
throw new Error("[!] Sanitizer | Unknown type.\n" + type + " : " + JSON.stringify(options)); | ||
throw new Error("[!] Sanitize | Unknown type.\n" + type + " : " + JSON.stringify(options)); | ||
} | ||
} | ||
function postNormilize(type, input, options) { | ||
function $sanitize(type, input, options) { | ||
switch(type) { | ||
@@ -537,241 +563,344 @@ case "string": | ||
//-------[HELPERS]-------}> | ||
function $validate(use, input, options, data) { | ||
switch(use) { | ||
case "null": | ||
return input === null; | ||
function wFuncStore(name, func, store) { | ||
if(name === null) | ||
return; | ||
case "nan": | ||
return typeof(input) === "number" && isNaN(input); | ||
switch(typeof(name)) { | ||
case "finite": | ||
return typeof(input) === "number" && isFinite(input); | ||
//-----------------------]> | ||
case "boolean": | ||
return typeof(input) === "boolean"; | ||
case "string": | ||
if(func === null) delete store[name]; | ||
else if(typeof(func) === "function") store[name] = func; | ||
if(typeof(input) !== "string") | ||
return false; | ||
break; | ||
return !( | ||
(typeof(options.min) !== "undefined" && input.length < options.min) || | ||
(typeof(options.max) !== "undefined" && input.length > options.max) || | ||
(typeof(options.pattern) !== "undefined" && !options.pattern.test(input)) || | ||
(typeof(options.enum) !== "undefined" && options.enum.indexOf(input) === -1) | ||
); | ||
case "object": | ||
for(var field in name) { | ||
if(!Object.prototype.hasOwnProperty.call(name, field)) continue; | ||
case "integer": | ||
if(typeof(input) !== "number" || isNaN(input)) | ||
return false; | ||
func = name[field]; | ||
return !( | ||
(input !== parseInt(input, 10)) || | ||
(typeof(options.min) !== "undefined" && input < options.min) || | ||
(typeof(options.max) !== "undefined" && input > options.max) || | ||
(typeof(options.divisibleBy) !== "undefined" && (input % options.divisibleBy) !== 0) || | ||
(typeof(options.enum) !== "undefined" && options.enum.indexOf(input) === -1) | ||
); | ||
if(func === null) delete store[name]; | ||
else if(typeof(func) === "function") store[name] = func; | ||
} | ||
case "float": | ||
if(typeof(input) !== "number" || isNaN(input)) | ||
return false; | ||
break; | ||
} | ||
} | ||
return !( | ||
(typeof(options.min) !== "undefined" && input < options.min) || | ||
(typeof(options.max) !== "undefined" && input > options.max) || | ||
(typeof(options.divisibleBy) !== "undefined" && (input % options.divisibleBy) !== 0) || | ||
(typeof(options.enum) !== "undefined" && options.enum.indexOf(input) === -1) | ||
); | ||
//-----------------------------]> | ||
case "date": | ||
if(!(input instanceof(Date)) || !input.getTime()) | ||
return false; | ||
var gExport = { | ||
"global": function(v) { | ||
if(global && typeof(global) !== "object" || typeof(v) === "undefined") | ||
return this; | ||
return !( | ||
(typeof(options.min) !== "undefined" && input < options.min) || | ||
(typeof(options.max) !== "undefined" && input > options.max) | ||
); | ||
if(v) { | ||
var gSObj = gExport.sanitize, | ||
gVObj = gExport.validate; | ||
case "hashTable": | ||
if(Array.isArray(input) || !input) | ||
return false; | ||
for(var i in gExport) { | ||
if(gExport.hasOwnProperty(i)) | ||
gSObj[i] = gVObj[i] = gExport[i]; | ||
} | ||
return typeof(input) === "object"; | ||
if(typeof(global.$sanitize) === "undefined") | ||
global.$sanitize = gSObj; | ||
case "array": | ||
if(!Array.isArray(input)) | ||
return false; | ||
if(typeof(global.$validate) === "undefined") | ||
global.$validate = gVObj; | ||
} else { | ||
if(global.$sanitize === gExport.sanitize) | ||
delete global.$sanitize; | ||
return !( | ||
(typeof(options.min) !== "undefined" && input.length < options.min) || | ||
(typeof(options.max) !== "undefined" && input.length > options.max) | ||
); | ||
if(global.$validate === gExport.validate) | ||
delete global.$validate; | ||
} | ||
case "json": | ||
return input === null || typeof(input) === "object"; | ||
return this; | ||
}, | ||
//-----------------------]> | ||
"type": function(name, func) { | ||
wFuncStore(name, func, customTypesStore); | ||
return this; | ||
}, | ||
case "required": | ||
return !( | ||
input === null || typeof(input) === "undefined" || | ||
(typeof(input) === "number" && input !== input) || | ||
(typeof(input) === "string" && !input.length) || | ||
(input instanceof(Date) && !input.getTime()) | ||
); | ||
"rule": function(name, func) { | ||
wFuncStore(name, func, customRulesStore); | ||
return this; | ||
}, | ||
case "equal": | ||
var d; | ||
//--------]> | ||
if(typeof(options.value) !== "undefined") { | ||
d = options.value; | ||
"sanitize": function(schema, data, options) { | ||
if(!schema) | ||
throw new Error("[!] Sanitizer | schema: " + schema); | ||
if(typeof(input) !== "string") | ||
input = $typenize("string", input); | ||
options = options || {}; | ||
if(typeof(d) !== "string") | ||
d = $typenize("string", d); | ||
//----------------]> | ||
return input === d; | ||
} | ||
if(typeof(schema) === "string") { | ||
if(schema[0] == "?") { | ||
if(typeof(data) == "undefined") | ||
return undefined; | ||
if(typeof(options.field) !== "undefined" && data && typeof(data) === "object") { | ||
d = data[options.field]; | ||
schema = schema.substring(1); | ||
if(typeof(input) !== "string") | ||
input = $typenize("string", input); | ||
if(typeof(d) !== "string") | ||
d = $typenize("string", d); | ||
return input === d; | ||
} | ||
return postNormilize(schema, normalize(schema, data, options), options); | ||
} | ||
return false; | ||
if(typeof(schema) === "object") { | ||
if(!data || typeof(data) !== "object") | ||
return null; | ||
case "notEmpty": | ||
return typeof(input) === "string" && !input.match(/^[\s\t\r\n]*$/); | ||
//----------------)> | ||
case "lowercase": | ||
return typeof(input) === "string" && input === input.toLowerCase(); | ||
var optScenario = options.on; | ||
case "uppercase": | ||
return typeof(input) === "string" && input === input.toUpperCase(); | ||
var result = {}; | ||
//-----------------------]> | ||
for(var field in schema) { | ||
if(!Object.prototype.hasOwnProperty.call(schema, field)) continue; | ||
case "wordchar": | ||
return typeof(input) === "string" && !!input.match(/^[\w]+$/); | ||
var nameFunc, | ||
schemaData = schema[field], | ||
fieldData = data[field]; | ||
case "alphanumeric": | ||
return typeof(input) === "string" && !!input.match(/^[a-zA-Z0-9]+$/); | ||
//-----------------)> | ||
case "alpha": | ||
return typeof(input) === "string" && !!input.match(/^[a-zA-Z]+$/); | ||
if(!schemaData) { | ||
throw new Error("[!] Sanitizer | schemaData: " + schemaData); | ||
} | ||
case "numeric": | ||
return typeof(input) === "string" && !!input.match(/^[0-9]+$/); | ||
if(typeof(schemaData) === "string") { | ||
nameFunc = schemaData; | ||
schemaData = {}; | ||
} else if(typeof(schemaData) === "object") { | ||
nameFunc = schemaData.type || schemaData.use; | ||
case "hexadecimal": | ||
return typeof(input) === "string" && !!input.match(/^[0-9a-fA-F]+$/); | ||
if(typeof(schemaData.on) !== "undefined" && schemaData.on != optScenario) | ||
continue; | ||
} else { | ||
throw new Error("[!] Sanitizer | schemaData: " + schemaData); | ||
} | ||
case "email": | ||
return typeof(input) === "string" && !!input.match(/^(?:[\w\!\#\$\%\&\"\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\"\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/); | ||
if(nameFunc[0] === "?") { | ||
if(typeof(fieldData) === "undefined") | ||
continue; | ||
case "url": | ||
return typeof(input) === "string" && !!input.match(/^(?!mailto:)(?:(?:https?|ftp|ssh|ws|gopher|news|telnet|ldap):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i); | ||
nameFunc = nameFunc.substring(1); | ||
} | ||
case "mongoId": | ||
return typeof(input) === "string" && !!input.match(/^[0-9a-fA-F]{24}$/); | ||
//-----------------)> | ||
//-----------------------]> | ||
result[field] = postNormilize(nameFunc, normalize(nameFunc, fieldData, schemaData), schemaData); | ||
} | ||
case "hexColor": | ||
if(typeof(input) !== "string") | ||
return false; | ||
return result; | ||
} | ||
return !!input.match(options.strict ? /^#[0-9A-F]{6}$/i : /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i); | ||
//----------------]> | ||
case "creditcard": | ||
if(typeof(input) !== "string") | ||
return false; | ||
throw new Error("[!] Sanitizer | schema: " + schema); | ||
}, | ||
input = input.replace(/[^0-9]+/g, ""); | ||
"validate": function(schema, data, options) { | ||
if(!schema) | ||
throw new Error("[!] Validation | schema: " + schema); | ||
if(!input || !input.match(/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/)) | ||
return false; | ||
options = options || {}; | ||
var sum = 0, shouldDouble = false; | ||
var digit, tmpNum; | ||
//----------------]> | ||
for(var i = input.length - 1; i >= 0; i--) { | ||
digit = input.substring(i, (i + 1)); | ||
tmpNum = parseInt(digit, 10); | ||
if(typeof(schema) === "string") { | ||
if(schema[0] == "?") { | ||
if(typeof(data) == "undefined") | ||
return true; | ||
if(shouldDouble) { | ||
tmpNum *= 2; | ||
sum += (tmpNum >= 10) ? ((tmpNum % 10) + 1) : tmpNum; | ||
} else | ||
sum += tmpNum; | ||
schema = schema.substring(1); | ||
shouldDouble = !shouldDouble; | ||
} | ||
return validation(schema, data, options, options.data); | ||
} | ||
return (sum % 10) === 0; | ||
//-------]> | ||
case "phone": | ||
if(!input || typeof(input) !== "string") | ||
return false; | ||
if(typeof(schema) === "object") { | ||
if(!data || typeof(data) !== "object") | ||
///---)> | ||
var rgPhone = gVPhones[options.locale || "ru-RU"]; | ||
return rgPhone && rgPhone.test(input); | ||
case "uuid": | ||
if(!input || typeof(input) !== "string") | ||
return false; | ||
//----------------)> | ||
///---)> | ||
var optScenario = options.on, | ||
optErrors = options.errors; | ||
var version = options.version, | ||
pattern; | ||
var result = optErrors ? null : true; | ||
if(version == 3 || version == "v3") | ||
pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i; | ||
else if(version == 4 || version == "v4") | ||
pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; | ||
else if(version == 5 || version == "v5") | ||
pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; | ||
else | ||
pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i; | ||
for(var field in schema) { | ||
if(!Object.prototype.hasOwnProperty.call(schema, field)) continue; | ||
return pattern.test(input); | ||
var nameFunc, | ||
case "ip": | ||
if(!input || typeof(input) !== "string") | ||
return false; | ||
schemaData = schema[field], | ||
fieldData = data[field]; | ||
///---)> | ||
//-----------------)> | ||
var version = options.version, | ||
ipV4 = function() { | ||
if((/^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$/).test(input)) { | ||
var parts = input.split(".").sort(); | ||
// no need to check for < 0 as regex won't match in that case | ||
return !(parts[3] > 255); | ||
} | ||
}; | ||
if(!schemaData) { | ||
throw new Error("[!] Validation | schemaData: " + schemaData); | ||
} | ||
///---)> | ||
if(typeof(schemaData) === "string") { | ||
nameFunc = schemaData; | ||
schemaData = {}; | ||
} else if(typeof(schemaData) === "object") { | ||
nameFunc = schemaData.rule || schemaData.use; | ||
if(version && version != 4 && version != 6) | ||
return false; | ||
if(typeof(schemaData.on) !== "undefined" && schemaData.on != optScenario) | ||
continue; | ||
} else { | ||
throw new Error("[!] Validation | schemaData: " + schemaData); | ||
} | ||
if(!version && !ipV4() && !(/^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/).test(input)) | ||
return false; | ||
if(nameFunc[0] === "?") { | ||
if(typeof(fieldData) === "undefined") | ||
continue; | ||
if(version == 4 && !ipV4()) | ||
return false; | ||
nameFunc = nameFunc.substring(1); | ||
} | ||
if(version == 6 && !(/^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/).test(input)) | ||
return false; | ||
//-----------------)> | ||
return true; | ||
case "ascii": | ||
return typeof(input) === "string" && (/^[\x00-\x7F]+$/).test(input); | ||
if(!validation(nameFunc, fieldData, schemaData, data)) { | ||
if(optErrors) { | ||
result = result || []; | ||
result.push({ | ||
"field": field, | ||
"use": nameFunc, | ||
case "base64": | ||
return typeof(input) === "string" && (/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/).test(input); | ||
"input": fieldData | ||
}); | ||
} else { | ||
result = false; | ||
break; | ||
} | ||
//------------------------]> | ||
default: | ||
var func = customRulesStore[use]; | ||
if(func) | ||
return func(input, options); | ||
throw new Error("[!] Validation | Unknown rule.\n" + use + " : " + JSON.stringify(options)); | ||
} | ||
} | ||
//-------[HELPERS]-------}> | ||
function parseSchema(mode, schema, data, options, callbacks) { | ||
if(!schema) | ||
throw new Error("[!] Empty schema."); | ||
options = options || {}; | ||
//----------------]> | ||
if(typeof(schema) === "string") { | ||
if(schema[0] === "?") { | ||
if(typeof(data) === "undefined") { | ||
switch(mode) { | ||
case C_MODE_TYPENIZE: | ||
case C_MODE_SANITIZE: | ||
return undefined; | ||
case C_MODE_VALIDATE: | ||
return true; | ||
} | ||
} | ||
return result; | ||
schema = schema.substring(1); | ||
} | ||
//----------------]> | ||
return callbacks.string(schema, data, options); | ||
} | ||
throw new Error("[!] Validation | schema: " + schema); | ||
//-------]> | ||
if(typeof(schema) === "object" && !Array.isArray(schema)) { | ||
if(!data || typeof(data) !== "object") { | ||
switch(mode) { | ||
case C_MODE_TYPENIZE: | ||
case C_MODE_SANITIZE: | ||
return null; | ||
case C_MODE_VALIDATE: | ||
return false; | ||
} | ||
} | ||
//----------------)> | ||
return callbacks.hashTable(schema, data, options); | ||
} | ||
}; | ||
return gExport; | ||
//----------------]> | ||
throw new Error("[!] Invalid schema."); | ||
} | ||
function wFuncStore(name, func, store) { | ||
if(name === null) | ||
return; | ||
switch(typeof(name)) { | ||
case "string": | ||
if(func === null) delete store[name]; | ||
else if(typeof(func) === "function") store[name] = func; | ||
break; | ||
case "object": | ||
for(var field in name) { | ||
if(!Object.prototype.hasOwnProperty.call(name, field)) continue; | ||
func = name[field]; | ||
if(func === null) delete store[name]; | ||
else if(typeof(func) === "function") store[name] = func; | ||
} | ||
break; | ||
} | ||
} | ||
})(); | ||
@@ -778,0 +907,0 @@ |
{ | ||
"name": "aigis", | ||
"version": "0.0.14", | ||
"description": "Simple and Powerful module for strict validation", | ||
"version": "0.0.15", | ||
"description": "Simple and Powerful module for strict data control", | ||
"homepage": "http://666.io", | ||
"keywords": [ | ||
"typenize", | ||
"sanitize", | ||
"validate", | ||
@@ -9,0 +11,0 @@ "validation", |
@@ -7,13 +7,54 @@ `npm install aigis -g` | ||
var schema = { | ||
"name": {"type": "string", "rule": "required", "max": 3, "trim": true}, | ||
"status": "?string", | ||
"pts": {"use": "integer", "max": 30, "abs": true} | ||
var schema = { | ||
"name": { | ||
"type": "string", | ||
"rule": "required", | ||
"max": 3, | ||
"trim": true | ||
}, | ||
"status": "?string", | ||
"pts": { | ||
"use": "integer", | ||
"max": 30, | ||
"abs": true | ||
}, | ||
"data": { | ||
"type": "hashTable", | ||
"schema": { | ||
"login": "string", | ||
"password": "string", | ||
"more": { | ||
"type": "hashTable", | ||
"schema": { | ||
"someData": "string" | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
data = {"name": " XX + ", "pts": "-60", "delThisField": "data"}; | ||
$sanitize(schema, data); //_ { name: 'XX', pts: 30 } | ||
$validate(schema, data); //_ false | ||
data = {"name": " XX + ", "pts": "-60", "delThisField": "data"}; | ||
$typenize(schema, data); | ||
$sanitize(schema, data); | ||
$validate(schema, data); | ||
//_ $typenize: | ||
// { name: ' XX + ', pts: -60, data: { login: '', password: '', more: { someData: '' } } } | ||
//_ $sanitize: | ||
// { name: 'XX', pts: 30, data: { login: '', password: '', more: { someData: '' } } } | ||
//_ $validate: false | ||
``` | ||
* Support schema-tree: + | ||
* Tests: + | ||
@@ -34,8 +75,11 @@ * Examples: + | ||
| | - || | ||
| global | Set `$sanitize, $validate` as Global Var (NodeJS) | (v [default: true]) | | ||
| type | Set/Delete custom Type (Sanitize) | (name (String/HashTable), [func]) ~ func(input, options) | | ||
| rule | Set/Delete custom Rule (Validate) | (name (String/HashTable), [func]) ~ func(input, options) | | ||
| | - || | ||
| sanitize | - | (schema (String/HashTable), data, [options]) | | ||
| validate | - | (schema (String/HashTable), data, [options]) | | ||
| createInstance | Create new instance | ([isGlobal]) | | ||
| global | Set `$typenize, $sanitize, $validate` as Global Var (NodeJS) | (v [default: true]) | | ||
| | - || | ||
| type | Set/Delete custom Type (Sanitize) | (name (String/HashTable), [func]) ~ func(input, options) | | ||
| rule | Set/Delete custom Rule (Validate) | (name (String/HashTable), [func]) ~ func(input, options) | | ||
| | - || | ||
| typenize | - | (schema (String/HashTable), data, [options]) | | ||
| sanitize | - | (schema (String/HashTable), data, [options]) | | ||
| validate | - | (schema (String/HashTable), data, [options]) | | ||
@@ -46,8 +90,11 @@ | ||
| | - || | ||
| | ALL || | ||
| on | Scenario | - | | ||
| | - || | ||
| | Validate || | ||
| errors | Validate method returns null or an array of errors | true/false (def: false)| | ||
| on | Scenario | - | | ||
```js | ||
//_ Error: structure | ||
//_ Validation error: structure | ||
{ | ||
@@ -62,5 +109,22 @@ "field": field, | ||
#### Typenize | ||
| Type | Desc | Params/Options | | ||
|-------------|-------------|-------------| | ||
| | - || | ||
| | ALL (If `schema` is HashTable) | on | | ||
| custom | - || | ||
| boolean | true: "true", "on", "yes", "1" || | ||
| string | - || | ||
| integer | - || | ||
| float | - || | ||
| date | - || | ||
| hashTable | - | schema | | ||
| array | - || | ||
| json | - || | ||
#### Sanitize | ||
| Type | Desc | Val | | ||
| Type | Desc | Params/Options | | ||
|-------------|-------------|-------------| | ||
@@ -67,0 +131,0 @@ | | - || |
@@ -17,2 +17,127 @@ //----------------------------------------------------- | ||
console.log("+-------------------------+"); | ||
console.log("| Schema"); | ||
console.log("+-------------------------+"); | ||
var schema = { | ||
"name": { | ||
"type": "string", | ||
"rule": "required", | ||
"max": 3, | ||
"trim": true | ||
}, | ||
"status": "?string", | ||
"pts": { | ||
"use": "integer", | ||
"max": 30, | ||
"abs": true | ||
}, | ||
"data": { | ||
"type": "hashTable", | ||
"schema": { | ||
"login": "string", | ||
"password": "string", | ||
"more": { | ||
"type": "hashTable", | ||
"schema": { | ||
"someData": "string" | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
data = {"name": " XX + ", "pts": "-60", "delThisField": "data"}; | ||
$typenize(schema, data); //_ { name: ' XX + ', pts: -60 } | ||
$sanitize(schema, data); //_ { name: 'XX', pts: 30 } | ||
$validate(schema, data); //_ false | ||
console.log(JSON.stringify({ | ||
"T0": $typenize(schema, data), | ||
"T1": $sanitize(schema, data), | ||
"T2": $validate(schema, data) | ||
}, null, "\t")); | ||
console.log("+-------------------------+"); | ||
console.log("| Store"); | ||
console.log("+-------------------------+"); | ||
$typenize.set("myName", {"name": "string"}); | ||
console.log("0#", $typenize.run("myName", {"name": [1,2,3]})); | ||
console.log("1#", $typenize.get("myName")); | ||
$sanitize.set("myName", {"name": "string"}); | ||
console.log("0#", $sanitize.run("myName", {"name": [1,2,3]})); | ||
console.log("1#", $sanitize.get("myName")); | ||
$validate.set("myName", {"name": "string"}); | ||
console.log("0#", $validate.run("myName", {"name": [1,2,3]})); | ||
console.log("1#", $validate.get("myName")); | ||
console.log("+-------------------------+"); | ||
console.log("| T: Schema"); | ||
console.log("+-------------------------+"); | ||
console.log("0#", $typenize("string", 10) + 10); | ||
var schema = { | ||
"name": "?string", | ||
"data": { | ||
"type": "hashTable", | ||
"schema": { | ||
"login": "string", | ||
"password": "string", | ||
"deep": { | ||
"type": "hashTable", | ||
"schema": { | ||
"someData": "string" | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
data = { | ||
"name": "XX"/*, | ||
"data": { | ||
"login": new Date(), | ||
"password": /s+/g, | ||
"deep": { | ||
"someData": [1,2,3] | ||
} | ||
} | ||
*/ | ||
}; | ||
console.log("1#", $typenize(schema, data)); | ||
console.log("+-------------------------+"); | ||
console.log("| S: Custom"); | ||
@@ -96,2 +221,3 @@ console.log("+-------------------------+"); | ||
"status": "?string", | ||
"pts": "integer" | ||
@@ -98,0 +224,0 @@ }, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
64583
1196
299