# This file is part of bish-bosh. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/raphaelcohn/bish-bosh/master/COPYRIGHT. No part of bish-bosh, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
# Copyright © 2014-2015 The developers of bish-bosh. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/raphaelcohn/bish-bosh/master/COPYRIGHT.


core_dependency_oneOf '*' iconv
core_dependency_oneOf '*' sed
core_dependency_oneOf '*' tr
bishbosh_connection_validate_initialise()
{
	if core_compatibility_whichNoOutput iconv; then
		
		_bishbosh_connection_validate_isUtf8_iconv_iconv()
		{
			iconv -c -s -f utf-8 -t utf-8 1>/dev/null <<-EOF
				$value
			EOF
		}

		_bishbosh_connection_validate_isUtf8_iconv()
		{
			if ! _bishbosh_connection_validate_isUtf8_iconv_iconv; then
				core_exitError $core_commandLine_exitCode_CONFIG "The argument '$argument' is not valid UTF-8"
			fi
		}
	
	# We can use  bsdconv utf-8:utf-8 1>/dev/null, and look for non-zero output on stderr
	
	else
		
		core_message WARN "Disabling UTF-8 validation because 'iconv' isn't available"
		_bishbosh_connection_validate_isUtf8_iconv()
		{
			:
		}
	fi
	
	if core_compatibility_whichNoOutput sed; then

		_bishbosh_connection_validate_topicFilter_sed_sed()
		{
			sed -e 's;/+/;XXX;g' -e 's;^+/;XX;g' -e 's;/+$;XX;g' -e 's;/#$;XX;g' -e 's;#;;g' -e 's;+;;g' <<-EOF
				$value
			EOF
		}

		_bishbosh_connection_validate_topicFilter_sed()
		{
			local strippedOfWildcard="$(_bishbosh_connection_validate_topicFilter_sed_sed)"
			if [ ${#strippedOfWildcard} -ne ${#topicFilter} ]; then
				core_exitError $core_commandLine_exitCode_CONFIG "The argument '$argument' ('$value') contains invalid wildcards"
			fi
		}
		
	else
		
		core_message WARN "Disabling some topic filter validation because 'sed' isn't available"
		_bishbosh_connection_validate_topicFilter_sed()
		{
			:
		}
		
	fi
	
	if core_compatibility_whichNoOutput tr; then
	
		bishbosh_connection_validate_removeCharacters()
		{
			local strip="$1"
			local value="$2"
			printf '%s' "$value" | tr -d "$strip"
		}

		_bishbosh_connection_validate_clientId_restrictedCharacters()
		{
			local stripped="$(printf '%s' "$bishbosh_clientId" | tr -d -c '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')"
			if [ ${#stripped} -ne ${#bishbosh_clientId} ]; then
				core_message WARN "Not all MQTT servers support a ClientId with characters other than 0-9, a-z and A-Z."
			fi
		}
		
	else
		
		core_message WARN "Disabling invalid character validation because 'tr' isn't available"
		bishbosh_connection_validate_removeCharacters()
		{
			local strip="$1"
			local value="$2"
			printf '%s' "$value"
		}
		
		core_message WARN "Disabling Client Id restricted character validation because 'tr' isn't available"
		_bishbosh_connection_validate_clientId_restrictedCharacters()
		{
			:
		}
	fi

	# Only zsh can potentially have NUL in strings
	if core_variable_isSet ZSH_VERSION; then
		
		_bishbosh_connection_validate_isUtf8_asciiNul()
		{
			local strippedOfAsciiNul="$(bishbosh_connection_validate_removeCharacters '\000' "$value")"
			if [ ${#strippedOfAsciiNul} -ne ${#value} ]; then
				core_exitError $core_commandLine_exitCode_CONFIG "The argument '$argument' contains U+0000 (NUL)"
			fi
		}
		
	else
		
		_bishbosh_connection_validate_isUtf8_asciiNul()
		{
			:
		}
	fi
}

bishbosh_connection_validate_fieldLength()
{
	local packetName="$1"
	local variableName="$2"
	
	local core_variable_indirectValue_result
	core_variable_indirectValue "$variableName"
	if [ ${#core_variable_indirectValue_result} -gt 65535 ]; then
		core_exitError $core_commandLine_exitCode_CONFIG "The argument 'bishbosh_connection_write_${packetName}_${variableName}' can not be longer than 65,535 bytes"
	fi
}

bishbosh_connection_validate_isUtf8()
{
	local argument="$1"
	local value="$2"
	
	_bishbosh_connection_validate_isUtf8_iconv
	_bishbosh_connection_validate_isUtf8_asciiNul
}

bishbosh_connection_validate_clientId()
{
	bishbosh_connection_validate_isUtf8 bishbosh_clientId "$bishbosh_clientId"

	if [ ${#bishbosh_clientId} -gt 254 ]; then
		core_exitError $core_commandLine_exitCode_CONFIG "The option -i,--client-id or configuration setting bishbosh_clientId '$bishbosh_clientId' is longer than 254 bytes. ${_program_name} can not support this."
	fi
	
	if [ ${#bishbosh_clientId} -gt 23 ]; then
		core_message WARN "Not all MQTT servers support a ClientId of more than 23 encoded bytes."
	fi
	
	_bishbosh_connection_validate_clientId_restrictedCharacters
}

bishbosh_connection_validate_topicName()
{
	local argument="$1"
	local value="$2"

	if [ ${#value} -eq 0 ]; then
		core_exitError $core_commandLine_exitCode_CONFIG "The argument '$argument' is empty; this is not permitted for topic names"
	fi
	
	_bishbosh_connection_validate_isUtf8_iconv
	
	local strippedOfInvalidCharacters="$(bishbosh_connection_validate_removeCharacters '#*\000' "$value")"
	
	if [ ${#strippedOfInvalidCharacters} -ne ${#value} ]; then
		_bishbosh_connection_validate_isUtf8_asciiNul
		core_exitError $core_commandLine_exitCode_CONFIG "The argument '$argument' ('$value') contains a wildcard ('#' or '+')"
	fi
}

bishbosh_connection_validate_topicFilter()
{
	local argument="$1"
	local index=$2
	local value=$3
	
	argument="$argument' at pair index '$index"
	
	if [ ${#value} -eq 0 ]; then
		core_exitError $core_commandLine_exitCode_CONFIG "The argument '$argument' is empty; this is not permitted for topic filters"
	fi
	
	_bishbosh_connection_validate_isUtf8_iconv
	
	local strippedTopicFilter="$(bishbosh_connection_validate_removeCharacters '\n\000' "$value")"
	if [ ${#strippedTopicFilter} -ne ${#value} ]; then
		_bishbosh_connection_validate_isUtf8_asciiNul
		core_exitError $core_commandLine_exitCode_CONFIG "The argument '$argument' has a topic filter containing \n (LF, Linefeed), which, although allowed in the MQTT 3.1.1 specification can not be supported in portable shell scripts or common tools (outside of those supplied by GNU)"
	fi
	
	_bishbosh_connection_validate_topicFilter_sed
}

bishbosh_connection_validate_publishMessageFieldLength()
{
	local maximumLength=$((268435455-2-topicNameFieldLength))
	if [ $QoS -ne 0 ]; then
		maximumLength=$((maximumLength-2))
	fi
	if [ $messageFieldLength -gt $maximumLength ]; then
		core_exitError $core_commandLine_exitCode_CONFIG "The message can not be longer than $maximumLength bytes when topicName is $topicNameFieldLength bytes and QoS is $QoS."
	fi
}

bishbosh_connection_validate_packetIdentifier()
{
	core_validate_isUnsignedInteger $core_commandLine_exitCode_CONFIG 'argument' "bishbosh_connection_packetIdentifier_forWriting" "$bishbosh_connection_packetIdentifier_forWriting"
	
	if [ $bishbosh_connection_packetIdentifier_forWriting -eq 0 ]; then
		core_exitError $core_commandLine_exitCode_CONFIG "The argument 'bishbosh_connection_packetIdentifier_forWriting' is a packet identifier and so can not be 0"
	fi
	
	if [ $bishbosh_connection_packetIdentifier_forWriting -gt 65535 ]; then
		core_exitError $core_commandLine_exitCode_CONFIG "The argument 'bishbosh_connection_packetIdentifier_forWriting' is a packet identifier and so can not be greater than 65,535"
	fi
}
