Sindbad~EG File Manager
"use strict";
var FormatValidators = require("./FormatValidators"),
JsonValidation = require("./JsonValidation"),
Report = require("./Report"),
Utils = require("./Utils");
var SchemaValidators = {
$ref: function (report, schema) {
// http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
// http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
if (typeof schema.$ref !== "string") {
report.addError("KEYWORD_TYPE_EXPECTED", ["$ref", "string"]);
}
},
$schema: function (report, schema) {
// http://json-schema.org/latest/json-schema-core.html#rfc.section.6
if (typeof schema.$schema !== "string") {
report.addError("KEYWORD_TYPE_EXPECTED", ["$schema", "string"]);
}
},
multipleOf: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.1.1
if (typeof schema.multipleOf !== "number") {
report.addError("KEYWORD_TYPE_EXPECTED", ["multipleOf", "number"]);
} else if (schema.multipleOf <= 0) {
report.addError("KEYWORD_MUST_BE", ["multipleOf", "strictly greater than 0"]);
}
},
maximum: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.2.1
if (typeof schema.maximum !== "number") {
report.addError("KEYWORD_TYPE_EXPECTED", ["maximum", "number"]);
}
},
exclusiveMaximum: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.2.1
if (typeof schema.exclusiveMaximum !== "boolean") {
report.addError("KEYWORD_TYPE_EXPECTED", ["exclusiveMaximum", "boolean"]);
} else if (schema.maximum === undefined) {
report.addError("KEYWORD_DEPENDENCY", ["exclusiveMaximum", "maximum"]);
}
},
minimum: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.3.1
if (typeof schema.minimum !== "number") {
report.addError("KEYWORD_TYPE_EXPECTED", ["minimum", "number"]);
}
},
exclusiveMinimum: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.3.1
if (typeof schema.exclusiveMinimum !== "boolean") {
report.addError("KEYWORD_TYPE_EXPECTED", ["exclusiveMinimum", "boolean"]);
} else if (schema.minimum === undefined) {
report.addError("KEYWORD_DEPENDENCY", ["exclusiveMinimum", "minimum"]);
}
},
maxLength: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.1.1
if (Utils.whatIs(schema.maxLength) !== "integer") {
report.addError("KEYWORD_TYPE_EXPECTED", ["maxLength", "integer"]);
} else if (schema.maxLength < 0) {
report.addError("KEYWORD_MUST_BE", ["maxLength", "greater than, or equal to 0"]);
}
},
minLength: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.2.1
if (Utils.whatIs(schema.minLength) !== "integer") {
report.addError("KEYWORD_TYPE_EXPECTED", ["minLength", "integer"]);
} else if (schema.minLength < 0) {
report.addError("KEYWORD_MUST_BE", ["minLength", "greater than, or equal to 0"]);
}
},
pattern: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.3.1
if (typeof schema.pattern !== "string") {
report.addError("KEYWORD_TYPE_EXPECTED", ["pattern", "string"]);
} else {
try {
RegExp(schema.pattern);
} catch (e) {
report.addError("KEYWORD_PATTERN", ["pattern", schema.pattern]);
}
}
},
additionalItems: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.1.1
var type = Utils.whatIs(schema.additionalItems);
if (type !== "boolean" && type !== "object") {
report.addError("KEYWORD_TYPE_EXPECTED", ["additionalItems", ["boolean", "object"]]);
} else if (type === "object") {
report.path.push("additionalItems");
exports.validateSchema.call(this, report, schema.additionalItems);
report.path.pop();
}
},
items: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.1.1
var type = Utils.whatIs(schema.items);
if (type === "object") {
report.path.push("items");
exports.validateSchema.call(this, report, schema.items);
report.path.pop();
} else if (type === "array") {
var idx = schema.items.length;
while (idx--) {
report.path.push("items");
report.path.push(idx.toString());
exports.validateSchema.call(this, report, schema.items[idx]);
report.path.pop();
report.path.pop();
}
} else {
report.addError("KEYWORD_TYPE_EXPECTED", ["items", ["array", "object"]]);
}
// custom - strict mode
if (this.options.forceAdditional === true && schema.additionalItems === undefined && Array.isArray(schema.items)) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["additionalItems"]);
}
// custome - assume defined false mode
if (this.options.assumeAdditional && schema.additionalItems === undefined && Array.isArray(schema.items)) {
schema.additionalItems = false;
}
},
maxItems: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.2.1
if (typeof schema.maxItems !== "number") {
report.addError("KEYWORD_TYPE_EXPECTED", ["maxItems", "integer"]);
} else if (schema.maxItems < 0) {
report.addError("KEYWORD_MUST_BE", ["maxItems", "greater than, or equal to 0"]);
}
},
minItems: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.3.1
if (Utils.whatIs(schema.minItems) !== "integer") {
report.addError("KEYWORD_TYPE_EXPECTED", ["minItems", "integer"]);
} else if (schema.minItems < 0) {
report.addError("KEYWORD_MUST_BE", ["minItems", "greater than, or equal to 0"]);
}
},
uniqueItems: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.4.1
if (typeof schema.uniqueItems !== "boolean") {
report.addError("KEYWORD_TYPE_EXPECTED", ["uniqueItems", "boolean"]);
}
},
maxProperties: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.1.1
if (Utils.whatIs(schema.maxProperties) !== "integer") {
report.addError("KEYWORD_TYPE_EXPECTED", ["maxProperties", "integer"]);
} else if (schema.maxProperties < 0) {
report.addError("KEYWORD_MUST_BE", ["maxProperties", "greater than, or equal to 0"]);
}
},
minProperties: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.2.1
if (Utils.whatIs(schema.minProperties) !== "integer") {
report.addError("KEYWORD_TYPE_EXPECTED", ["minProperties", "integer"]);
} else if (schema.minProperties < 0) {
report.addError("KEYWORD_MUST_BE", ["minProperties", "greater than, or equal to 0"]);
}
},
required: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.3.1
if (Utils.whatIs(schema.required) !== "array") {
report.addError("KEYWORD_TYPE_EXPECTED", ["required", "array"]);
} else if (schema.required.length === 0) {
report.addError("KEYWORD_MUST_BE", ["required", "an array with at least one element"]);
} else {
var idx = schema.required.length;
while (idx--) {
if (typeof schema.required[idx] !== "string") {
report.addError("KEYWORD_VALUE_TYPE", ["required", "string"]);
}
}
if (Utils.isUniqueArray(schema.required) === false) {
report.addError("KEYWORD_MUST_BE", ["required", "an array with unique items"]);
}
}
},
additionalProperties: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
var type = Utils.whatIs(schema.additionalProperties);
if (type !== "boolean" && type !== "object") {
report.addError("KEYWORD_TYPE_EXPECTED", ["additionalProperties", ["boolean", "object"]]);
} else if (type === "object") {
report.path.push("additionalProperties");
exports.validateSchema.call(this, report, schema.additionalProperties);
report.path.pop();
}
},
properties: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
if (Utils.whatIs(schema.properties) !== "object") {
report.addError("KEYWORD_TYPE_EXPECTED", ["properties", "object"]);
return;
}
var keys = Object.keys(schema.properties),
idx = keys.length;
while (idx--) {
var key = keys[idx],
val = schema.properties[key];
report.path.push("properties");
report.path.push(key);
exports.validateSchema.call(this, report, val);
report.path.pop();
report.path.pop();
}
// custom - strict mode
if (this.options.forceAdditional === true && schema.additionalProperties === undefined) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["additionalProperties"]);
}
// custome - assume defined false mode
if (this.options.assumeAdditional && schema.additionalProperties === undefined) {
schema.additionalProperties = false;
}
// custom - forceProperties
if (this.options.forceProperties === true && keys.length === 0) {
report.addError("CUSTOM_MODE_FORCE_PROPERTIES", ["properties"]);
}
},
patternProperties: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
if (Utils.whatIs(schema.patternProperties) !== "object") {
report.addError("KEYWORD_TYPE_EXPECTED", ["patternProperties", "object"]);
return;
}
var keys = Object.keys(schema.patternProperties),
idx = keys.length;
while (idx--) {
var key = keys[idx],
val = schema.patternProperties[key];
try {
RegExp(key);
} catch (e) {
report.addError("KEYWORD_PATTERN", ["patternProperties", key]);
}
report.path.push("patternProperties");
report.path.push(key.toString());
exports.validateSchema.call(this, report, val);
report.path.pop();
report.path.pop();
}
// custom - forceProperties
if (this.options.forceProperties === true && keys.length === 0) {
report.addError("CUSTOM_MODE_FORCE_PROPERTIES", ["patternProperties"]);
}
},
dependencies: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.5.1
if (Utils.whatIs(schema.dependencies) !== "object") {
report.addError("KEYWORD_TYPE_EXPECTED", ["dependencies", "object"]);
} else {
var keys = Object.keys(schema.dependencies),
idx = keys.length;
while (idx--) {
var schemaKey = keys[idx],
schemaDependency = schema.dependencies[schemaKey],
type = Utils.whatIs(schemaDependency);
if (type === "object") {
report.path.push("dependencies");
report.path.push(schemaKey);
exports.validateSchema.call(this, report, schemaDependency);
report.path.pop();
report.path.pop();
} else if (type === "array") {
var idx2 = schemaDependency.length;
if (idx2 === 0) {
report.addError("KEYWORD_MUST_BE", ["dependencies", "not empty array"]);
}
while (idx2--) {
if (typeof schemaDependency[idx2] !== "string") {
report.addError("KEYWORD_VALUE_TYPE", ["dependensices", "string"]);
}
}
if (Utils.isUniqueArray(schemaDependency) === false) {
report.addError("KEYWORD_MUST_BE", ["dependencies", "an array with unique items"]);
}
} else {
report.addError("KEYWORD_VALUE_TYPE", ["dependencies", "object or array"]);
}
}
}
},
enum: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.1.1
if (Array.isArray(schema.enum) === false) {
report.addError("KEYWORD_TYPE_EXPECTED", ["enum", "array"]);
} else if (schema.enum.length === 0) {
report.addError("KEYWORD_MUST_BE", ["enum", "an array with at least one element"]);
} else if (Utils.isUniqueArray(schema.enum) === false) {
report.addError("KEYWORD_MUST_BE", ["enum", "an array with unique elements"]);
}
},
type: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.2.1
var primitiveTypes = ["array", "boolean", "integer", "number", "null", "object", "string"],
primitiveTypeStr = primitiveTypes.join(","),
isArray = Array.isArray(schema.type);
if (isArray) {
var idx = schema.type.length;
while (idx--) {
if (primitiveTypes.indexOf(schema.type[idx]) === -1) {
report.addError("KEYWORD_TYPE_EXPECTED", ["type", primitiveTypeStr]);
}
}
if (Utils.isUniqueArray(schema.type) === false) {
report.addError("KEYWORD_MUST_BE", ["type", "an object with unique properties"]);
}
} else if (typeof schema.type === "string") {
if (primitiveTypes.indexOf(schema.type) === -1) {
report.addError("KEYWORD_TYPE_EXPECTED", ["type", primitiveTypeStr]);
}
} else {
report.addError("KEYWORD_TYPE_EXPECTED", ["type", ["string", "array"]]);
}
if (this.options.noEmptyStrings === true) {
if (schema.type === "string" || isArray && schema.type.indexOf("string") !== -1) {
if (schema.minLength === undefined &&
schema.enum === undefined &&
schema.format === undefined) {
schema.minLength = 1;
}
}
}
if (this.options.noEmptyArrays === true) {
if (schema.type === "array" || isArray && schema.type.indexOf("array") !== -1) {
if (schema.minItems === undefined) {
schema.minItems = 1;
}
}
}
if (this.options.forceProperties === true) {
if (schema.type === "object" || isArray && schema.type.indexOf("object") !== -1) {
if (schema.properties === undefined && schema.patternProperties === undefined) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["properties"]);
}
}
}
if (this.options.forceItems === true) {
if (schema.type === "array" || isArray && schema.type.indexOf("array") !== -1) {
if (schema.items === undefined) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["items"]);
}
}
}
if (this.options.forceMinItems === true) {
if (schema.type === "array" || isArray && schema.type.indexOf("array") !== -1) {
if (schema.minItems === undefined) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["minItems"]);
}
}
}
if (this.options.forceMaxItems === true) {
if (schema.type === "array" || isArray && schema.type.indexOf("array") !== -1) {
if (schema.maxItems === undefined) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["maxItems"]);
}
}
}
if (this.options.forceMinLength === true) {
if (schema.type === "string" || isArray && schema.type.indexOf("string") !== -1) {
if (schema.minLength === undefined &&
schema.format === undefined &&
schema.enum === undefined &&
schema.pattern === undefined) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["minLength"]);
}
}
}
if (this.options.forceMaxLength === true) {
if (schema.type === "string" || isArray && schema.type.indexOf("string") !== -1) {
if (schema.maxLength === undefined &&
schema.format === undefined &&
schema.enum === undefined &&
schema.pattern === undefined) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["maxLength"]);
}
}
}
},
allOf: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.3.1
if (Array.isArray(schema.allOf) === false) {
report.addError("KEYWORD_TYPE_EXPECTED", ["allOf", "array"]);
} else if (schema.allOf.length === 0) {
report.addError("KEYWORD_MUST_BE", ["allOf", "an array with at least one element"]);
} else {
var idx = schema.allOf.length;
while (idx--) {
report.path.push("allOf");
report.path.push(idx.toString());
exports.validateSchema.call(this, report, schema.allOf[idx]);
report.path.pop();
report.path.pop();
}
}
},
anyOf: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.4.1
if (Array.isArray(schema.anyOf) === false) {
report.addError("KEYWORD_TYPE_EXPECTED", ["anyOf", "array"]);
} else if (schema.anyOf.length === 0) {
report.addError("KEYWORD_MUST_BE", ["anyOf", "an array with at least one element"]);
} else {
var idx = schema.anyOf.length;
while (idx--) {
report.path.push("anyOf");
report.path.push(idx.toString());
exports.validateSchema.call(this, report, schema.anyOf[idx]);
report.path.pop();
report.path.pop();
}
}
},
oneOf: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.5.1
if (Array.isArray(schema.oneOf) === false) {
report.addError("KEYWORD_TYPE_EXPECTED", ["oneOf", "array"]);
} else if (schema.oneOf.length === 0) {
report.addError("KEYWORD_MUST_BE", ["oneOf", "an array with at least one element"]);
} else {
var idx = schema.oneOf.length;
while (idx--) {
report.path.push("oneOf");
report.path.push(idx.toString());
exports.validateSchema.call(this, report, schema.oneOf[idx]);
report.path.pop();
report.path.pop();
}
}
},
not: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.6.1
if (Utils.whatIs(schema.not) !== "object") {
report.addError("KEYWORD_TYPE_EXPECTED", ["not", "object"]);
} else {
report.path.push("not");
exports.validateSchema.call(this, report, schema.not);
report.path.pop();
}
},
definitions: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.7.1
if (Utils.whatIs(schema.definitions) !== "object") {
report.addError("KEYWORD_TYPE_EXPECTED", ["definitions", "object"]);
} else {
var keys = Object.keys(schema.definitions),
idx = keys.length;
while (idx--) {
var key = keys[idx],
val = schema.definitions[key];
report.path.push("definitions");
report.path.push(key);
exports.validateSchema.call(this, report, val);
report.path.pop();
report.path.pop();
}
}
},
format: function (report, schema) {
if (typeof schema.format !== "string") {
report.addError("KEYWORD_TYPE_EXPECTED", ["format", "string"]);
} else {
if (FormatValidators[schema.format] === undefined && this.options.ignoreUnknownFormats !== true) {
report.addError("UNKNOWN_FORMAT", [schema.format]);
}
}
},
id: function (report, schema) {
// http://json-schema.org/latest/json-schema-core.html#rfc.section.7.2
if (typeof schema.id !== "string") {
report.addError("KEYWORD_TYPE_EXPECTED", ["id", "string"]);
}
},
title: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1
if (typeof schema.title !== "string") {
report.addError("KEYWORD_TYPE_EXPECTED", ["title", "string"]);
}
},
description: function (report, schema) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1
if (typeof schema.description !== "string") {
report.addError("KEYWORD_TYPE_EXPECTED", ["description", "string"]);
}
},
"default": function (/* report, schema */) {
// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.2
// There are no restrictions placed on the value of this keyword.
}
};
/**
*
* @param {Report} report
* @param {*[]} arr
*
* @returns {boolean}
*/
var validateArrayOfSchemas = function (report, arr) {
var idx = arr.length;
while (idx--) {
exports.validateSchema.call(this, report, arr[idx]);
}
return report.isValid();
};
/**
*
* @param {Report} report
* @param {*} schema
*/
exports.validateSchema = function (report, schema) {
report.commonErrorMessage = "SCHEMA_VALIDATION_FAILED";
// if schema is an array, assume it's an array of schemas
if (Array.isArray(schema)) {
return validateArrayOfSchemas.call(this, report, schema);
}
// do not revalidate schema that has already been validated once
if (schema.__$validated) {
return true;
}
// if $schema is present, this schema should validate against that $schema
var hasParentSchema = schema.$schema && schema.id !== schema.$schema;
if (hasParentSchema) {
if (schema.__$schemaResolved && schema.__$schemaResolved !== schema) {
var subReport = new Report(report);
var valid = JsonValidation.validate.call(this, subReport, schema.__$schemaResolved, schema);
if (valid === false) {
report.addError("PARENT_SCHEMA_VALIDATION_FAILED", null, subReport);
}
} else {
if (this.options.ignoreUnresolvableReferences !== true) {
report.addError("REF_UNRESOLVED", [schema.$schema]);
}
}
}
if (this.options.noTypeless === true) {
// issue #36 - inherit type to anyOf, oneOf, allOf if noTypeless is defined
if (schema.type !== undefined) {
var schemas = [];
if (Array.isArray(schema.anyOf)) { schemas = schemas.concat(schema.anyOf); }
if (Array.isArray(schema.oneOf)) { schemas = schemas.concat(schema.oneOf); }
if (Array.isArray(schema.allOf)) { schemas = schemas.concat(schema.allOf); }
schemas.forEach(function (sch) {
if (!sch.type) { sch.type = schema.type; }
});
}
// end issue #36
if (schema.enum === undefined &&
schema.type === undefined &&
schema.anyOf === undefined &&
schema.oneOf === undefined &&
schema.not === undefined &&
schema.$ref === undefined) {
report.addError("KEYWORD_UNDEFINED_STRICT", ["type"]);
}
}
var keys = Object.keys(schema),
idx = keys.length;
while (idx--) {
var key = keys[idx];
if (key.indexOf("__") === 0) { continue; }
if (SchemaValidators[key] !== undefined) {
SchemaValidators[key].call(this, report, schema);
} else if (!hasParentSchema) {
if (this.options.noExtraKeywords === true) {
report.addError("KEYWORD_UNEXPECTED", [key]);
}
}
}
if (this.options.pedanticCheck === true) {
if (schema.enum) {
// break recursion
var tmpSchema = Utils.clone(schema);
delete tmpSchema.enum;
delete tmpSchema.default;
report.path.push("enum");
idx = schema.enum.length;
while (idx--) {
report.path.push(idx.toString());
JsonValidation.validate.call(this, report, tmpSchema, schema.enum[idx]);
report.path.pop();
}
report.path.pop();
}
if (schema.default) {
report.path.push("default");
JsonValidation.validate.call(this, report, schema, schema.default);
report.path.pop();
}
}
var isValid = report.isValid();
if (isValid) {
schema.__$validated = true;
}
return isValid;
};
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists