diff -r 000000000000 -r c8830336c852 eapol/eapol_framework/eapol_common/am/common/eap_file_config.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eapol/eapol_framework/eapol_common/am/common/eap_file_config.cpp Thu Dec 17 08:47:43 2009 +0200 @@ -0,0 +1,2229 @@ +/* +* Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: EAP and WLAN authentication protocols. +* +*/ + + +// This is enumeration of EAPOL source code. +#if defined(USE_EAP_MINIMUM_RELEASE_TRACES) + #undef EAP_FILE_NUMBER_ENUM + #define EAP_FILE_NUMBER_ENUM 14 + #undef EAP_FILE_NUMBER_DATE + #define EAP_FILE_NUMBER_DATE 1127594498 +#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES) + + +#include "eap_am_memory.h" +#include "eap_file_config.h" +#include "eap_automatic_variable.h" + +#if defined(_WIN32) && !defined(__GNUC__) + #pragma warning( disable : 4355 ) // 'this' : used in base member initializer list +#endif + + +#if 0 + const u32_t TRACE_FLAGS_CONFIGURE_DATA = TRACE_FLAGS_DEFAULT; +#else + const u32_t TRACE_FLAGS_CONFIGURE_DATA = eap_am_tools_c::eap_trace_mask_none; +#endif + +//----------------------------------------------------------------- +//----------------------------------------------------------------- +//----------------------------------------------------------------- + +eap_config_value_c::~eap_config_value_c() +{ + delete m_subsection_map; + m_subsection_map = 0; +} + +eap_config_value_c::eap_config_value_c( + abs_eap_am_tools_c* const tools) + : m_am_tools(tools) + , m_subsection_map(0) + , m_data(tools) + , m_type(eap_configure_type_none) + , m_is_valid(false) +{ + if (m_data.get_is_valid() == false) + { + return; + } + + m_is_valid = true; +} + +void eap_config_value_c::set_subsection( + eap_core_map_c * const subsection_map) +{ + m_subsection_map = subsection_map; +} + +eap_core_map_c * eap_config_value_c::get_subsection() +{ + return m_subsection_map; +} + +eap_variable_data_c * eap_config_value_c::get_data() +{ + return &m_data; +} + +void eap_config_value_c::set_type(const eap_configure_type_e type) +{ + m_type = type; +} + +eap_configure_type_e eap_config_value_c::get_type() +{ + return m_type; +} + +void eap_config_value_c::object_increase_reference_count() +{ +} + +bool eap_config_value_c::get_is_valid() +{ + return m_is_valid; +} + +//----------------------------------------------------------------- +//----------------------------------------------------------------- +//----------------------------------------------------------------- + + +EAP_FUNC_EXPORT eap_file_config_c::eap_file_config_c( + abs_eap_am_tools_c* const tools) +: m_am_tools(tools) +, m_config_map(tools, this) +, m_is_valid(false) +{ + EAP_UNREFERENCED_PARAMETER(TRACE_FLAGS_CONFIGURE_DATA); // in release + + set_is_valid(); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_file_config_c::~eap_file_config_c() +{ +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::configure( + abs_eap_am_file_input_c * const file) +{ + eap_status_e status = read_subsections(file, &m_config_map); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::expand_environment_variables( + eap_core_map_c * const config_map, + const eap_variable_data_c * const original_value, + eap_variable_data_c * const expanded_value + ) +{ + eap_status_e status = eap_status_process_general_error; + + if (original_value == 0 + || expanded_value == 0 + ) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + const u8_t env_char = '$'; + const u8_t char_left_parenthesis = '('; + const u8_t char_right_parenthesis = ')'; + + eap_variable_data_c tmp_value_buffer(m_am_tools); + if (tmp_value_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = tmp_value_buffer.set_buffer_length(MAX_LINE_LENGTH); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + bool expanded_value_when_true = false; + + status = expanded_value->set_copy_of_buffer(original_value); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + + for (;;) + { + u8_t * const start_of_value = expanded_value->get_data(expanded_value->get_data_length()); + + u8_t * const env_start = static_cast(m_am_tools->memchr( + start_of_value, + env_char, + expanded_value->get_data_length())); + + if (env_start == 0) + { + status = eap_status_ok; + break; + } + else + { + if (static_cast((env_start+2)-start_of_value) < expanded_value->get_data_length() + && env_start[1] == char_left_parenthesis) + { + u8_t *tmp_end = start_of_value + expanded_value->get_data_length(); + + u8_t *env_end = static_cast(m_am_tools->memchr( + env_start, + char_right_parenthesis, + tmp_end-env_start)); + if (env_end != 0) + { + *env_end = '\0'; + + u8_t *env_name = env_start+2; + + eap_variable_data_c env_name_buffer(m_am_tools); + if (env_name_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = env_name_buffer.set_buffer( + env_name, + env_end-env_name, + false, + false); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + eap_variable_data_c env_value_buffer(m_am_tools); + if (env_value_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_status_e env_status = m_am_tools->getenv( + &env_name_buffer, + &env_value_buffer); + + eap_variable_data_c parsed_value_buffer(m_am_tools); + if (parsed_value_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = parsed_value_buffer.set_buffer_length(MAX_LINE_LENGTH); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + parsed_value_buffer.set_data_length(MAX_LINE_LENGTH); + + eap_variable_data_c configure_option(m_am_tools); + if (configure_option.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + if (env_status != eap_status_ok) + { + // Next check whether a one of the defined configuration + // options match to the variable. + eap_configure_type_e configuration_data_type = eap_configure_type_none; + static const u32_t EAP_MAX_CONFIG_BUFFER_LENGTH = 256; + eap_configuration_field_template_c * const tmp_env_name + = new eap_configuration_field_template_c; + + eap_automatic_variable_c > + automatic_tmp_env_name(m_am_tools, tmp_env_name); + + if (tmp_env_name == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_status_e status = tmp_env_name->set_fields( + m_am_tools, + env_name, + eap_configure_type_none, + false); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = read_configure( + config_map, + tmp_env_name->get_field(), + &configure_option, + &configuration_data_type, + false); + + if (status == eap_status_ok) + { + if (configuration_data_type == eap_configure_type_string) + { + status = configure_option.add_end_null(); + } + else if (configuration_data_type == eap_configure_type_u32_t) + { + u32_t * const p_value = reinterpret_cast( + configure_option.get_data( + configure_option.get_data_length())); + if (p_value != 0) + { + u32_t value = *p_value; + + status = configure_option.set_buffer_length(EAP_MAX_CONFIG_BUFFER_LENGTH); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = configure_option.set_data_length(EAP_MAX_CONFIG_BUFFER_LENGTH); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + u32_t length = m_am_tools->snprintf( + reinterpret_cast( + configure_option.get_data( + configure_option.get_data_length())), + EAP_MAX_CONFIG_BUFFER_LENGTH, + EAPL("%u"), + value); + status = configure_option.set_data_length(length); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = configure_option.add_end_null(); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + } + else if (configuration_data_type == eap_configure_type_boolean) + { + u32_t * const p_value = reinterpret_cast( + configure_option.get_data( + configure_option.get_data_length())); + if (p_value != 0) + { + bool value = (*p_value == 0) ? false : true; + + status = configure_option.set_buffer_length(EAP_MAX_CONFIG_BUFFER_LENGTH); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = configure_option.set_data_length(EAP_MAX_CONFIG_BUFFER_LENGTH); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + if (value == true) + { + u32_t length = m_am_tools->snprintf( + reinterpret_cast( + configure_option.get_data( + configure_option.get_data_length())), + EAP_MAX_CONFIG_BUFFER_LENGTH, + EAPL("true")); + status = configure_option.set_data_length(length); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + else + { + u32_t length = m_am_tools->snprintf( + reinterpret_cast( + configure_option.get_data( + configure_option.get_data_length())), + EAP_MAX_CONFIG_BUFFER_LENGTH, + EAPL("false")); + configure_option.set_data_length(length); + } + + status = configure_option.add_end_null(); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + } + else if (configuration_data_type == eap_configure_type_hex_data) + { + u8_t * const p_value = reinterpret_cast( + configure_option.get_data( + configure_option.get_data_length())); + + u8_t buffer[3]; + u8_t comma(','); + + eap_variable_data_c tmp(m_am_tools); + if (tmp.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + for (u32_t ind = 0ul; ind < configure_option.get_data_length(); ind++) + { + u32_t length = m_am_tools->snprintf( + buffer, + sizeof(buffer), + EAPL("%02x"), + p_value[ind]); + + status = tmp.add_data(buffer, length); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + if ((ind+1) < configure_option.get_data_length()) + { + status = tmp.add_data(&comma, sizeof(comma)); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + } // for() + + status = configure_option.set_copy_of_buffer(&tmp); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = configure_option.add_end_null(); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + } + + if (configure_option.get_is_valid_data() == false + || configure_option.get_data_length() == 0ul) + { + #if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("WARNING: CONFIG: unknown environment variable %s.\n", + env_name); + #endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("WARNING: CONFIG: unknown environment variable %s.\n"), + env_name)); + + // This is empty environment value. + } + } + else + { + // OK environment variable found. + eap_configure_type_e type = eap_configure_type_none; + + status = cnf_parse_value( + &env_value_buffer, + &env_name_buffer, + &type, + &configure_option, + true + ); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + + + if (configure_option.get_is_valid_data() == true + && configure_option.get_data_length() > 0ul) + { + tmp_value_buffer.reset(); + + u32_t tmp_index = 0ul; + + if (env_start > start_of_value) + { + u32_t length_of_begin = env_start-start_of_value; + if (length_of_begin > 0ul) + { + status = tmp_value_buffer.set_copy_of_buffer( + expanded_value->get_data(length_of_begin), + length_of_begin); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + tmp_index += length_of_begin; + } + } + + if (configure_option.get_data_length() > 0ul) + { + status = tmp_value_buffer.add_data(&configure_option); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + tmp_index += configure_option.get_data_length(); + } + + if (tmp_end > (env_end+1)) + { + u32_t length_of_end = tmp_end-(env_end+1); + if (length_of_end > 0ul) + { + status = tmp_value_buffer.add_data( + (env_end+1), + length_of_end); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + tmp_index += length_of_end; + } + } + + if (tmp_value_buffer.get_is_valid_data() == true + && tmp_value_buffer.get_data_length() > 0ul) + { + status = expanded_value->set_copy_of_buffer(&tmp_value_buffer); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = expanded_value->add_end_null(); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + expanded_value_when_true = true; + } + + } + } + else + { + #if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("ERROR: CONFIG: illegal configure value %s.\n", + expanded_value->get_data(expanded_value->get_data_length())); + #endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("ERROR: CONFIG: illegal configure value %s.\n"), + expanded_value->get_data(expanded_value->get_data_length()))); + status = eap_status_illegal_configure_field; + break; + } + } + else + { + #if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("ERROR: CONFIG: illegal configure value %s.\n", + expanded_value->get_data(expanded_value->get_data_length())); + #endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("ERROR: CONFIG: illegal configure value %s.\n"), + expanded_value->get_data(expanded_value->get_data_length()))); + status = eap_status_illegal_configure_field; + break; + } + } + } // for() + + if (status == eap_status_ok + && expanded_value_when_true == true) + { + #if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("CONFIG: expanded configuration value [%s] => [%s].\n", + value, + expanded_value); + #endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: expanded configuration value [%s] => [%s].\n"), + original_value->get_data(original_value->get_data_length()), + expanded_value->get_data(expanded_value->get_data_length()))); + } + + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT u8_t * eap_file_config_c::read_hex_byte( + u8_t * cursor, + const u8_t * const end, + u8_t * const hex_byte) +{ + u8_t * start = cursor; + bool stop = false; + + while(stop == false && cursor < end) + { + switch(*cursor) + { + case static_cast(','): + case static_cast(' '): + case static_cast('\t'): + stop = true; + break; + default: + ++cursor; + break; + } + + } + + if (cursor <= end) + { + u32_t target_length = sizeof(*hex_byte); + + eap_status_e status = m_am_tools->convert_hex_ascii_to_bytes( + start, + cursor-start, + hex_byte, + &target_length); + if (status != eap_status_ok) + { + return 0; + } + + return ++cursor; + } + + return 0; +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT u8_t * eap_file_config_c::read_u32_t( + u8_t * cursor, + const u8_t * const end, + u32_t * const integer) +{ + u8_t * start = cursor; + bool stop = false; + + while(stop == false && cursor < end) + { + switch(*cursor) + { + case static_cast(','): + case static_cast(' '): + case static_cast('\t'): + stop = true; + break; + default: + ++cursor; + break; + } + + } + + if (cursor <= end) + { + eap_variable_data_c buffer(m_am_tools); + if (buffer.get_is_valid() == false) + { + (void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + return 0; + } + + eap_status_e status = buffer.add_data(start, cursor-start); + if (status != eap_status_ok) + { + (void) EAP_STATUS_RETURN(m_am_tools, status); + return 0; + } + + status = m_am_tools->number_string_to_u32( + buffer.get_data(buffer.get_data_length()), + buffer.get_data_length(), + integer); + if (status != eap_status_ok) + { + (void) EAP_STATUS_RETURN(m_am_tools, status); + return 0; + } + + return ++cursor; + } + + (void) EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload); + return 0; +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::convert_value( + eap_core_map_c * const config_map, + const eap_variable_data_c * const value_buffer, + const eap_configure_type_e type, + eap_variable_data_c * const value_data) +{ + eap_status_e status = eap_status_process_general_error; + + eap_variable_data_c expanded_value_buffer(m_am_tools); + if (expanded_value_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = expanded_value_buffer.set_buffer_length(MAX_LINE_LENGTH); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + expanded_value_buffer.set_data_length(MAX_LINE_LENGTH); + + status = expand_environment_variables( + config_map, + value_buffer, + &expanded_value_buffer); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + if (type == eap_configure_type_u32_t) + { + u32_t uint_value = 0UL; + + status = m_am_tools->number_string_to_u32( + expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()), + expanded_value_buffer.get_data_length(), + &uint_value); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = value_data->set_copy_of_buffer( + &uint_value, + sizeof(uint_value)); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + else if (type == eap_configure_type_boolean) + { + u32_t uint_value = static_cast(~0); + + if (!m_am_tools->memcmp( + expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()), + EAP_FILECONFIG_TRUE, + expanded_value_buffer.get_data_length())) + { + // OK, true + uint_value = 1u; + } + else if (!m_am_tools->memcmp( + expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()), + EAP_FILECONFIG_FALSE, + expanded_value_buffer.get_data_length())) + { + // OK, false + uint_value = 0u; + } + else + { +#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("ERROR: CONFIG: illegal boolean value %s\n", + expanded_value_buffer.get_data(expanded_value_buffer.get_data_length())); +#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("ERROR: CONFIG: illegal boolean value %s\n"), + expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()))); + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field); + } + + status = value_data->set_copy_of_buffer( + &uint_value, + sizeof(uint_value)); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + else if (type == eap_configure_type_string) + { + status = value_data->set_copy_of_buffer( + &expanded_value_buffer); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + else if (type == eap_configure_type_hex_data) + { + status = remove_spaces(&expanded_value_buffer); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + u8_t * cursor = expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()); + const u8_t * const cursor_end = cursor + expanded_value_buffer.get_data_length(); + + while(cursor < cursor_end) + { + u8_t hex_byte = 0; + cursor = read_hex_byte( + cursor, + cursor_end, + &hex_byte); + if (cursor == 0) + { + break; + } + + status = value_data->add_data(&hex_byte, sizeof(hex_byte)); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + } + else if (type == eap_configure_type_u32array) + { + status = remove_spaces(&expanded_value_buffer); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + u8_t * cursor = expanded_value_buffer.get_data(expanded_value_buffer.get_data_length()); + const u8_t * const cursor_end = cursor + expanded_value_buffer.get_data_length(); + + while(cursor < cursor_end) + { + u32_t integer = 0; + cursor = read_u32_t( + cursor, + cursor_end, + &integer); + if (cursor == 0) + { + break; + } + + status = value_data->add_data(&integer, sizeof(integer)); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + } + else + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); + } + + return EAP_STATUS_RETURN(m_am_tools, status); +} + + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::store_configure( + abs_eap_am_file_input_c * const file, + const eap_variable_data_c * const line, + eap_core_map_c * const config_map) +{ + eap_status_e status = eap_status_process_general_error; + + eap_variable_data_c name_buffer(m_am_tools); + if (name_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_variable_data_c value_buffer(m_am_tools); + if (value_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_variable_data_c value_data(m_am_tools); + if (value_data.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + + status = name_buffer.set_buffer_length(MAX_LINE_LENGTH); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + name_buffer.set_data_length(0ul); + + status = value_buffer.set_buffer_length(MAX_LINE_LENGTH); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + value_buffer.set_data_length(0ul); + + eap_configure_type_e type = eap_configure_type_none; + + if (line->compare( + EAP_FILECONFIG_SECTION_END, + EAP_FILECONFIG_SECTION_END_LENGTH) == 0) + { + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: section ends.\n"))); + return EAP_STATUS_RETURN(m_am_tools, eap_status_section_ends); + } + + status = cnf_get_string( + line, + &name_buffer, + &value_buffer, + &type); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + + if (name_buffer.compare_length( + EAP_FILECONFIG_SECTION, + EAP_FILECONFIG_SECTION_LENGTH, + EAP_FILECONFIG_SECTION_LENGTH) == 0) + { + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: section %s.\n"), + name_buffer.get_data(name_buffer.get_data_length()))); + + status = name_buffer.set_start_offset(EAP_FILECONFIG_SECTION_LENGTH); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + eap_core_map_c * const section_map + = new eap_core_map_c< + eap_config_value_c, + abs_eap_core_map_c, + eap_variable_data_c>(m_am_tools, this); + + eap_automatic_variable_c > + automatic_section_map(m_am_tools, section_map); + + if (section_map == 0 + || section_map->get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = read_section(file, section_map); + if (status == eap_status_section_ends) + { + // Add subsection. + eap_config_value_c * config = new eap_config_value_c(m_am_tools); + + eap_automatic_variable_c + automatic_config(m_am_tools, config); + + if (config == 0 + || config->get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + config->set_type(eap_configure_type_subsection); + + config->set_subsection(section_map); + automatic_section_map.do_not_free_variable(); + + status = convert_value( + &m_config_map, // Note here we use the global name space. + &value_buffer, + type, + &value_data); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + { + // selector of the section is :. + // section:example=string:match => example:match + status = name_buffer.add_data( + EAP_FILECONFIG_SECTION_SEPARATOR, + EAP_FILECONFIG_SECTION_SEPARATOR_LENGTH); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = name_buffer.add_data(&value_data); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = name_buffer.add_end_null(); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + + eap_variable_data_c selector(m_am_tools); + if (selector.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = selector.set_copy_of_buffer( + name_buffer.get_data(), + name_buffer.get_data_length()); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = config_map->add_handler(&selector, config); + if (status == eap_status_ok) + { + automatic_config.do_not_free_variable(); + } + else if (status == eap_status_handler_exists_error) + { + // This is dublicate subsection. + // We will skip this. + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("ERROR: CONFIG: section %s is already defined.\n"), + name_buffer.get_data(name_buffer.get_data_length()))); + + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); + } + else if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: subsection name"), + name_buffer.get_data(), + name_buffer.get_data_length())); + + return EAP_STATUS_RETURN(m_am_tools, status); + } + else + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + else + { + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_CONFIGURE_DATA, + (EAPL("CONFIG: check subsection %s.\n"), + name_buffer.get_data(name_buffer.get_data_length()))); + + eap_configuration_field_template_c * const tmp_name + = new eap_configuration_field_template_c; + + eap_automatic_variable_c > + automatic_tmp_name(m_am_tools, tmp_name); + + if (tmp_name == 0 + || tmp_name->get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = tmp_name->set_fields( + m_am_tools, + name_buffer.get_data(name_buffer.get_data_length()), + type, + false); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + eap_variable_data_c check(m_am_tools); + if (check.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = read_configure( + config_map, + tmp_name->get_field(), + &check, + &type, + true); + if (status == eap_status_ok) + { + status = name_buffer.add_end_null(); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + // This subsection is already defined. +#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("WARNING: CONFIG: subsection %s is already defined.\n", + name_buffer.get_data(name_buffer.get_data_length())); +#endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("WARNING: CONFIG: subsection %s is already defined.\n"), + name_buffer.get_data(name_buffer.get_data_length()))); + + // We will skip the dublicate section. + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); + } + + //------------------------------------------------------------------------------- + + eap_config_value_c * config = new eap_config_value_c(m_am_tools); + + eap_automatic_variable_c + automatic_config(m_am_tools, config); + + if (config == 0 + || config->get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + config->set_type(type); + + status = convert_value( + &m_config_map, // Note here we use the global name space. + &value_buffer, + type, + &value_data); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = config->get_data()->set_copy_of_buffer( + &value_data); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + eap_variable_data_c selector(m_am_tools); + if (selector.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = selector.set_copy_of_buffer( + tmp_name->get_field()->get_field(), + tmp_name->get_field()->get_field_length()); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = config_map->add_handler(&selector, config); + if (status == eap_status_ok) + { + automatic_config.do_not_free_variable(); + } + else //if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: option added"), + tmp_name->get_field()->get_field(), + tmp_name->get_field()->get_field_length())); + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: data"), + config->get_data()->get_data(), + config->get_data()->get_data_length())); + + //----------------------------------------------------------------------------- + + } + + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +eap_status_e eap_file_config_c::find_rvalue( + const eap_variable_data_c * const config_param, + bool * const read_env_value, + eap_variable_data_c * const param_name, + eap_variable_data_c * const param_value + ) +{ + const u8_t * rvalue = 0; + const u8_t *env_value = 0; + + if (config_param == 0 + || read_env_value == 0 + || param_name == 0 + || param_value == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + const u8_t * const param = config_param->get_data(config_param->get_data_length()); + if (param == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + const u8_t * const param_end + = config_param->get_data(config_param->get_data_length()) + + config_param->get_data_length(); + if (param_end == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + for (rvalue = param; *rvalue; rvalue++) + { + if (*rvalue == '=') + { + break; + } + } + + if (*rvalue == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + // Check are there defined environment variable to override the file configuration. + { + // backup spaces. + const u8_t *tmp_param_end = rvalue; + + for (tmp_param_end-- + ; m_am_tools->isspace(*tmp_param_end) + || *tmp_param_end == '\r' + || *tmp_param_end == '\n' + || *tmp_param_end == '=' + ; tmp_param_end--) + { + /* empty */ + } + + tmp_param_end++; + u32_t length = tmp_param_end - param; + + + eap_status_e status = param_name->add_data(param, length); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + status = param_name->add_end_null(); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + eap_variable_data_c env_value_buffer(m_am_tools); + if (env_value_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_status_e env_status = m_am_tools->getenv( + param_name, + &env_value_buffer); + if (env_status == eap_status_ok) + { + env_value = env_value_buffer.get_data(env_value_buffer.get_data_length()); + } + else + { + env_value = 0; + } + + if (env_value != 0) + { + rvalue = env_value; + length = m_am_tools->strlen(reinterpret_cast(rvalue)); + *read_env_value = true; + } + else + { + rvalue = tmp_param_end; + + for (; *rvalue; rvalue++) + { + if (*rvalue == '=') + { + break; + } + } + + for (rvalue++; m_am_tools->isspace(*rvalue) || *rvalue == '\r' || *rvalue == '\n'; rvalue++){ + /* empty */ + } + + if (*rvalue == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + length = param_end - rvalue; + } + + // There is overriding environment variable. + status = param_value->set_copy_of_buffer(rvalue, length); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + status = param_value->add_end_null(); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::cnf_parse_value( + const eap_variable_data_c * const found_type_value, + const eap_variable_data_c * const found_type_name, + eap_configure_type_e * const parsed_type, + eap_variable_data_c * const parsed_type_value, + const bool is_environment_variable) +{ + if (found_type_value == 0 + || found_type_name == 0 + || parsed_type == 0 + || parsed_type_value == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + *parsed_type = eap_configure_type_none; + + u32_t ind; + for (ind = 0u; ind < sizeof(eap_configure_type_id)/sizeof(eap_configure_type_id[0]); ind++) + { + if (!m_am_tools->memcmp( + eap_configure_type_id[ind].id, + found_type_value->get_data(found_type_value->get_data_length()), + eap_configure_type_id[ind].id_length)) + { + *parsed_type = eap_configure_type_id[ind].type; + break; + } + } + + u32_t value_length = found_type_value->get_data_length(); + + eap_variable_data_c tmp_buffer(m_am_tools); + if (tmp_buffer.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_status_e status = tmp_buffer.set_buffer_length(MAX_LINE_LENGTH); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + tmp_buffer.set_data_length(MAX_LINE_LENGTH); + + u8_t * const tmp_value_buffer = tmp_buffer.get_buffer(MAX_LINE_LENGTH); + if (tmp_value_buffer == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + const u8_t * used_type_value = found_type_value->get_data(found_type_value->get_data_length()); + if (used_type_value == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + if (*parsed_type == eap_configure_type_none) + { + // No type defined. + if (is_environment_variable == true) + { + // Environment variable without type is handled as a string type. + *parsed_type = eap_configure_type_string; + ind = *parsed_type; + m_am_tools->memmove( + tmp_value_buffer, + eap_configure_type_id[ind].id, + eap_configure_type_id[ind].id_length); + m_am_tools->memmove( + tmp_value_buffer+eap_configure_type_id[ind].id_length, + found_type_value->get_data(found_type_value->get_data_length()), + value_length); + value_length = eap_configure_type_id[ind].id_length+value_length; + tmp_value_buffer[value_length] = 0; + used_type_value = tmp_value_buffer; + } + else + { + #if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("ERROR: CONFIG: no subsection type: %s=%s\n", + found_type_name->get_data(found_type_name->get_data_length()), + found_type_value->get_data(found_type_value->get_data_length())); + #endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("ERROR: CONFIG: no subsection type: %s=%s\n"), + found_type_name->get_data(found_type_name->get_data_length()), + found_type_value->get_data(found_type_value->get_data_length()))); + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field); + } + } + + + const u8_t * value_end = used_type_value+value_length; + + // Remove separator and spaces. + for (value_end-- + ; used_type_value < value_end + && (m_am_tools->isspace(*value_end) + || *value_end == '=' + || *value_end == '\r' + || *value_end == '\n') + ; value_end--) + { + /* empty */ + --value_length; + } + ++value_end; + + const u32_t tmp_length = value_end - used_type_value; + + u32_t len = tmp_length - eap_configure_type_id[ind].id_length; + + status = parsed_type_value->add_data( + used_type_value+eap_configure_type_id[ind].id_length, + len); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = parsed_type_value->add_end_null(); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + if (is_environment_variable == true) + { + #if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("CONFIG: %s=%s%s; from environment variable\n", + found_type_name->get_data(found_type_name->get_data_length()), + eap_configure_type_id[ind].id, + parsed_type_value->get_data(parsed_type_value->get_data_length())); + #endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: %s=%s%s; from environment variable\n"), + found_type_name->get_data(found_type_name->get_data_length()), + eap_configure_type_id[ind].id, + parsed_type_value->get_data(parsed_type_value->get_data_length()))); + } + else + { + #if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("CONFIG: %s=%s%s\n", + found_type_name->get_data(found_type_name->get_data_length()), + eap_configure_type_id[ind].id, + parsed_type_value->get_data(parsed_type_value->get_data_length())); + #endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: %s=%s%s\n"), + found_type_name->get_data(found_type_name->get_data_length()), + eap_configure_type_id[ind].id, + parsed_type_value->get_data(parsed_type_value->get_data_length()))); + } + + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::cnf_get_string( + const eap_variable_data_c * const param, + eap_variable_data_c * const param_name, + eap_variable_data_c * const param_value, + eap_configure_type_e * const type) +{ + if (param == 0 + || param_name == 0 + || param_value == 0 + || type == 0) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + bool env_value = false; + + *type = eap_configure_type_none; + + // Returned value could be pointer to environment value. + // Do not modify returned value. + eap_status_e status = find_rvalue( + param, + &env_value, + param_name, + param_value + ); + + if (status != eap_status_ok) + { + #if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + printf("ERROR: CONFIG: illegal subsection: %s\n", + param->get_data(param->get_data_length())); + #endif //#if defined(EAP_FILE_CONFIG_USE_CONSOLE_PRINTS) + + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("ERROR: CONFIG: illegal subsection: %s\n"), + param->get_data(param->get_data_length()))); + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field); + } + + eap_variable_data_c parsed_value(m_am_tools); + if (parsed_value.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = cnf_parse_value( + param_value, + param_name, + type, + &parsed_value, + env_value); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = param_value->set_copy_of_buffer(&parsed_value); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = param_value->add_end_null(); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_subsections( + abs_eap_am_file_input_c * const file, + eap_core_map_c * const config_map) +{ + eap_variable_data_c line(m_am_tools); + if (line.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_status_e status = eap_status_ok; + + // This sets the pre-allocated buffer. + status = line.set_buffer_length(MAX_LINE_LENGTH); + + for (;status == eap_status_ok;) + { + status = get_subsect(file, &line); + if (status == eap_status_end_of_file) + { + // End of file reached. + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); + } + else if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = store_configure(file, &line, config_map); + } + + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_section( + abs_eap_am_file_input_c * const file, + eap_core_map_c * const config_map) +{ + eap_variable_data_c line(m_am_tools); + if (line.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_status_e status = eap_status_ok; + + // This sets the pre-allocated buffer. + status = line.set_buffer_length(MAX_LINE_LENGTH); + + while (status == eap_status_ok) + { + status = get_subsect(file, &line); + if (status == eap_status_end_of_file) + { + // End of file reached. + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); + } + else if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + if (line.compare( + EAP_FILECONFIG_SECTION_START, + EAP_FILECONFIG_SECTION_START_LENGTH) == 0) + { + // Starts new section block. + status = read_subsections( + file, + config_map); + + return EAP_STATUS_RETURN(m_am_tools, status); + } + else + { + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("ERROR: CONFIG: section start '{' is missing.\n"))); + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field); + } + } + + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::remove_spaces(eap_variable_data_c * const buffer) +{ + eap_variable_data_c tmp(m_am_tools); + if (tmp.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + eap_status_e status(eap_status_ok); + + for (u32_t ind = 0ul; ind < buffer->get_data_length(); ind++) + { + u8_t * const character = buffer->get_data_offset(ind, sizeof(u8_t)); + if (character == 0) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + + if (m_am_tools->isspace(*character) == false) + { + status = tmp.add_data(character, sizeof(*character)); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + } // for() + + status = buffer->set_copy_of_buffer(&tmp); + + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::remove_leading_spaces( + eap_variable_data_c * const line) +{ + if (line->get_data_length() == 0) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); + } + + u8_t * const begin = line->get_data(line->get_data_length()); + if(begin == 0) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); + } + + for (u32_t ind = 0; ind < line->get_data_length(); ind++) + { + if (begin[ind] != ' ' + && begin[ind] != '\t') + { + eap_status_e status = line->set_start_offset(ind); + if (status != eap_status_ok) + { + return EAP_STATUS_RETURN(m_am_tools, status); + } + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); + } + } + + return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::file_read_line( + abs_eap_am_file_input_c * const file, + eap_variable_data_c * const line) +{ + eap_status_e status(eap_status_ok); + bool line_continues(true); + + eap_variable_data_c tmp_line(m_am_tools); + if (tmp_line.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + const u32_t TMP_LINE_BUFFER_INITIAL_LENGTH = 256ul; + + status = tmp_line.set_buffer_length(TMP_LINE_BUFFER_INITIAL_LENGTH); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + + // This is small optimization that does not free the old buffer. + status = line->reset_start_offset_and_data_length(); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + + do + { + status = tmp_line.reset_start_offset_and_data_length(); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = file->file_read_line(&tmp_line); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_CONFIGURE_DATA, + (EAPL("Configure line"), + tmp_line.get_data(), + tmp_line.get_data_length())); + + status = remove_leading_spaces(&tmp_line); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_CONFIGURE_DATA, + (EAPL("No spaces line"), + tmp_line.get_data(), + tmp_line.get_data_length())); + + if (tmp_line.get_data_length() > 0ul) + { + u8_t * last_char = tmp_line.get_buffer_offset( + tmp_line.get_data_length() - 1ul, + sizeof(u8_t)); + + if (last_char != 0 + && *last_char == '\\') + { + // If the last character in the line is '\' then the line continues to the next line. + tmp_line.set_data_length(tmp_line.get_data_length() - 1ul); + } + else + { + line_continues = false; + } + } + else + { + line_continues = false; + } + + status = line->add_data(&tmp_line); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + } while(line_continues == true); + + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_CONFIGURE_DATA, + (EAPL("Configure line"), + tmp_line.get_data(), + tmp_line.get_data_length())); + + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::get_subsect( + abs_eap_am_file_input_c * const file, + eap_variable_data_c * const line) +{ + if( file == 0 + || line == 0) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); + } + + eap_status_e status(eap_status_ok); + + for(;status == eap_status_ok;) + { + status = file_read_line(file, line); + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_CONFIGURE_DATA, + (EAPL("Configure line"), + line->get_data(line->get_data_length()), + line->get_data_length())); + + // error or end of file + if(status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + status = remove_leading_spaces(line); + if(status != eap_status_ok) + { + // Skip this error. + status = eap_status_ok; + continue; + } + + // too short line, ignore + if(line->get_data_length() < 1ul) + { + continue; + } + + u8_t * const result = line->get_data(line->get_data_length()); + if(result == 0) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); + } + + // ignore the lines starting with newline, space, tab or '#' + if ((*result == '\r') + || (*result == '\n') + || (*result == ' ') + || (*result == '\t') + || (*result == '#')) + { + continue; + } + else + { + // OK we get a line. + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_configure( + eap_core_map_c * const config_map, + const eap_configuration_field_c * const field, + eap_variable_data_c* const data, + eap_configure_type_e * const configuration_data_type, + const bool existence_test) +{ + eap_status_e status = eap_status_process_general_error; + + eap_variable_data_c selector(m_am_tools); + if (selector.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + status = selector.set_buffer( + field->get_field(), + field->get_field_length(), + false, + false); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + eap_config_value_c *config = config_map->get_handler(&selector); + + if (config != 0) + { + status = data->set_copy_of_buffer(config->get_data()); + + if (status == eap_status_ok) + { + *configuration_data_type = config->get_type(); + } + else + { + *configuration_data_type = eap_configure_type_none; + } + } + else + { + if (existence_test == false) + { + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("WARNING: CONFIG: unknown option"), + field->get_field(), + field->get_field_length())); + } + status = eap_status_illegal_configure_field; + } + + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return status; // Here EAP_STATUS_RETURN() macro is too noisy. +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_configure( + const eap_configuration_field_c * const field, + eap_variable_data_c* const data, + eap_core_map_c * const config_map, + const bool check_subsection_when_true) +{ + eap_status_e status = eap_status_process_general_error; + + eap_variable_data_c selector(m_am_tools); + if (selector.get_is_valid() == false) + { + return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); + } + + if (check_subsection_when_true == true + && field->get_subsection() != 0) + { + status = selector.set_buffer( + field->get_subsection()); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: finds subsection name"), + field->get_subsection()->get_data(), + field->get_subsection()->get_data_length())); + + eap_config_value_c *config = config_map->get_handler(&selector); + + if (config != 0) + { + if (check_subsection_when_true == true + && config->get_type() == eap_configure_type_subsection) + { + if (config->get_subsection() != 0) + { + status = read_configure( + field, + data, + config->get_subsection(), + false); + if (status == eap_status_ok) + { + // OK, section configuration found. + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + } + else + { + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("WARNING: CONFIG: subsection not found"), + field->get_field(), + field->get_field_length())); + } + } + } + else + { + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("WARNING: CONFIG: subsection not found"), + field->get_field(), + field->get_field_length())); + } + } + + + + { + status = selector.set_buffer( + field->get_field(), + field->get_field_length(), + false, + false); + if (status != eap_status_ok) + { + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); + } + + eap_config_value_c *config = config_map->get_handler(&selector); + + if (config != 0) + { + if (field->get_type() != config->get_type()) + { + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("WARNING: CONFIG: option type failed: required %d != actual %d\n"), + field->get_type(), + config->get_type())); + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("WARNING: CONFIG: rear option type failed: %s\n"), + field->get_field())); + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_type); + } + + status = data->set_copy_of_buffer(config->get_data()); + + EAP_TRACE_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("CONFIG: value read from eap_file_config_c: %s\n"), + field->get_field())); + + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("value"), + data->get_data(), + data->get_data_length())); + } + else + { + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("WARNING: CONFIG: option not found"), + field->get_field(), + field->get_field_length())); + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field); + } + + } + + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//----------------------------------------------------------------- + +EAP_FUNC_EXPORT eap_status_e eap_file_config_c::read_configure( + const eap_configuration_field_c * const field, + eap_variable_data_c* const data) +{ + EAP_TRACE_DATA_DEBUG( + m_am_tools, + TRACE_FLAGS_DEFAULT, + (EAPL("eap_file_config_c::read_configure()"), + field->get_field(), + field->get_field_length())); + + eap_status_e status = read_configure( + field, + data, + &m_config_map, + true); + + EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); + return EAP_STATUS_RETURN(m_am_tools, status); +} + +//-----------------------------------------------------------------