mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	
		
			
	
	
		
			152 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			152 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * Asterisk -- An open source telephony toolkit. | ||
|  |  * | ||
|  |  * Copyright (C) 2022, Sangoma Technologies Corporation | ||
|  |  * | ||
|  |  * George Joseph <gjoseph@sangoma.com> | ||
|  |  * | ||
|  |  * See http://www.asterisk.org for more information about
 | ||
|  |  * the Asterisk project. Please do not directly contact | ||
|  |  * any of the maintainers of this project for assistance; | ||
|  |  * the project provides a web site, mailing lists and IRC | ||
|  |  * channels for your use. | ||
|  |  * | ||
|  |  * This program is free software, distributed under the terms of | ||
|  |  * the GNU General Public License Version 2. See the LICENSE file | ||
|  |  * at the top of the source tree. | ||
|  |  */ | ||
|  | 
 | ||
|  | #include "asterisk.h"
 | ||
|  | #include "asterisk/config.h"
 | ||
|  | #include "asterisk/cli.h"
 | ||
|  | #include "asterisk/res_geolocation.h"
 | ||
|  | #include "asterisk/xml.h"
 | ||
|  | #include "geoloc_private.h"
 | ||
|  | 
 | ||
|  | static const char *addr_code_name_entries[] = { | ||
|  | 	"country", | ||
|  | 	"A1", | ||
|  | 	"A2", | ||
|  | 	"A3", | ||
|  | 	"A4", | ||
|  | 	"A5", | ||
|  | 	"A6", | ||
|  | 	"ADDCODE", | ||
|  | 	"BLD", | ||
|  | 	"FLR", | ||
|  | 	"HNO", | ||
|  | 	"HNS", | ||
|  | 	"LMK", | ||
|  | 	"LOC", | ||
|  | 	"NAM", | ||
|  | 	"PC", | ||
|  | 	"PCN", | ||
|  | 	"PLC", | ||
|  | 	"POBOX", | ||
|  | 	"POD", | ||
|  | 	"POM", | ||
|  | 	"PRD", | ||
|  | 	"PRM", | ||
|  | 	"RD", | ||
|  | 	"RD", | ||
|  | 	"RDBR", | ||
|  | 	"RDSEC", | ||
|  | 	"RDSUBBR", | ||
|  | 	"ROOM", | ||
|  | 	"SEAT", | ||
|  | 	"STS", | ||
|  | 	"UNIT", | ||
|  | }; | ||
|  | 
 | ||
|  | static int compare_civicaddr_codes(const void *_a, const void *_b) | ||
|  | { | ||
|  | 	/* See the man page for qsort(3) for an explanation of the casts */ | ||
|  | 	int rc = strcmp(*(const char **)_a, *(const char **)_b); | ||
|  | 	return rc; | ||
|  | } | ||
|  | 
 | ||
|  | int ast_geoloc_civicaddr_is_code_valid(const char *code) | ||
|  | { | ||
|  | 	const char **entry = bsearch(&code, addr_code_name_entries, ARRAY_LEN(addr_code_name_entries), | ||
|  | 		sizeof(const char *), compare_civicaddr_codes); | ||
|  | 	return (entry != NULL); | ||
|  | } | ||
|  | 
 | ||
|  | enum ast_geoloc_validate_result ast_geoloc_civicaddr_validate_varlist( | ||
|  | 	const struct ast_variable *varlist,	const char **result) | ||
|  | { | ||
|  | 	const struct ast_variable *var = varlist; | ||
|  | 	for (; var; var = var->next) { | ||
|  | 		int valid = ast_geoloc_civicaddr_is_code_valid(var->name); | ||
|  | 		if (!valid) { | ||
|  | 			*result = var->name; | ||
|  | 			return AST_GEOLOC_VALIDATE_INVALID_VARNAME; | ||
|  | 		} | ||
|  | 	} | ||
|  | 	return AST_GEOLOC_VALIDATE_SUCCESS; | ||
|  | } | ||
|  | 
 | ||
|  | struct ast_xml_node *geoloc_civicaddr_list_to_xml(const struct ast_variable *resolved_location, | ||
|  | 	const char *ref_string) | ||
|  | { | ||
|  | 	char *lang = NULL; | ||
|  | 	char *s = NULL; | ||
|  | 	struct ast_variable *var; | ||
|  | 	struct ast_xml_node *ca_node; | ||
|  | 	struct ast_xml_node *child_node; | ||
|  | 	int rc = 0; | ||
|  | 	SCOPE_ENTER(3, "%s", ref_string); | ||
|  | 
 | ||
|  | 	lang = (char *)ast_variable_find_in_list(resolved_location, "lang"); | ||
|  | 	if (ast_strlen_zero(lang)) { | ||
|  | 		lang = ast_strdupa(ast_defaultlanguage); | ||
|  | 		for (s = lang; *s; s++) { | ||
|  | 			if (*s == '_') { | ||
|  | 				*s = '-'; | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	ca_node = ast_xml_new_node("civicAddress"); | ||
|  | 	if (!ca_node) { | ||
|  | 		SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create 'civicAddress' XML node\n", ref_string); | ||
|  | 	} | ||
|  | 	rc = ast_xml_set_attribute(ca_node, "lang", lang); | ||
|  | 	if (rc != 0) { | ||
|  | 		ast_xml_free_node(ca_node); | ||
|  | 		SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create 'lang' XML attribute\n", ref_string); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	for (var = (struct ast_variable *)resolved_location; var; var = var->next) { | ||
|  | 		if (ast_strings_equal(var->name, "lang")) { | ||
|  | 			continue; | ||
|  | 		} | ||
|  | 		child_node = ast_xml_new_child(ca_node, var->name); | ||
|  | 		if (!child_node) { | ||
|  | 			ast_xml_free_node(ca_node); | ||
|  | 			SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create '%s' XML node\n", var->name, ref_string); | ||
|  | 		} | ||
|  | 		ast_xml_set_text(child_node, var->value); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	SCOPE_EXIT_RTN_VALUE(ca_node, "%s: Done\n", ref_string); | ||
|  | } | ||
|  | 
 | ||
|  | int geoloc_civicaddr_unload(void) | ||
|  | { | ||
|  | 	return AST_MODULE_LOAD_SUCCESS; | ||
|  | } | ||
|  | 
 | ||
|  | int geoloc_civicaddr_load(void) | ||
|  | { | ||
|  | 	qsort(addr_code_name_entries, ARRAY_LEN(addr_code_name_entries), sizeof(const char *), | ||
|  | 		compare_civicaddr_codes); | ||
|  | 
 | ||
|  | 	return AST_MODULE_LOAD_SUCCESS; | ||
|  | } | ||
|  | 
 | ||
|  | int geoloc_civicaddr_reload(void) | ||
|  | { | ||
|  | 	return AST_MODULE_LOAD_SUCCESS; | ||
|  | } |