mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	* Fix Rewrite/Latch Time
* dependencies can now be specified in the schema
Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
* dependencies can now be specified in the schema
Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
* correct default config
Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
* dependencies part 2
Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
* Update README.md
* build: Update Windows to Qt5.15 (#798)
* Update compile howto
- to qt5.15
- minimal install overhead
- sync with vscode and cmake
* Update docs with more input
gh actions windows: Qt5.15 and msvc2019
* fix: Azure build
* feat: Add Trapezoid to LED Layout (#791)
* Update schema-ledConfig.json
extend schema with corner points (vertcal and horizontal values in percent)
* Update conf_leds.html
input fields for corner points
* Update content_leds.js
add corner values and calculation of led rows
* Update de.json
german title for corners
* CHanges 26.12.2019 Correction and PowerOff add
* GrabberFix PiCam
* VType as QString
* Unused variable deletet
* Missing new paramneters for GrabberFix
* Error json
* JSon error by user
* Crosscompile SutnikElf frok
* Warning unused variable
* Revert "Crosscompile SutnikElf frok"
This reverts commit 443fe80090.
* Fixing a linting error
* Adding Grabber Override Names
* Adding more Grabber Fix translations
* Missed one
* remove V4L2 Grabber Fix and Power Button from Dashboard
Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
* Setting some limits to the trapezoid
Co-authored-by: SputnikElf <58911932+SputnikElf@users.noreply.github.com>
Co-authored-by: SputnikElf <sputnikelf@gmx.de>
Co-authored-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
* add Hue EntertainmentAPI + Forwarder & other Fixes (#592)
* whitespaces + typo fixes
* JS / LGTM fixes
* SSDP Handler crash fix
* MessageForwarder handlePriorityChanges Slave fixes
* use aboutToQuit Signal
* complete rewriten Hue Entertainment API structure
combined Philips Hue and Entertainment API
with new MbedTLS based SSL UDP Provider
* add required cross-compile submodules
* logical rebuild fn: initLeds, setLights + new logs
-more detailed checks and error handling inside iniLeds and setLights
- logical script procedure before ProviderUdpSSL init
- first steps for multiple ProviderUdpSSL usage
- better fallback support to old RestAPI, if entertainment api is not supported
- just 4 u LordGrey: new log fn for cosmetic config outputs ;)
* add OSX CompileHowTo - undo from CrossCompileHowTo
* whitespace fixes
* lightID toString fix
* fix unsigned int E-API + debug output
* bugfixes, reworked black signal detection, wizard:
- change device config field light-ids from int to string -> real unsigned int fix
- add signal detection brightness minimum threshold value
0.0 for 0% brightness - 1.0 for 100% brightness to count for blacklight signal detection
reason: input may not 100% black, like mine - i have a deep dark gray input signal
-> my threshold value is set to 0.005 for 0.5% minimum brightness = 1 (from max 255) to count as black
- wizard optimations, with fallback without entertainment support (beta state)
- whitespace fixes
* cleanup + minor fixes
* change fixed Hue UPD SSL config to _devConfig paras
* Hotfix SSL Connection, new light models, wizard:
- Fix UPD SSL Connection failed Problems
- add new supported gamut C light models: LCG002, LCA001, LCA002, LCA003
- wizard: extend fallback support to classic mode + hints
* whitespace, typo fix
* uncheck useEntertainmentAPI, if noAPISupport detected + hint
* coredump fix -> add _blackLightsTimer nullptr init
* code cleanup / remove old debugs + whitespacefixes
* add gamut C LCP001, LCP002
* SSL UDP config made more flexible + remove qDebug
-> switch to hyerion.ng _log
-> replace logCommand with verbose
-> code cleanups etc...
* extended mbedtls debugging infos
* add adjustable ssl timeout settings
* error handling
* streamdebugger bugfixes
* UPDSSL psk / psk_identity bugfixes! + hue wizard fn typo fix +
- verbose option available without dependencies
- whitespace fixes
* Philips Hue Assistant now recognizes non-original bridges better...
+ Added note if no clientkey is set when using the entertainment API
+ User creation (+ clientkey) for non-original bridges can now also be used
+ Minor changes and bug fixes
* CMAKE mbedTLS  detection
* minor bug fixes + code cleanups
* FindMbedTLS.cmake remove Path-Hints + wizard.js: ajax timeout handling
Test - content_grabber.js: run relevant code only, if V4L2_AVAIL is true:
conf_grabber don't displays other devices, if V4L2 is not available
* compile mbedtls via cmake as static lib
* remove libmbedtls-dev from compileHowto / scripts
* Fix Windows build
* Fix windows build (part 2)
* removed unnecessary osx x11 include directory path
* QTimer Shutdown bugfix
* cmake win32 fix + minor bugfixes
* cmake debug msg used mbedtls libs
* Bugfix: noSignalDetection wasn't switchedOn again
if no signal was previously detected
* Some code fixes based on alerts from lgtm.com
Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com>
* Update devices allowing rewriteTime
* Fix typo
* Add missing "general_btn_saverestart" text to en-file
Co-authored-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com>
Co-authored-by: brindosch <edeltraud70@gmx.de>
Co-authored-by: Ben Williams <desertblade@gmail.com>
Co-authored-by: SputnikElf <58911932+SputnikElf@users.noreply.github.com>
Co-authored-by: SputnikElf <sputnikelf@gmx.de>
Co-authored-by: SJunkies <41368976+SJunkies@users.noreply.github.com>
		
	
		
			
				
	
	
		
			612 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			612 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// stdlib includes
 | 
						|
#include <iterator>
 | 
						|
#include <algorithm>
 | 
						|
#include <math.h>
 | 
						|
 | 
						|
// Utils-Jsonschema includes
 | 
						|
#include <utils/jsonschema/QJsonSchemaChecker.h>
 | 
						|
#include <utils/jsonschema/QJsonUtils.h>
 | 
						|
 | 
						|
QJsonSchemaChecker::QJsonSchemaChecker()
 | 
						|
{
 | 
						|
	// empty
 | 
						|
}
 | 
						|
 | 
						|
QJsonSchemaChecker::~QJsonSchemaChecker()
 | 
						|
{
 | 
						|
	// empty
 | 
						|
}
 | 
						|
 | 
						|
bool QJsonSchemaChecker::setSchema(const QJsonObject & schema)
 | 
						|
{
 | 
						|
	_qSchema = schema;
 | 
						|
 | 
						|
	// TODO: check the schema
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
QPair<bool, bool> QJsonSchemaChecker::validate(const QJsonObject & value, bool ignoreRequired)
 | 
						|
{
 | 
						|
	// initialize state
 | 
						|
	_ignoreRequired = ignoreRequired;
 | 
						|
	_error = false;
 | 
						|
	_schemaError = false;
 | 
						|
	_messages.clear();
 | 
						|
	_currentPath.clear();
 | 
						|
	_currentPath.append("[root]");
 | 
						|
 | 
						|
	// validate
 | 
						|
	validate(value, _qSchema);
 | 
						|
 | 
						|
	return QPair<bool, bool>(!_error, !_schemaError);
 | 
						|
}
 | 
						|
 | 
						|
QJsonObject QJsonSchemaChecker::getAutoCorrectedConfig(const QJsonObject& value, bool ignoreRequired)
 | 
						|
{
 | 
						|
	_ignoreRequired = ignoreRequired;
 | 
						|
	QStringList sequence = QStringList() << "remove" << "modify" << "create";
 | 
						|
	_error = false;
 | 
						|
	_schemaError = false;
 | 
						|
	_messages.clear();
 | 
						|
	_autoCorrected = value;
 | 
						|
 | 
						|
	for(const QString &correct : sequence)
 | 
						|
	{
 | 
						|
		_correct = correct;
 | 
						|
		_currentPath.clear();
 | 
						|
		_currentPath.append("[root]");
 | 
						|
		validate(_autoCorrected, _qSchema);
 | 
						|
	}
 | 
						|
 | 
						|
	return _autoCorrected;
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &schema)
 | 
						|
{
 | 
						|
	// check the current json value
 | 
						|
	for (QJsonObject::const_iterator i = schema.begin(); i != schema.end(); ++i)
 | 
						|
	{
 | 
						|
		QString attribute = i.key();
 | 
						|
		const QJsonValue & attributeValue = *i;
 | 
						|
 | 
						|
		QJsonObject::const_iterator defaultValue = schema.find("default");
 | 
						|
 | 
						|
		if (attribute == "type")
 | 
						|
			checkType(value, attributeValue, (defaultValue != schema.end() ? *defaultValue : QJsonValue::Null));
 | 
						|
		else if (attribute == "properties")
 | 
						|
		{
 | 
						|
			if (value.isObject())
 | 
						|
				checkProperties(value.toObject(), attributeValue.toObject());
 | 
						|
			else
 | 
						|
			{
 | 
						|
				_schemaError = true;
 | 
						|
				setMessage("properties attribute is only valid for objects");
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (attribute == "dependencies")
 | 
						|
		{
 | 
						|
			if (value.isObject())
 | 
						|
				checkDependencies(value.toObject(), attributeValue.toObject());
 | 
						|
			else
 | 
						|
			{
 | 
						|
				_schemaError = true;
 | 
						|
				setMessage("dependencies attribute is only valid for objects");
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (attribute == "additionalProperties")
 | 
						|
		{
 | 
						|
			if (value.isObject())
 | 
						|
			{
 | 
						|
				// ignore the properties which are handled by the properties attribute (if present)
 | 
						|
				QStringList ignoredProperties;
 | 
						|
				if (schema.contains("properties")) {
 | 
						|
					const QJsonObject & props = schema["properties"].toObject();
 | 
						|
					ignoredProperties = props.keys();
 | 
						|
				}
 | 
						|
 | 
						|
				checkAdditionalProperties(value.toObject(), attributeValue, ignoredProperties);
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				_schemaError = true;
 | 
						|
				setMessage("additional properties attribute is only valid for objects");
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (attribute == "minimum")
 | 
						|
			checkMinimum(value, attributeValue, (defaultValue != schema.end() ? *defaultValue : QJsonValue::Null));
 | 
						|
		else if (attribute == "maximum")
 | 
						|
			checkMaximum(value, attributeValue, (defaultValue != schema.end() ? *defaultValue : QJsonValue::Null));
 | 
						|
		else if (attribute == "minLength")
 | 
						|
			checkMinLength(value, attributeValue, (defaultValue != schema.end() ? *defaultValue : QJsonValue::Null));
 | 
						|
		else if (attribute == "maxLength")
 | 
						|
			checkMaxLength(value, attributeValue, (defaultValue != schema.end() ? *defaultValue : QJsonValue::Null));
 | 
						|
		else if (attribute == "items")
 | 
						|
		{
 | 
						|
			if (value.isArray())
 | 
						|
				checkItems(value, attributeValue.toObject());
 | 
						|
			else
 | 
						|
			{
 | 
						|
				_error = true;
 | 
						|
				setMessage("items only valid for arrays");
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (attribute == "minItems")
 | 
						|
			checkMinItems(value, attributeValue, (defaultValue != schema.end() ? *defaultValue : QJsonValue::Null));
 | 
						|
		else if (attribute == "maxItems")
 | 
						|
			checkMaxItems(value, attributeValue, (defaultValue != schema.end() ? *defaultValue : QJsonValue::Null));
 | 
						|
		else if (attribute == "uniqueItems")
 | 
						|
			checkUniqueItems(value, attributeValue);
 | 
						|
		else if (attribute == "enum")
 | 
						|
			checkEnum(value, attributeValue, (defaultValue != schema.end() ? *defaultValue : QJsonValue::Null));
 | 
						|
 		else if (attribute == "required")
 | 
						|
 			; // nothing to do. value is present so always oke
 | 
						|
 		else if (attribute == "id")
 | 
						|
 			; // references have already been collected
 | 
						|
 		else if (attribute == "title" || attribute == "description"  || attribute == "default" || attribute == "format"
 | 
						|
			|| attribute == "defaultProperties" || attribute == "propertyOrder" || attribute == "append" || attribute == "step"
 | 
						|
			|| attribute == "access" || attribute == "options" || attribute == "script" || attribute == "allowEmptyArray" || attribute == "comment")
 | 
						|
 			; // nothing to do.
 | 
						|
		else
 | 
						|
		{
 | 
						|
			// no check function defined for this attribute
 | 
						|
			_schemaError = true;
 | 
						|
			setMessage("No check function defined for attribute " + attribute);
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::setMessage(const QString & message)
 | 
						|
{
 | 
						|
	_messages.append(_currentPath.join("") +": "+message);
 | 
						|
}
 | 
						|
 | 
						|
const QStringList & QJsonSchemaChecker::getMessages() const
 | 
						|
{
 | 
						|
	return _messages;
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkType(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
 | 
						|
{
 | 
						|
	QString type = schema.toString();
 | 
						|
 | 
						|
	bool wrongType = false;
 | 
						|
	if (type == "string")
 | 
						|
		wrongType = !value.isString();
 | 
						|
	else if (type == "number")
 | 
						|
		wrongType = !value.isDouble();
 | 
						|
	else if (type == "integer")
 | 
						|
	{
 | 
						|
		if (value.isDouble()) //check if value type not boolean (true = 1 && false = 0)
 | 
						|
			wrongType = (rint(value.toDouble()) != value.toDouble());
 | 
						|
		else
 | 
						|
			wrongType = true;
 | 
						|
	}
 | 
						|
	else if (type == "double")
 | 
						|
		wrongType = !value.isDouble();
 | 
						|
	else if (type == "boolean")
 | 
						|
		wrongType = !value.isBool();
 | 
						|
	else if (type == "object")
 | 
						|
		wrongType = !value.isObject();
 | 
						|
	else if (type == "array")
 | 
						|
		wrongType = !value.isArray();
 | 
						|
	else if (type == "null")
 | 
						|
		wrongType = !value.isNull();
 | 
						|
	else if (type == "enum")
 | 
						|
		wrongType = !value.isString();
 | 
						|
	else if (type == "any")
 | 
						|
		wrongType = false;
 | 
						|
 | 
						|
	if (wrongType)
 | 
						|
	{
 | 
						|
		_error = true;
 | 
						|
 | 
						|
		if (_correct == "modify")
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue);
 | 
						|
 | 
						|
 | 
						|
		if (_correct == "")
 | 
						|
			setMessage(type + " expected");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkProperties(const QJsonObject & value, const QJsonObject & schema)
 | 
						|
{
 | 
						|
	for (QJsonObject::const_iterator i = schema.begin(); i != schema.end(); ++i)
 | 
						|
	{
 | 
						|
		QString property = i.key();
 | 
						|
 | 
						|
		const QJsonValue  & propertyValue = *i;
 | 
						|
 | 
						|
		_currentPath.append("." + property);
 | 
						|
		QJsonObject::const_iterator required = propertyValue.toObject().find("required");
 | 
						|
 | 
						|
		if (value.contains(property))
 | 
						|
		{
 | 
						|
			validate(value[property], propertyValue.toObject());
 | 
						|
		}
 | 
						|
		else if (required != propertyValue.toObject().end() && propertyValue.toObject().find("required").value().toBool() && !_ignoreRequired)
 | 
						|
		{
 | 
						|
			_error = true;
 | 
						|
 | 
						|
			if (_correct == "create")
 | 
						|
			{
 | 
						|
				QJsonUtils::modify(_autoCorrected, _currentPath,  QJsonUtils::create(propertyValue, _ignoreRequired), property);
 | 
						|
				setMessage("Create property: "+property+" with value: "+QJsonUtils::getDefaultValue(propertyValue));
 | 
						|
			}
 | 
						|
 | 
						|
			if (_correct == "")
 | 
						|
				setMessage("missing member");
 | 
						|
		}
 | 
						|
		else if (_correct == "create" && _ignoreRequired)
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath,  QJsonUtils::create(propertyValue, _ignoreRequired), property);
 | 
						|
 | 
						|
		_currentPath.removeLast();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkDependencies(const QJsonObject & value, const QJsonObject & schema)
 | 
						|
{
 | 
						|
	for (QJsonObject::const_iterator i = schema.begin(); i != schema.end(); ++i)
 | 
						|
	{
 | 
						|
		QString property = i.key();
 | 
						|
		const QJsonValue & propertyValue = *i;
 | 
						|
 | 
						|
		if (propertyValue.toObject().contains("properties"))
 | 
						|
		{
 | 
						|
			_currentPath.append("." + property);
 | 
						|
 | 
						|
			const QJsonObject & dependencies = propertyValue.toObject()["properties"].toObject();
 | 
						|
 | 
						|
			bool valid = false;
 | 
						|
			for (QJsonObject::const_iterator d = dependencies.begin(); d != dependencies.end(); ++d)
 | 
						|
			{
 | 
						|
				QString dependency = d.key();
 | 
						|
				const QJsonValue & dependencyValue = *d;
 | 
						|
 | 
						|
				if (dependencyValue.toObject()["enum"].isArray())
 | 
						|
				{
 | 
						|
					QJsonArray jArray = dependencyValue.toObject()["enum"].toArray();
 | 
						|
					for(int a = 0; a < jArray.size(); ++a)
 | 
						|
					{
 | 
						|
						if (value[dependency] == jArray[a])
 | 
						|
						{
 | 
						|
							valid = true;
 | 
						|
							break;
 | 
						|
						}
 | 
						|
						else
 | 
						|
							valid = false;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				else
 | 
						|
					valid = (value[dependency] == dependencyValue.toObject()["enum"]);
 | 
						|
			}
 | 
						|
 | 
						|
			if (value.contains(property) && !valid)
 | 
						|
			{
 | 
						|
				_error = true;
 | 
						|
 | 
						|
				if (_correct == "remove")
 | 
						|
				{
 | 
						|
					QJsonUtils::modify(_autoCorrected, _currentPath);
 | 
						|
					setMessage("Removed property: "+property);
 | 
						|
				}
 | 
						|
 | 
						|
				if (_correct == "")
 | 
						|
					setMessage("Property not required");
 | 
						|
			}
 | 
						|
 | 
						|
			_currentPath.removeLast();
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkAdditionalProperties(const QJsonObject & value, const QJsonValue & schema, const QStringList & ignoredProperties)
 | 
						|
{
 | 
						|
	for (QJsonObject::const_iterator i = value.begin(); i != value.end(); ++i)
 | 
						|
	{
 | 
						|
		QString property = i.key();
 | 
						|
		if (std::find(ignoredProperties.begin(), ignoredProperties.end(), property) == ignoredProperties.end())
 | 
						|
		{
 | 
						|
			// property has no property definition. check against the definition for additional properties
 | 
						|
			_currentPath.append("." + property);
 | 
						|
			if (schema.isBool())
 | 
						|
			{
 | 
						|
				if (schema.toBool() == false)
 | 
						|
				{
 | 
						|
					_error = true;
 | 
						|
 | 
						|
					if (_correct == "remove")
 | 
						|
					{
 | 
						|
						QJsonUtils::modify(_autoCorrected, _currentPath);
 | 
						|
						setMessage("Removed property: "+property);
 | 
						|
					}
 | 
						|
 | 
						|
					if (_correct == "")
 | 
						|
						setMessage("no schema definition");
 | 
						|
				}
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				validate(value[property].toObject(), schema.toObject());
 | 
						|
			}
 | 
						|
			_currentPath.removeLast();
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkMinimum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
 | 
						|
{
 | 
						|
	if (!value.isDouble())
 | 
						|
	{
 | 
						|
		// only for numeric
 | 
						|
		_error = true;
 | 
						|
		setMessage("minimum check only for numeric fields");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if (value.toDouble() < schema.toDouble())
 | 
						|
	{
 | 
						|
		_error = true;
 | 
						|
 | 
						|
		if (_correct == "modify")
 | 
						|
		{
 | 
						|
			(defaultValue != QJsonValue::Null) ?
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, schema);
 | 
						|
			setMessage("Correct too small value: "+QString::number(value.toDouble())+" to: "+QString::number(defaultValue.toDouble()));
 | 
						|
		}
 | 
						|
 | 
						|
		if (_correct == "")
 | 
						|
			setMessage("value is too small (minimum=" + QString::number(schema.toDouble()) + ")");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkMaximum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
 | 
						|
{
 | 
						|
	if (!value.isDouble())
 | 
						|
	{
 | 
						|
		// only for numeric
 | 
						|
		_error = true;
 | 
						|
		setMessage("maximum check only for numeric fields");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if (value.toDouble() > schema.toDouble())
 | 
						|
	{
 | 
						|
		_error = true;
 | 
						|
 | 
						|
		if (_correct == "modify")
 | 
						|
		{
 | 
						|
			(defaultValue != QJsonValue::Null) ?
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, schema);
 | 
						|
			setMessage("Correct too large value: "+QString::number(value.toDouble())+" to: "+QString::number(defaultValue.toDouble()));
 | 
						|
		}
 | 
						|
 | 
						|
		if (_correct == "")
 | 
						|
			setMessage("value is too large (maximum=" + QString::number(schema.toDouble()) + ")");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkMinLength(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
 | 
						|
{
 | 
						|
	if (!value.isString())
 | 
						|
	{
 | 
						|
		// only for Strings
 | 
						|
		_error = true;
 | 
						|
		setMessage("minLength check only for string fields");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if (value.toString().size() < schema.toInt())
 | 
						|
	{
 | 
						|
		_error = true;
 | 
						|
 | 
						|
		if (_correct == "modify")
 | 
						|
		{
 | 
						|
			(defaultValue != QJsonValue::Null) ?
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, schema);
 | 
						|
			setMessage("Correct too short value: "+value.toString()+" to: "+defaultValue.toString());
 | 
						|
		}
 | 
						|
		if (_correct == "")
 | 
						|
			setMessage("value is too short (minLength=" + QString::number(schema.toInt()) + ")");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkMaxLength(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
 | 
						|
{
 | 
						|
	if (!value.isString())
 | 
						|
	{
 | 
						|
		// only for Strings
 | 
						|
		_error = true;
 | 
						|
		setMessage("maxLength check only for string fields");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if (value.toString().size() > schema.toInt())
 | 
						|
	{
 | 
						|
		_error = true;
 | 
						|
 | 
						|
		if (_correct == "modify")
 | 
						|
		{
 | 
						|
			(defaultValue != QJsonValue::Null) ?
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, schema);
 | 
						|
			setMessage("Correct too long value: "+value.toString()+" to: "+defaultValue.toString());
 | 
						|
		}
 | 
						|
		if (_correct == "")
 | 
						|
			setMessage("value is too long (maxLength=" + QString::number(schema.toInt()) + ")");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkItems(const QJsonValue & value, const QJsonObject & schema)
 | 
						|
{
 | 
						|
	if (!value.isArray())
 | 
						|
	{
 | 
						|
		// only for arrays
 | 
						|
		_error = true;
 | 
						|
		setMessage("items only valid for arrays");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	QJsonArray jArray = value.toArray();
 | 
						|
 | 
						|
	if (_correct == "remove")
 | 
						|
		if (jArray.isEmpty() && !schema.contains("allowEmptyArray"))
 | 
						|
		{
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath);
 | 
						|
			setMessage("Remove empty array");
 | 
						|
		}
 | 
						|
 | 
						|
	for(int i = 0; i < jArray.size(); ++i)
 | 
						|
	{
 | 
						|
		// validate each item
 | 
						|
		_currentPath.append("[" + QString::number(i) + "]");
 | 
						|
		validate(jArray[i], schema);
 | 
						|
		_currentPath.removeLast();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkMinItems(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
 | 
						|
{
 | 
						|
	if (!value.isArray())
 | 
						|
	{
 | 
						|
		// only for arrays
 | 
						|
		_error = true;
 | 
						|
		setMessage("minItems only valid for arrays");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	QJsonArray jArray = value.toArray();
 | 
						|
	if (jArray.size() < schema.toInt())
 | 
						|
	{
 | 
						|
		_error = true;
 | 
						|
 | 
						|
		if (_correct == "modify")
 | 
						|
		{
 | 
						|
			(defaultValue != QJsonValue::Null) ?
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, schema);
 | 
						|
			setMessage("Correct minItems: "+QString::number(jArray.size())+" to: "+QString::number(defaultValue.toArray().size()));
 | 
						|
		}
 | 
						|
 | 
						|
		if (_correct == "")
 | 
						|
			setMessage("array is too small (minimum=" + QString::number(schema.toInt()) + ")");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkMaxItems(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
 | 
						|
{
 | 
						|
	if (!value.isArray())
 | 
						|
	{
 | 
						|
		// only for arrays
 | 
						|
		_error = true;
 | 
						|
		setMessage("maxItems only valid for arrays");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	QJsonArray jArray = value.toArray();
 | 
						|
	if (jArray.size() > schema.toInt())
 | 
						|
	{
 | 
						|
		_error = true;
 | 
						|
 | 
						|
		if (_correct == "modify")
 | 
						|
		{
 | 
						|
			(defaultValue != QJsonValue::Null) ?
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, schema);
 | 
						|
			setMessage("Correct maxItems: "+QString::number(jArray.size())+" to: "+QString::number(defaultValue.toArray().size()));
 | 
						|
		}
 | 
						|
 | 
						|
		if (_correct == "")
 | 
						|
			setMessage("array is too large (maximum=" + QString::number(schema.toInt()) + ")");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkUniqueItems(const QJsonValue & value, const QJsonValue & schema)
 | 
						|
{
 | 
						|
	if (!value.isArray())
 | 
						|
	{
 | 
						|
		// only for arrays
 | 
						|
		_error = true;
 | 
						|
		setMessage("uniqueItems only valid for arrays");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if (schema.toBool() == true)
 | 
						|
	{
 | 
						|
		// make sure no two items are identical
 | 
						|
 | 
						|
		bool removeDuplicates = false;
 | 
						|
 | 
						|
		QJsonArray jArray = value.toArray();
 | 
						|
		for(int i = 0; i < jArray.size(); ++i)
 | 
						|
		{
 | 
						|
			for (int j = i+1; j < jArray.size(); ++j)
 | 
						|
			{
 | 
						|
				if (jArray[i] == jArray[j])
 | 
						|
				{
 | 
						|
					// found a value twice
 | 
						|
					_error = true;
 | 
						|
					removeDuplicates = true;
 | 
						|
 | 
						|
					if (_correct == "")
 | 
						|
						setMessage("array must have unique values");
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if (removeDuplicates && _correct == "modify")
 | 
						|
		{
 | 
						|
			QJsonArray uniqueItemsArray;
 | 
						|
 | 
						|
			for(int i = 0; i < jArray.size(); ++i)
 | 
						|
				if (!uniqueItemsArray.contains(jArray[i]))
 | 
						|
					uniqueItemsArray.append(jArray[i]);
 | 
						|
 | 
						|
			QJsonUtils::modify(_autoCorrected, _currentPath, uniqueItemsArray);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void QJsonSchemaChecker::checkEnum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
 | 
						|
{
 | 
						|
	if (schema.isArray())
 | 
						|
	{
 | 
						|
		QJsonArray jArray = schema.toArray();
 | 
						|
		for(int i = 0; i < jArray.size(); ++i)
 | 
						|
		{
 | 
						|
			if (jArray[i] == value)
 | 
						|
			{
 | 
						|
				// found enum value. done.
 | 
						|
				return;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// nothing found
 | 
						|
	_error = true;
 | 
						|
 | 
						|
	if (_correct == "modify")
 | 
						|
	{
 | 
						|
		(defaultValue != QJsonValue::Null) ?
 | 
						|
		QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
 | 
						|
		QJsonUtils::modify(_autoCorrected, _currentPath, schema.toArray().first());
 | 
						|
		setMessage("Correct unknown enum value: "+value.toString()+" to: "+defaultValue.toString());
 | 
						|
	}
 | 
						|
 | 
						|
	if (_correct == "")
 | 
						|
	{
 | 
						|
		QJsonDocument doc(schema.toArray());
 | 
						|
		QString strJson(doc.toJson(QJsonDocument::Compact));
 | 
						|
		setMessage("Unknown enum value (allowed values are: " + strJson+ ")");
 | 
						|
	}
 | 
						|
}
 |