|  |  |  | @@ -67,13 +67,17 @@ static void *geoloc_location_alloc(const char *name) | 
		
	
		
			
				|  |  |  |  | 	return location; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | CONFIG_ENUM(profile, pidf_element) | 
		
	
		
			
				|  |  |  |  | CONFIG_ENUM(profile, precedence) | 
		
	
		
			
				|  |  |  |  | CONFIG_VAR_LIST(profile, location_refinement) | 
		
	
		
			
				|  |  |  |  | CONFIG_VAR_LIST(profile, location_variables) | 
		
	
		
			
				|  |  |  |  | CONFIG_VAR_LIST(profile, usage_rules) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | CONFIG_ENUM_HANDLER(profile, format) | 
		
	
		
			
				|  |  |  |  | CONFIG_ENUM_TO_STR(profile, format) | 
		
	
		
			
				|  |  |  |  | CONFIG_VAR_LIST(profile, location_info) | 
		
	
		
			
				|  |  |  |  | CONFIG_VAR_LIST(profile, confidence) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static void geoloc_profile_destructor(void *obj) { | 
		
	
		
			
				|  |  |  |  | 	struct ast_geoloc_profile *profile = obj; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -81,6 +85,8 @@ static void geoloc_profile_destructor(void *obj) { | 
		
	
		
			
				|  |  |  |  | 	ast_variables_destroy(profile->location_refinement); | 
		
	
		
			
				|  |  |  |  | 	ast_variables_destroy(profile->location_variables); | 
		
	
		
			
				|  |  |  |  | 	ast_variables_destroy(profile->usage_rules); | 
		
	
		
			
				|  |  |  |  | 	ast_variables_destroy(profile->location_info); | 
		
	
		
			
				|  |  |  |  | 	ast_variables_destroy(profile->confidence); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static void *geoloc_profile_alloc(const char *name) | 
		
	
	
		
			
				
					
					|  |  |  | @@ -94,60 +100,83 @@ static void *geoloc_profile_alloc(const char *name) | 
		
	
		
			
				|  |  |  |  | 	return profile; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int geoloc_location_apply_handler(const struct ast_sorcery *sorcery, void *obj) | 
		
	
		
			
				|  |  |  |  | static enum ast_geoloc_validate_result validate_location_info(const char *id, | 
		
	
		
			
				|  |  |  |  | 	enum ast_geoloc_format format, struct ast_variable *location_info) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	struct ast_geoloc_location *location = obj; | 
		
	
		
			
				|  |  |  |  | 	const char *location_id = ast_sorcery_object_get_id(location); | 
		
	
		
			
				|  |  |  |  | 	enum ast_geoloc_validate_result result; | 
		
	
		
			
				|  |  |  |  | 	const char *failed; | 
		
	
		
			
				|  |  |  |  | 	const char *uri; | 
		
	
		
			
				|  |  |  |  | 	enum ast_geoloc_validate_result result; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	switch (location->format) { | 
		
	
		
			
				|  |  |  |  | 	switch (format) { | 
		
	
		
			
				|  |  |  |  | 	case AST_GEOLOC_FORMAT_NONE: | 
		
	
		
			
				|  |  |  |  | 	case AST_GEOLOC_FORMAT_LAST: | 
		
	
		
			
				|  |  |  |  | 		ast_log(LOG_ERROR, "Location '%s' must have a format\n", location_id); | 
		
	
		
			
				|  |  |  |  | 		ast_log(LOG_ERROR, "Location '%s' must have a format\n", id); | 
		
	
		
			
				|  |  |  |  | 		return -1; | 
		
	
		
			
				|  |  |  |  | 	case AST_GEOLOC_FORMAT_CIVIC_ADDRESS: | 
		
	
		
			
				|  |  |  |  | 		result = ast_geoloc_civicaddr_validate_varlist(location->location_info, &failed); | 
		
	
		
			
				|  |  |  |  | 		result = ast_geoloc_civicaddr_validate_varlist(location_info, &failed); | 
		
	
		
			
				|  |  |  |  | 		if (result != AST_GEOLOC_VALIDATE_SUCCESS) { | 
		
	
		
			
				|  |  |  |  | 			ast_log(LOG_ERROR, "Location '%s' has invalid item '%s' in the location\n", | 
		
	
		
			
				|  |  |  |  | 				location_id, failed); | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 				id, failed); | 
		
	
		
			
				|  |  |  |  | 			return result; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		break; | 
		
	
		
			
				|  |  |  |  | 	case AST_GEOLOC_FORMAT_GML: | 
		
	
		
			
				|  |  |  |  | 		result = ast_geoloc_gml_validate_varlist(location->location_info, &failed); | 
		
	
		
			
				|  |  |  |  | 		result = ast_geoloc_gml_validate_varlist(location_info, &failed); | 
		
	
		
			
				|  |  |  |  | 		if (result != AST_GEOLOC_VALIDATE_SUCCESS) { | 
		
	
		
			
				|  |  |  |  | 			ast_log(LOG_ERROR, "%s for item '%s' in location '%s'\n", | 
		
	
		
			
				|  |  |  |  | 				ast_geoloc_validate_result_to_str(result),	failed, location_id); | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 				ast_geoloc_validate_result_to_str(result),	failed, id); | 
		
	
		
			
				|  |  |  |  | 			return result; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		break; | 
		
	
		
			
				|  |  |  |  | 	case AST_GEOLOC_FORMAT_URI: | 
		
	
		
			
				|  |  |  |  | 		uri = ast_variable_find_in_list(location->location_info, "URI"); | 
		
	
		
			
				|  |  |  |  | 		uri = ast_variable_find_in_list(location_info, "URI"); | 
		
	
		
			
				|  |  |  |  | 		if (!uri) { | 
		
	
		
			
				|  |  |  |  | 			struct ast_str *str = ast_variable_list_join(location->location_info, ",", "=", "\"", NULL); | 
		
	
		
			
				|  |  |  |  | 			struct ast_str *str = ast_variable_list_join(location_info, ",", "=", "\"", NULL); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			ast_log(LOG_ERROR, "Geolocation location '%s' format is set to '%s' but no 'URI' was found in location parameter '%s'\n", | 
		
	
		
			
				|  |  |  |  | 				location_id, format_names[AST_GEOLOC_FORMAT_URI], ast_str_buffer(str)); | 
		
	
		
			
				|  |  |  |  | 				id, format_names[AST_GEOLOC_FORMAT_URI], ast_str_buffer(str)); | 
		
	
		
			
				|  |  |  |  | 			ast_free(str); | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 			return AST_GEOLOC_VALIDATE_NOT_ENOUGH_VARNAMES; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		break; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (!ast_strlen_zero(location->location_source)) { | 
		
	
		
			
				|  |  |  |  | 	return AST_GEOLOC_VALIDATE_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int validate_location_source(const char *id, const char *location_source) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (!ast_strlen_zero(location_source)) { | 
		
	
		
			
				|  |  |  |  | 		struct ast_sockaddr loc_source_addr; | 
		
	
		
			
				|  |  |  |  | 		int rc = ast_sockaddr_parse(&loc_source_addr, location->location_source, PARSE_PORT_FORBID); | 
		
	
		
			
				|  |  |  |  | 		int rc = ast_sockaddr_parse(&loc_source_addr, location_source, PARSE_PORT_FORBID); | 
		
	
		
			
				|  |  |  |  | 		if (rc == 1) { | 
		
	
		
			
				|  |  |  |  | 			ast_log(LOG_ERROR, "Geolocation location '%s' location_source '%s' must be a FQDN." | 
		
	
		
			
				|  |  |  |  | 				" RFC8787 expressly forbids IP addresses.\n", | 
		
	
		
			
				|  |  |  |  | 				location_id, location->location_source); | 
		
	
		
			
				|  |  |  |  | 				id, location_source); | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static int geoloc_location_apply_handler(const struct ast_sorcery *sorcery, void *obj) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	struct ast_geoloc_location *location = obj; | 
		
	
		
			
				|  |  |  |  | 	const char *location_id = ast_sorcery_object_get_id(location); | 
		
	
		
			
				|  |  |  |  | 	enum ast_geoloc_validate_result result; | 
		
	
		
			
				|  |  |  |  | 	int rc = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	result = validate_location_info(location_id, location->format, location->location_info); | 
		
	
		
			
				|  |  |  |  | 	if (result != AST_GEOLOC_VALIDATE_SUCCESS) { | 
		
	
		
			
				|  |  |  |  | 		return -1; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	rc = validate_location_source(location_id, location->location_source); | 
		
	
		
			
				|  |  |  |  | 	if (rc != 0) { | 
		
	
		
			
				|  |  |  |  | 		return -1; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -156,48 +185,52 @@ static int geoloc_profile_apply_handler(const struct ast_sorcery *sorcery, void | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	struct ast_geoloc_profile *profile = obj; | 
		
	
		
			
				|  |  |  |  | 	struct ast_geoloc_location *location; | 
		
	
		
			
				|  |  |  |  | 	const char *profile_id = ast_sorcery_object_get_id(profile); | 
		
	
		
			
				|  |  |  |  | 	const char *failed; | 
		
	
		
			
				|  |  |  |  | 	const char *id = ast_sorcery_object_get_id(profile); | 
		
	
		
			
				|  |  |  |  | 	enum ast_geoloc_validate_result result; | 
		
	
		
			
				|  |  |  |  | 	enum ast_geoloc_format format; | 
		
	
		
			
				|  |  |  |  | 	int rc = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (ast_strlen_zero(profile->location_reference)) { | 
		
	
		
			
				|  |  |  |  | 		if (profile->location_refinement || | 
		
	
		
			
				|  |  |  |  | 			profile->location_variables) { | 
		
	
		
			
				|  |  |  |  | 			ast_log(LOG_ERROR, "Profile '%s' can't have location_refinement or location_variables without a location_reference", | 
		
	
		
			
				|  |  |  |  | 				profile_id); | 
		
	
		
			
				|  |  |  |  | 	if (!ast_strlen_zero(profile->location_reference)) { | 
		
	
		
			
				|  |  |  |  | 		if (profile->location_info || | 
		
	
		
			
				|  |  |  |  | 			profile->format != AST_GEOLOC_FORMAT_NONE) { | 
		
	
		
			
				|  |  |  |  | 			ast_log(LOG_ERROR, "Profile '%s' can't have location_reference and location_info or format at the same time", | 
		
	
		
			
				|  |  |  |  | 				id); | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		return 0; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	location = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", profile->location_reference); | 
		
	
		
			
				|  |  |  |  | 	if (!location) { | 
		
	
		
			
				|  |  |  |  | 		ast_log(LOG_ERROR, "Profile '%s' has a location_reference '%s' that doesn't exist", | 
		
	
		
			
				|  |  |  |  | 			profile_id, profile->location_reference); | 
		
	
		
			
				|  |  |  |  | 	if (profile->location_info) { | 
		
	
		
			
				|  |  |  |  | 		result = validate_location_info(id, profile->format, profile->location_info); | 
		
	
		
			
				|  |  |  |  | 		if (result != AST_GEOLOC_VALIDATE_SUCCESS) { | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (profile->location_refinement) { | 
		
	
		
			
				|  |  |  |  | 		switch (location->format) { | 
		
	
		
			
				|  |  |  |  | 		case AST_GEOLOC_FORMAT_NONE: | 
		
	
		
			
				|  |  |  |  | 		case AST_GEOLOC_FORMAT_LAST: | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 		case AST_GEOLOC_FORMAT_CIVIC_ADDRESS: | 
		
	
		
			
				|  |  |  |  | 			result = ast_geoloc_civicaddr_validate_varlist(profile->location_refinement, &failed); | 
		
	
		
			
				|  |  |  |  | 			if (result != AST_GEOLOC_VALIDATE_SUCCESS) { | 
		
	
		
			
				|  |  |  |  | 				ast_log(LOG_ERROR, "Profile '%s' error: %s: for item '%s' in the location_refinement\n", | 
		
	
		
			
				|  |  |  |  | 					profile_id,	ast_geoloc_validate_result_to_str(result), failed); | 
		
	
		
			
				|  |  |  |  | 				ao2_ref(location, -1); | 
		
	
		
			
				|  |  |  |  | 		rc = validate_location_source(id, profile->location_source); | 
		
	
		
			
				|  |  |  |  | 		if (rc != 0) { | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 		case AST_GEOLOC_FORMAT_GML: | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 		case AST_GEOLOC_FORMAT_URI: | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		return 0; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (!ast_strlen_zero(profile->location_reference)) { | 
		
	
		
			
				|  |  |  |  | 		location = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", profile->location_reference); | 
		
	
		
			
				|  |  |  |  | 		if (!location) { | 
		
	
		
			
				|  |  |  |  | 			ast_log(LOG_ERROR, "Profile '%s' has a location_reference '%s' that doesn't exist", | 
		
	
		
			
				|  |  |  |  | 				id, profile->location_reference); | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		format = location->format; | 
		
	
		
			
				|  |  |  |  | 		ao2_ref(location, -1); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (profile->location_refinement) { | 
		
	
		
			
				|  |  |  |  | 		result = validate_location_info(id, format, profile->location_refinement); | 
		
	
		
			
				|  |  |  |  | 		if (result != AST_GEOLOC_VALIDATE_SUCCESS) { | 
		
	
		
			
				|  |  |  |  | 			return -1; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -217,7 +250,6 @@ static char *geoloc_config_list_locations(struct ast_cli_entry *e, int cmd, stru | 
		
	
		
			
				|  |  |  |  | 	int using_regex = 0; | 
		
	
		
			
				|  |  |  |  | 	char *result = CLI_SUCCESS; | 
		
	
		
			
				|  |  |  |  | 	int ret = 0; | 
		
	
		
			
				|  |  |  |  | 	char *format_name; | 
		
	
		
			
				|  |  |  |  | 	int count = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	switch (cmd) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -285,14 +317,12 @@ static char *geoloc_config_list_locations(struct ast_cli_entry *e, int cmd, stru | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		format_to_str(loc, NULL, &format_name); | 
		
	
		
			
				|  |  |  |  | 		ast_cli(a->fd, "%-46.46s %-13s %-s\n", | 
		
	
		
			
				|  |  |  |  | 			ast_sorcery_object_get_id(loc), | 
		
	
		
			
				|  |  |  |  | 			format_name, | 
		
	
		
			
				|  |  |  |  | 			format_names[loc->format], | 
		
	
		
			
				|  |  |  |  | 			ast_str_buffer(str)); | 
		
	
		
			
				|  |  |  |  | 		ao2_unlock(loc); | 
		
	
		
			
				|  |  |  |  | 		ast_free(str); | 
		
	
		
			
				|  |  |  |  | 		ast_free(format_name); | 
		
	
		
			
				|  |  |  |  | 		count++; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	ao2_iterator_destroy(&iter); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -311,7 +341,6 @@ static char *geoloc_config_list_profiles(struct ast_cli_entry *e, int cmd, struc | 
		
	
		
			
				|  |  |  |  | 	int using_regex = 0; | 
		
	
		
			
				|  |  |  |  | 	char *result = CLI_SUCCESS; | 
		
	
		
			
				|  |  |  |  | 	int ret = 0; | 
		
	
		
			
				|  |  |  |  | 	char *precedence; | 
		
	
		
			
				|  |  |  |  | 	int count = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	switch (cmd) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -368,13 +397,11 @@ static char *geoloc_config_list_profiles(struct ast_cli_entry *e, int cmd, struc | 
		
	
		
			
				|  |  |  |  | 	for (; (profile = ao2_iterator_next(&iter)); ao2_ref(profile, -1)) { | 
		
	
		
			
				|  |  |  |  | 		ao2_lock(profile); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		precedence_to_str(profile, NULL, &precedence); | 
		
	
		
			
				|  |  |  |  | 		ast_cli(a->fd, "%-46.46s %-16s %-s\n", | 
		
	
		
			
				|  |  |  |  | 			ast_sorcery_object_get_id(profile), | 
		
	
		
			
				|  |  |  |  | 			precedence, | 
		
	
		
			
				|  |  |  |  | 			precedence_names[profile->precedence], | 
		
	
		
			
				|  |  |  |  | 			profile->location_reference); | 
		
	
		
			
				|  |  |  |  | 		ao2_unlock(profile); | 
		
	
		
			
				|  |  |  |  | 		ast_free(precedence); | 
		
	
		
			
				|  |  |  |  | 		count++; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	ao2_iterator_destroy(&iter); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -441,7 +468,7 @@ static char *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struc | 
		
	
		
			
				|  |  |  |  | 		return CLI_FAILURE; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	ast_cli(a->fd, "Geolocation Profile Objects:\n\n"); | 
		
	
		
			
				|  |  |  |  | 	ast_cli(a->fd, "Geolocation Profile Objects:\n"); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	iter = ao2_iterator_init(sorted_container, AO2_ITERATOR_UNLINK); | 
		
	
		
			
				|  |  |  |  | 	for (; (profile = ao2_iterator_next(&iter)); ) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -450,26 +477,28 @@ static char *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struc | 
		
	
		
			
				|  |  |  |  | 		struct ast_str *variables_str = NULL; | 
		
	
		
			
				|  |  |  |  | 		struct ast_str *resolved_str = NULL; | 
		
	
		
			
				|  |  |  |  | 		struct ast_str *usage_rules_str = NULL; | 
		
	
		
			
				|  |  |  |  | 		struct ast_str *confidence_str = NULL; | 
		
	
		
			
				|  |  |  |  | 		struct ast_geoloc_eprofile *eprofile = ast_geoloc_eprofile_create_from_profile(profile); | 
		
	
		
			
				|  |  |  |  | 		ao2_ref(profile, -1); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!ast_strlen_zero(eprofile->location_reference)) { | 
		
	
		
			
				|  |  |  |  | 		loc_str = ast_variable_list_join(eprofile->location_info, ",", "=", "\"", NULL); | 
		
	
		
			
				|  |  |  |  | 		resolved_str = ast_variable_list_join(eprofile->effective_location, ",", "=", "\"", NULL); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		refinement_str = ast_variable_list_join(eprofile->location_refinement, ",", "=", "\"", NULL); | 
		
	
		
			
				|  |  |  |  | 		variables_str = ast_variable_list_join(eprofile->location_variables, ",", "=", "\"", NULL); | 
		
	
		
			
				|  |  |  |  | 		usage_rules_str = ast_variable_list_join(eprofile->usage_rules, ",", "=", "\"", NULL); | 
		
	
		
			
				|  |  |  |  | 		confidence_str = ast_variable_list_join(eprofile->confidence, ",", "=", "\"", NULL); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		ast_cli(a->fd, | 
		
	
		
			
				|  |  |  |  | 		ast_cli(a->fd,"\n" | 
		
	
		
			
				|  |  |  |  | 			"id:                      %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"profile_precedence:      %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"pidf_element:            %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_reference:      %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"Location_format:         %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_details:        %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_format:         %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_info:           %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_method:         %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_source:         %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_confidence:     %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_refinement:     %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"location_variables:      %-s\n" | 
		
	
		
			
				|  |  |  |  | 			"allow_routing_use:       %-s\n" | 
		
	
	
		
			
				
					
					|  |  |  | @@ -484,6 +513,8 @@ static char *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struc | 
		
	
		
			
				|  |  |  |  | 			format_names[eprofile->format], | 
		
	
		
			
				|  |  |  |  | 			S_COR(loc_str, ast_str_buffer(loc_str), "<none>"), | 
		
	
		
			
				|  |  |  |  | 			S_OR(eprofile->method, "<none>"), | 
		
	
		
			
				|  |  |  |  | 			S_OR(eprofile->location_source, "<none>"), | 
		
	
		
			
				|  |  |  |  | 			S_COR(confidence_str, ast_str_buffer(confidence_str), "<none>"), | 
		
	
		
			
				|  |  |  |  | 			S_COR(refinement_str, ast_str_buffer(refinement_str), "<none>"), | 
		
	
		
			
				|  |  |  |  | 			S_COR(variables_str, ast_str_buffer(variables_str), "<none>"), | 
		
	
		
			
				|  |  |  |  | 			S_COR(eprofile->allow_routing_use, "yes", "no"), | 
		
	
	
		
			
				
					
					|  |  |  | @@ -499,6 +530,7 @@ static char *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struc | 
		
	
		
			
				|  |  |  |  | 		ast_free(variables_str); | 
		
	
		
			
				|  |  |  |  | 		ast_free(resolved_str); | 
		
	
		
			
				|  |  |  |  | 		ast_free(usage_rules_str); | 
		
	
		
			
				|  |  |  |  | 		ast_free(confidence_str); | 
		
	
		
			
				|  |  |  |  | 		count++; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	ao2_iterator_destroy(&iter); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -643,11 +675,11 @@ int geoloc_config_load(void) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "location", "type", "", OPT_NOOP_T, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "format", AST_GEOLOC_FORMAT_NONE, | 
		
	
		
			
				|  |  |  |  | 		format_handler, format_to_str, NULL, 0, 0); | 
		
	
		
			
				|  |  |  |  | 		location_format_handler, location_format_to_str, NULL, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "location_info", NULL, | 
		
	
		
			
				|  |  |  |  | 		location_info_handler, location_info_to_str, location_info_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 		location_location_info_handler, location_location_info_to_str, location_location_info_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "confidence", NULL, | 
		
	
		
			
				|  |  |  |  | 		confidence_handler, confidence_to_str, confidence_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 		location_confidence_handler, location_confidence_to_str, location_confidence_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "location", "location_source", "", OPT_STRINGFIELD_T, | 
		
	
		
			
				|  |  |  |  | 		0, STRFLDSET(struct ast_geoloc_location, location_source)); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "location", "method", "", OPT_STRINGFIELD_T, | 
		
	
	
		
			
				
					
					|  |  |  | @@ -678,17 +710,17 @@ int geoloc_config_load(void) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "profile", "type", "", OPT_NOOP_T, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "pidf_element", | 
		
	
		
			
				|  |  |  |  | 		pidf_element_names[AST_PIDF_ELEMENT_DEVICE], pidf_element_handler, pidf_element_to_str, NULL, 0, 0); | 
		
	
		
			
				|  |  |  |  | 		pidf_element_names[AST_PIDF_ELEMENT_DEVICE], profile_pidf_element_handler, profile_pidf_element_to_str, NULL, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "profile", "location_reference", "", OPT_STRINGFIELD_T, | 
		
	
		
			
				|  |  |  |  | 		0, STRFLDSET(struct ast_geoloc_profile, location_reference)); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "profile_precedence", "discard_incoming", | 
		
	
		
			
				|  |  |  |  | 		precedence_handler, precedence_to_str, NULL, 0, 0); | 
		
	
		
			
				|  |  |  |  | 		profile_precedence_handler, profile_precedence_to_str, NULL, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "usage_rules", NULL, | 
		
	
		
			
				|  |  |  |  | 		usage_rules_handler, usage_rules_to_str, usage_rules_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 		profile_usage_rules_handler, profile_usage_rules_to_str, profile_usage_rules_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_info_refinement", NULL, | 
		
	
		
			
				|  |  |  |  | 		location_refinement_handler, location_refinement_to_str, location_refinement_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 		profile_location_refinement_handler, profile_location_refinement_to_str, profile_location_refinement_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_variables", NULL, | 
		
	
		
			
				|  |  |  |  | 		location_variables_handler, location_variables_to_str, location_variables_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 		profile_location_variables_handler, profile_location_variables_to_str, profile_location_variables_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "profile", "notes", "", OPT_STRINGFIELD_T, | 
		
	
		
			
				|  |  |  |  | 		0, STRFLDSET(struct ast_geoloc_profile, notes)); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "profile", "allow_routing_use", | 
		
	
	
		
			
				
					
					|  |  |  | @@ -696,6 +728,17 @@ int geoloc_config_load(void) | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "profile", "suppress_empty_ca_elements", | 
		
	
		
			
				|  |  |  |  | 		"no", OPT_BOOL_T, 1, FLDSET(struct ast_geoloc_profile, suppress_empty_ca_elements)); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "format", AST_GEOLOC_FORMAT_NONE, | 
		
	
		
			
				|  |  |  |  | 		profile_format_handler, profile_format_to_str, NULL, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_info", NULL, | 
		
	
		
			
				|  |  |  |  | 		profile_location_info_handler, profile_location_info_to_str, profile_location_info_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "confidence", NULL, | 
		
	
		
			
				|  |  |  |  | 		profile_confidence_handler, profile_confidence_to_str, profile_confidence_dup, 0, 0); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "profile", "location_source", "", OPT_STRINGFIELD_T, | 
		
	
		
			
				|  |  |  |  | 		0, STRFLDSET(struct ast_geoloc_profile, location_source)); | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_object_field_register(geoloc_sorcery, "profile", "method", "", OPT_STRINGFIELD_T, | 
		
	
		
			
				|  |  |  |  | 		0, STRFLDSET(struct ast_geoloc_profile, method)); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	ast_sorcery_load(geoloc_sorcery); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  |   |