diff --git a/conf/autoload_configs/cidlookup.conf.xml b/conf/autoload_configs/cidlookup.conf.xml index 006851510f..a30f9f5c10 100644 --- a/conf/autoload_configs/cidlookup.conf.xml +++ b/conf/autoload_configs/cidlookup.conf.xml @@ -3,6 +3,10 @@ + + + diff --git a/src/mod/applications/mod_cidlookup/mod_cidlookup.c b/src/mod/applications/mod_cidlookup/mod_cidlookup.c index 892a189276..57cebd6ffd 100755 --- a/src/mod/applications/mod_cidlookup/mod_cidlookup.c +++ b/src/mod/applications/mod_cidlookup/mod_cidlookup.c @@ -46,6 +46,8 @@ static char *SYNTAX = "cidlookup status|number [skipurl] [skipcitystate]"; static struct { char *url; + + char *whitepages_apikey; switch_bool_t cache; int cache_expire; @@ -145,6 +147,7 @@ static switch_xml_config_string_options_t config_opt_dsn = {NULL, 0, NULL}; /* a static switch_xml_config_item_t instructions[] = { /* parameter name type reloadable pointer default value options structure */ SWITCH_CONFIG_ITEM_STRING_STRDUP("url", CONFIG_RELOAD, &globals.url, NULL, "http://server.example.com/app?number=${caller_id_number}", "URL for the CID lookup service"), + SWITCH_CONFIG_ITEM_STRING_STRDUP("whitepages-apikey", CONFIG_RELOAD, &globals.whitepages_apikey, NULL, "api key for whitepages.com", "api key for whitepages.com"), SWITCH_CONFIG_ITEM("cache", SWITCH_CONFIG_BOOL, CONFIG_RELOAD, &globals.cache, SWITCH_FALSE, NULL, "true|false", "whether to cache via cidlookup"), SWITCH_CONFIG_ITEM("cache-expire", SWITCH_CONFIG_INT, CONFIG_RELOAD, &globals.cache_expire, (void *)300, NULL, "expire", "seconds to preserve num->name cache"), SWITCH_CONFIG_ITEM_STRING_STRDUP("sql", CONFIG_RELOAD, &globals.sql, "", "sql whre number=${caller_id_number}", "SQL to run if overriding CID"), @@ -286,9 +289,8 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data) return realsize; } -static char *do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, const char *num) { +static char *do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, const char *query) { char *name = NULL; - char *newurl = NULL; CURL *curl_handle = NULL; long httpRes = 0; @@ -298,24 +300,22 @@ static char *do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, co memset(&http_data, 0, sizeof(http_data)); - http_data.max_bytes = 1024; + http_data.max_bytes = 10240; SWITCH_STANDARD_STREAM(http_data.stream); gethostname(hostname, sizeof(hostname)); - newurl = switch_event_expand_headers(event, globals.url); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "url: %s\n", newurl); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "url: %s\n", query); curl_handle = curl_easy_init(); - if (!strncasecmp(newurl, "https", 5)) { + if (!strncasecmp(query, "https", 5)) { curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } curl_easy_setopt(curl_handle, CURLOPT_POST, SWITCH_FALSE); curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); - curl_easy_setopt(curl_handle, CURLOPT_URL, newurl); + curl_easy_setopt(curl_handle, CURLOPT_URL, query); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &http_data); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-cidlookup/1.0"); @@ -331,13 +331,83 @@ static char *do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, co name = switch_core_strdup(pool, http_data.stream.data); } - if (newurl != globals.url) { - switch_safe_free(newurl); - } switch_safe_free(http_data.stream.data); return name; } +static char *do_whitepages_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, switch_bool_t *areaonly) +{ + char *xml_s = NULL; + char *query = NULL; + char *name = NULL; + char *city = NULL; + char *state = NULL; + switch_xml_t xml = NULL; + switch_xml_t node = NULL; + + /* NANPA check */ + if (strlen(num) == 11 && num[0] == '1') { + num++; /* skip past leading 1 */ + } else { + goto done; + } + + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "whitepages-cid", num); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "whitepages-api-key", globals.whitepages_apikey); + + query = switch_event_expand_headers(event, "http://api.whitepages.com/reverse_phone/1.0/?phone=${whitepages-cid};api_key=${whitepages-api-key}"); + xml_s = do_lookup_url(pool, event, query); + + xml = switch_xml_parse_str_dup(xml_s); + + if (!xml) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to parse XML: %s\n", xml_s); + goto done; + } + + *areaonly = SWITCH_FALSE; + + /* try for bizname first */ + node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:business", 0, "wp:businessname", -1); + if (node) { + name = switch_core_strdup(pool, switch_xml_txt(node)); + goto done; + } + + node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:displayname", -1); + if (node) { + name = switch_core_strdup(pool, switch_xml_txt(node)); + goto done; + } + + node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:address", 0, "wp:city", -1); + if (node) { + city = switch_xml_txt(node); + } + + node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:address", 0, "wp:state", -1); + if (node) { + state = switch_xml_txt(node); + } + + if (city || state) { + *areaonly = SWITCH_TRUE; + name = switch_core_sprintf(pool, "%s %s", city ? city : "", state ? state : ""); + } + +done: + + if (query) { + switch_safe_free(query); + } + if (xml) { + switch_xml_free(xml); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "whitepages XML: %s\n", xml_s); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "whitepages name: %s\n", name ? name : "(null)"); + return name; +} + static char *do_db_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, const char *sql) { char *name = NULL; char *newsql = NULL; @@ -362,6 +432,9 @@ static char *do_db_lookup(switch_memory_pool_t *pool, switch_event_t *event, con static char *do_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, switch_bool_t skipurl, switch_bool_t skipcitystate) { char *number = NULL; char *name = NULL; + char *area = NULL; + char *url_query = NULL; + switch_bool_t areaonly = SWITCH_FALSE; number = string_digitsonly(pool, num); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller_id_number", number); @@ -376,7 +449,28 @@ static char *do_lookup(switch_memory_pool_t *pool, switch_event_t *event, const name = check_cache(pool, number); } if (!skipurl && !name) { - name = do_lookup_url(pool, event, number); + name = do_whitepages_lookup(pool, event, number, &areaonly); + if (areaonly) { + if (!skipcitystate) { + area = name; /* preserve if we're not skipping city/state */ + } + name = NULL; /* always clear out name */ + } + if (globals.cache && name) { + set_cache(pool, number, name); + } + } + if (!skipurl && !name) { + url_query = switch_event_expand_headers(event, globals.url); + name = do_lookup_url(pool, event, url_query); + if (url_query != globals.url) { + switch_safe_free(url_query); + } + + /* store and use preserved area info */ + if (!name && area) { + name = area; + } if (globals.cache && name) { set_cache(pool, number, name); }