asterisk/res/res_geolocation/geoloc_civicaddr.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;
}